Example #1
0
 def testDevicePropertiesUpdate(self):
     # Test that updates to the device properties are counted correctly.
     device = self._CreateFakeDevices(n=1)[0]
     self.assertEqual(device.num_updates(), 1)
     new_properties = model.DeviceProperties()
     new_properties.device_info = device
     new_properties.put()
     self.assertEqual(device.num_updates(), 2)
     new_properties = model.DeviceProperties()
     new_properties.device_info = device
     new_properties.put()
     self.assertEqual(device.num_updates(), 3)
Example #2
0
    def PostMeasurement(self, **unused_args):
        """Handler used to post a measurement from a device."""
        if self.request.method.lower() != 'post':
            raise error.BadRequest('Not a POST request.')

        try:
            measurement_list = json.loads(self.request.body)
            logging.info('PostMeasurement: Got %d measurements to write',
                         len(measurement_list))
            for measurement_dict in measurement_list:
                device_info = model.DeviceInfo.get_or_insert(
                    measurement_dict['device_id'])

                # Write new device properties, if present
                if 'properties' in measurement_dict:
                    device_properties = model.DeviceProperties(
                        parent=device_info)
                    device_properties.device_info = device_info
                    properties_dict = measurement_dict['properties']
                    # TODO(wenjiezeng): Sanitize input that contains bad fields
                    util.ConvertFromDict(device_properties, properties_dict)
                    # Don't want the embedded properties in the Measurement object
                    del measurement_dict['properties']
                else:
                    # Get most recent device properties
                    device_properties = device.GetLatestDeviceProperties(
                        device_info, create_new_if_none=True)
                device_properties.put()

                measurement = model.Measurement(parent=device_info)
                util.ConvertFromDict(measurement, measurement_dict)
                measurement.device_properties = device_properties
                measurement.put()
        except Exception, e:
            logging.exception('Got exception posting measurements')
Example #3
0
    def _CreateFakeDevices(self, n=3, extra_info=None):
        """Create fake devices.

    Args:
      n: Number of devices to create.
      extra_info: optional list of dictionaries, where dictionary x
        will be written to the device properties of fake device x.

    Returns:
      A list of the created device objects.
    """
        devices = []
        for dev_num in range(n):
            dev_name = 'fakedevice%d' % dev_num

            new_device = model.DeviceInfo(key_name=dev_name)
            new_device.id = dev_name
            new_device.user = users.User(MobiperfTest.TEST_USER)
            new_device.manufacturer = MobiperfTest.TEST_DEVICE_MANUFACTURER
            new_device.model = MobiperfTest.TEST_DEVICE_MODEL
            new_device.os = MobiperfTest.TEST_DEVICE_OS
            new_device.put()

            properties = model.DeviceProperties()
            properties.device_info = new_device
            properties.app_version = MobiperfTest.TEST_DEVICE_PROPERTIES_APP_VERSION
            properties.os_version = MobiperfTest.TEST_DEVICE_PROPERTIES_OS_VERSION

            if extra_info and extra_info[dev_num]:
                for k, v in extra_info[dev_num].iteritems():
                    setattr(properties, k, v)
            properties.put()
            devices.append(new_device)

        return devices
Example #4
0
 def testDeviceLastUpdateTime(self):
     # Test that DeviceInfo.LastUpdateTime() works as expected.
     device = self._CreateFakeDevices(n=1)[0]
     new_properties = model.DeviceProperties()
     new_properties.device_info = device
     now = datetime.datetime.utcnow()
     new_properties.timestamp = now
     new_properties.put()
     self.assertEqual(device.LastUpdateTime(), now)
Example #5
0
 def testDevicePropertiesCreate(self):
     # Test that a DeviceProperties can be created.
     device = self._CreateFakeDevices(n=1)[0]
     self.assertEqual(1, len(model.DeviceProperties().all().fetch(2)))
     result = device.last_update()
     self.assertEqual(result.device_info.key().name(), 'fakedevice0')
     self.assertEqual(result.device_info.manufacturer,
                      test.MobiperfTest.TEST_DEVICE_MANUFACTURER)
     self.assertEqual(result.os_version,
                      test.MobiperfTest.TEST_DEVICE_PROPERTIES_OS_VERSION)
Example #6
0
  def Checkin(self, **unused_args):
    """Handler for checkin requests."""
    if self.request.method.lower() != 'post':
      url = self.request.get('url')
      if not url:
        raise error.BadRequest('No contrib url.')
      blob = GetContrib(url)
      if not blob:
        raise error.BadRequest('No this contrib in db.')
      self.response.headers['Content-type'] = 'application/java-archive'
      self.response.out.write(blob)
      return
    
    checkin = json.loads(self.request.body)
    logging.info('Got checkin: %s', self.request.body)

    try:
      # Extract DeviceInfo
      device_id = checkin['id']
      logging.info('Checkin from device %s', device_id)
      device_info = model.DeviceInfo.get_or_insert(device_id)

      device_info.user = users.get_current_user()
      # Don't want the embedded properties in the device_info structure
      device_info_dict = dict(checkin)
      del device_info_dict['properties']
      util.ConvertFromDict(device_info, device_info_dict)
      device_info.put()

      # Extract DeviceProperties
      device_properties = model.DeviceProperties(parent=device_info)
      device_properties.device_info = device_info
      util.ConvertFromDict(device_properties, checkin['properties'])
      device_properties.put()

      device_schedule = GetDeviceSchedule(device_properties)
      device_schedule_json = EncodeScheduleAsJson(device_schedule)
      logging.info('Sending checkin response: %s', device_schedule_json)
      self.response.headers['Content-Type'] = 'application/json'
      self.response.out.write(device_schedule_json)

    except Exception, e:
      logging.error('Got exception during checkin: %s', e)
      self.response.headers['Content-Type'] = 'application/json'
      self.response.out.write(json.dumps([]))
Example #7
0
    def Checkin(self, **unused_args):
        """Handler for checkin requests."""
        if self.request.method.lower() != 'post':
            raise error.BadRequest('Not a POST request.')

        checkin = json.loads(self.request.body)
        logging.info('Got checkin: %s', self.request.body)

        try:
            # Change device id such that it is anonymized, but preserve TAC.
            checkin['tac'] = util.GetTypeAllocationCode(checkin['id'])

            # We need the actual id, because we need to make a decision which ue need to take the task.
            # checkin['id'] = util.HashDeviceId(checkin['id'])

            # Extract DeviceInfo.
            device_id = checkin['id']
            logging.info('Checkin from device %s', device_id)
            device_info = model.DeviceInfo.get_or_insert(device_id)

            device_info.user = users.get_current_user()
            # Don't want the embedded properties in the device_info structure.
            device_info_dict = dict(checkin)
            del device_info_dict['properties']
            util.ConvertFromDict(device_info, device_info_dict)
            device_info.put()

            # Extract DeviceProperties.
            device_properties = model.DeviceProperties(parent=device_info)
            device_properties.device_info = device_info
            util.ConvertFromDict(device_properties, checkin['properties'])
            device_properties.put()

            device_schedule = GetDeviceSchedule(device_properties)
            device_schedule_json = EncodeScheduleAsJson(device_schedule)
            logging.info('Sending checkin response: %s', device_schedule_json)
            self.response.headers['Content-Type'] = 'application/json'
            self.response.out.write(device_schedule_json)

        except Exception, e:
            logging.error('Got exception during checkin: %s', e)
            self.response.headers['Content-Type'] = 'application/json'
            self.response.out.write(json.dumps([]))
Example #8
0
def GetLatestDeviceProperties(device_info, create_new_if_none=False):
    """Retrieve the latest device properties corresponding to this device_info.

  Arguments:
    device_info: The DeviceInfo object on which to retrieve the properties.
    create_new_if_none: Whether to create a new DeviceProperties if none
      exists.
  Returns:
    A DeviceProperties object, or None.
  """
    query = device_info.deviceproperties_set
    query.order('-timestamp')
    device_properties_list = query.fetch(1)
    if not device_properties_list:
        if create_new_if_none:
            device_properties = model.DeviceProperties(parent=device_info)
            device_properties.device_info = device_info
            return device_properties
        else:
            return None
    else:
        return device_properties_list[0]
Example #9
0
    def PostMeasurement(self, **unused_args):
        """Handler used to post a measurement from a device."""
        if self.request.method.lower() != 'post':
            raise error.BadRequest('Not a POST request.')

        try:
            measurement_list = json.loads(self.request.body)
            logging.info('PostMeasurement: Got %d measurements to write',
                         len(measurement_list))
            for measurement_dict in measurement_list:
                # Change device id such that it is anonymized, but preserve the TAC.
                measurement_dict['tac'] = util.GetTypeAllocationCode(
                    measurement_dict['device_id'])
                measurement_dict['device_id'] = util.HashDeviceId(
                    measurement_dict['device_id'])

                device_info = model.DeviceInfo.get_or_insert(
                    measurement_dict['device_id'])

                # Write new device properties, if present
                if 'properties' in measurement_dict:
                    device_properties = model.DeviceProperties(
                        parent=device_info)
                    device_properties.device_info = device_info
                    properties_dict = measurement_dict['properties']
                    # TODO(wenjiezeng): Sanitize input that contains bad fields
                    util.ConvertFromDict(device_properties, properties_dict)
                    # Don't want the embedded properties in the Measurement object
                    del measurement_dict['properties']
                else:
                    # Get most recent device properties
                    device_properties = device.GetLatestDeviceProperties(
                        device_info, create_new_if_none=True)
                device_properties.put()

                if 'context_results' in measurement_dict:
                    if 'values' in measurement_dict:
                        measurement_dict['values']['context_results'] = str(
                            measurement_dict['context_results'])
                    del measurement_dict['context_results']

                measurement = model.Measurement(parent=device_info)
                util.ConvertFromDict(measurement, measurement_dict)
                measurement.device_properties = device_properties
                measurement.put()

                #extracting the IPs from the ping measurement results to the main CDN domain
                if measurement.success == True and measurement.type == "ping":
                    if ('target' in measurement_dict['parameters']
                        ) and measurement_dict['parameters'][
                            'target'] in CDN_TARGETS:
                        ipdata = model.CDNIpData()
                        target_ip = measurement_dict['values'][
                            'target_ip'].replace('"', '')
                        if ':' in target_ip:
                            continue
                        prefix = target_ip[:target_ip.rfind('.') + 1].replace(
                            '"', '')
                        q = model.CDNIpData.all()
                        q.filter("prefix =", prefix)
                        record = q.get()
                        if record != None:
                            #updating timestamp (expiration time)
                            record.put()
                        else:
                            #inserting the new IP record to the data store
                            record = model.CDNIpData()
                            record.ip = target_ip
                            record.prefix = prefix
                            record.cdn_domain = measurement_dict['parameters'][
                                'target']
                            record.put()

                nettype = properties_dict['network_type'].lower().replace(
                    " ", "")
                # map from deviceid to the list of high ping rtts
                low_performance_devices = {}
                if measurement.success == True and measurement.type == "ping" and nettype != "wifi":
                    if ('target' in measurement_dict['parameters']
                        ) and measurement_dict['parameters'][
                            'target'] in CDN_TARGETS:
                        mean_rtt = float(
                            measurement_dict['values']['mean_rtt_ms'])
                        if util.IsLowPerformance("ping", nettype, mean_rtt):
                            lat = float(
                                properties_dict['location']['latitude'])
                            lon = float(
                                properties_dict['location']['longitude'])
                            carrier = properties_dict['carrier'].lower(
                            ).replace(" ", "")
                            timestamp = measurement_dict['timestamp']
                            target = measurement_dict['parameters']['target']

                            # get all the measurement results from the last 24 hours
                            q = model.Measurement.all()
                            q.filter("type =", "ping")
                            q.filter("success =", True)
                            q.filter("timestamp >",
                                     datetime.now() - timedelta(hours=24))
                            for record in q.run():
                                record_nettype = record.device_properties.network_type.lower(
                                ).replace(" ", "")
                                if record.GetParam(
                                        'target'
                                ) == target and record_nettype != "wifi":
                                    record_rtt = record.GetValue('mean_rtt_ms')
                                    if util.IsLowPerformance(
                                            "ping", record_nettype,
                                            record_rtt):
                                        record_location = record.device_properties.location
                                        record_carrier = record.device_properties.carrier
                                        distance = -1
                                        if record_location.lat != 0.0 and record_location.lon != 0.0:
                                            distance = util.Distance(
                                                lat, lon, record_location.lat,
                                                record_location.lon)

                                        if (
                                                distance != -1
                                                and distance < 2000
                                        ) or record_carrier == carrier:  #distance in km
                                            if not (record.device_properties.
                                                    device_info.id in
                                                    low_performance_devices):
                                                low_performance_devices[
                                                    record.device_properties.
                                                    device_info.id] = []
                                            low_performance_devices[
                                                record.device_properties.
                                                device_info.id].append(
                                                    record_rtt)

                #the number of devices should be at-least two
                if len(low_performance_devices.keys()) >= 2:
                    query = model.Task.all()
                    query.filter(
                        "tag = ", "DIAG_TARGET"
                    )  #specific ping tasks for target diagnosis, for example, ping to www.facebook.com
                    for diag_target_task in query.run():
                        filter = diag_target_task.filter
                        if not (str(device_info.id) in filter):
                            if filter == None:
                                diag_target_task.filter = "id = " + str(
                                    device_info.id)
                            else:
                                diag_target_task.filter = diag_target_task.filter + " OR id = " + str(
                                    device_info.id)
                            diag_target_task.put()

        except Exception, e:
            logging.exception('Got exception posting measurements')