Esempio n. 1
0
  def testLogClientConnectionWithInvalidUuid(self):
    """Tests LogClientConnection() function with an invalid uuid."""
    client_id = {'uuid': ''}
    event = 'custom'

    self.mox.StubOutWithMock(common.logging, 'warning')
    common.logging.warning(
        'LogClientConnection: uuid is unknown, skipping log')

    self.mox.ReplayAll()
    common.LogClientConnection(event, client_id)
    self.mox.VerifyAll()
Esempio n. 2
0
 def testLogClientConnectionAsync(self):
   """Tests calling LogClientConnection(delay=2)."""
   event = 'eventname'
   client_id = {'uuid': 'fooo'}
   ip_address = 'fooip'
   utcnow = datetime.datetime(2010, 9, 2, 19, 30, 21, 377827)
   self.mox.StubOutWithMock(datetime, 'datetime')
   self.stubs.Set(common.deferred, 'defer', self.mox.CreateMockAnything())
   deferred_name = 'log-client-conn-%s-%s' % (
       client_id['uuid'], '2010-09-02-19-30-21')
   common.datetime.datetime.utcnow().AndReturn(utcnow)
   common.deferred.defer(
       common.LogClientConnection, event, client_id, user_settings=None,
       pkgs_to_install=None, apple_updates_to_install=None,
       ip_address=ip_address, report_feedback=None,
       _name=deferred_name, _countdown=2)
   self.mox.ReplayAll()
   common.LogClientConnection(event, client_id, delay=2, ip_address=ip_address)
   self.mox.VerifyAll()
Esempio n. 3
0
  def testLogClientConnectionPreflightAndNew(self):
    """Tests LogClientConnection() function."""
    event = 'preflight'
    uuid = 'foo-uuid'
    ip_address = 'fooip'
    hostname = 'foohostname'
    serial = 'fooserial'
    owner = 'foouser'
    track = 'footrack'
    config_track = 'footrack'
    site = 'NYC'
    office = 'US-NYC-FOO'
    os_version = '10.6.3'
    client_version = '0.6.0.759.0'
    on_corp = True
    last_notified_datetime_str = '2010-11-03 15:15:10'
    last_notified_datetime = datetime.datetime(
        2010, 11, 03, 15, 15, 10)
    uptime = 123
    root_disk_free = 456
    user_disk_free = 789
    runtype = 'auto'
    client_id = {
        'uuid': uuid, 'hostname': hostname, 'serial': serial, 'owner': owner,
        'track': track, 'config_track': config_track, 'os_version': os_version,
        'client_version': client_version, 'on_corp': on_corp,
        'last_notified_datetime': last_notified_datetime_str,
        'site': site, 'office': office, 'uptime': uptime,
        'root_disk_free': root_disk_free, 'user_disk_free': user_disk_free,
        'runtype': runtype,
    }

    # bypass the db.run_in_transaction step
    self.stubs.Set(
        common.models.db, 'run_in_transaction',
        lambda fn, *args, **kwargs: fn(*args, **kwargs))

    self.MockModelStaticNone('Computer', 'get_by_key_name', uuid)
    mock_computer = self.MockModel('Computer', key_name=uuid)
    self.mox.StubOutWithMock(common.deferred, 'defer')

    mock_computer.connection_datetimes = []
    mock_computer.connection_dates = []
    mock_computer.connections_on_corp = None
    mock_computer.connections_off_corp = None
    mock_computer.preflight_count_since_postflight = None
    mock_computer.put().AndReturn(None)
    common.deferred.defer(
        common._SaveFirstConnection,
        client_id=client_id, computer=mock_computer, _countdown=300,
        _queue='first')

    self.mox.ReplayAll()
    common.LogClientConnection(event, client_id, ip_address=ip_address)
    self.assertEquals(uuid, mock_computer.uuid)
    self.assertEquals(ip_address, mock_computer.ip_address)
    self.assertEquals(runtype, mock_computer.runtype)
    self.assertEquals(hostname, mock_computer.hostname)
    self.assertEquals(serial, mock_computer.serial)
    self.assertEquals(owner, mock_computer.owner)
    self.assertEquals(track, mock_computer.track)
    self.assertEquals(config_track, mock_computer.config_track)
    self.assertEquals(site, mock_computer.site)
    self.assertEquals(office, mock_computer.office)
    self.assertEquals(os_version, mock_computer.os_version)
    self.assertEquals(client_version, mock_computer.client_version)
    self.assertEquals(
        last_notified_datetime, mock_computer.last_notified_datetime)
    # New client, so zero connection date/datetimes until after postflight.
    self.assertEquals([], mock_computer.connection_datetimes)
    self.assertEquals([], mock_computer.connection_dates)
    # Verify on_corp/off_corp counts.
    self.assertEquals(None, mock_computer.connections_on_corp)
    self.assertEquals(None, mock_computer.connections_off_corp)
    self.assertEquals(1, mock_computer.preflight_count_since_postflight)
    self.mox.VerifyAll()
Esempio n. 4
0
  def testLogClientConnectionPostflight(self):
    """Tests LogClientConnection() function."""
    event = 'postflight'
    uuid = 'foo-uuid'
    ip_address = 'fooip'
    hostname = 'foohostname'
    serial = 'serial'
    owner = 'foouser'
    track = 'footrack'
    config_track = 'footrack'
    site = 'NYC'
    office = 'US-NYC-FOO'
    os_version = '10.6.3'
    client_version = '0.6.0.759.0'
    on_corp = True
    last_notified_datetime_str = '2010-11-03 15:15:10'
    last_notified_datetime = datetime.datetime(2010, 11, 03, 15, 15, 10)
    uptime = 123
    root_disk_free = 456
    user_disk_free = 789
    runtype = 'custom'
    client_id = {
        'uuid': uuid, 'hostname': hostname, 'serial': serial, 'owner': owner,
        'track': track, 'config_track': config_track, 'os_version': os_version,
        'client_version': client_version, 'on_corp': on_corp,
        'last_notified_datetime': last_notified_datetime_str,
        'site': site, 'office': office, 'uptime': uptime,
        'root_disk_free': root_disk_free, 'user_disk_free': user_disk_free,
        'runtype': runtype,
    }
    pkgs_to_install = ['FooApp1', 'FooApp2']
    apple_updates_to_install = ['FooUpdate1', 'FooUpdate2']
    all_pkgs_to_install = pkgs_to_install + [
        common.APPLESUS_PKGS_TO_INSTALL_FORMAT % update
        for update in apple_updates_to_install]
    connection_datetimes = range(1, common.CONNECTION_DATETIMES_LIMIT + 1)
    connection_dates = range(1, common.CONNECTION_DATES_LIMIT + 1)

    # bypass the db.run_in_transaction step
    self.stubs.Set(
        common.models.db, 'run_in_transaction',
        lambda fn, *args, **kwargs: fn(*args, **kwargs))

    mock_computer = self.mox.CreateMockAnything()
    mock_computer.connection_datetimes = connection_datetimes
    mock_computer.connection_dates = connection_dates
    mock_computer.connections_on_corp = None  # test (None or 0) + 1
    mock_computer.connections_off_corp = 0
    mock_computer.put().AndReturn(None)

    self.mox.ReplayAll()
    common.LogClientConnection(
        event, client_id, pkgs_to_install=pkgs_to_install,
        apple_updates_to_install=apple_updates_to_install,
        computer=mock_computer, ip_address=ip_address)
    self.assertEquals(uuid, mock_computer.uuid)
    self.assertEquals(ip_address, mock_computer.ip_address)
    self.assertEquals(runtype, mock_computer.runtype)
    self.assertEquals(hostname, mock_computer.hostname)
    self.assertEquals(serial, mock_computer.serial)
    self.assertEquals(owner, mock_computer.owner)
    self.assertEquals(track, mock_computer.track)
    self.assertEquals(config_track, mock_computer.config_track)
    self.assertEquals(site, mock_computer.site)
    self.assertEquals(office, mock_computer.office)
    self.assertEquals(os_version, mock_computer.os_version)
    self.assertEquals(client_version, mock_computer.client_version)
    self.assertEquals(
        last_notified_datetime, mock_computer.last_notified_datetime)
    # Verify that the first "datetime" was popped off.
    self.assertEquals(connection_datetimes[0], 2)
    # Verify that the last datetime is the new datetime.
    new_datetime = connection_datetimes[common.CONNECTION_DATETIMES_LIMIT - 1]
    self.assertEquals(type(new_datetime), datetime.datetime)
    # Verify that the first "date" was popped off.
    self.assertEquals(connection_dates[0], 2)
    # Verify that the last date is the new date.
    new_date = connection_dates[common.CONNECTION_DATES_LIMIT - 1]
    self.assertEquals(type(new_date), datetime.datetime)
    # Verify on_corp/off_corp counts.
    self.assertEquals(1, mock_computer.connections_on_corp)
    self.assertEquals(0, mock_computer.connections_off_corp)
    self.assertEquals(all_pkgs_to_install, mock_computer.pkgs_to_install)
    self.assertEquals(False, mock_computer.all_pkgs_installed)
    self.assertEquals(0, mock_computer.preflight_count_since_postflight)
    self.mox.VerifyAll()
Esempio n. 5
0
  def testLogClientConnectionPreflight(self):
    """Tests LogClientConnection() function."""
    user_settings = {'foo': True}
    event = 'preflight'
    uuid = 'foo-uuid'
    hostname = 'foohostname'
    serial = 'serial'
    owner = 'foouser'
    track = 'footrack'
    config_track = 'footrack'
    site = 'NYC'
    office = 'US-NYC-FOO'
    os_version = '10.6.3'
    client_version = '0.6.0.759.0'
    on_corp = True
    last_notified_datetime_str = '2010-11-03 15:15:10'
    last_notified_datetime = datetime.datetime(2010, 11, 03, 15, 15, 10)
    uptime = 123
    root_disk_free = 456
    user_disk_free = 789
    ip_address = 'fooip'
    runtype = 'auto'
    report_feedback = {'force_continue': True}

    client_id = {
        'uuid': uuid, 'hostname': hostname, 'serial': serial, 'owner': owner,
        'track': track, 'config_track': config_track, 'os_version': os_version,
        'client_version': client_version, 'on_corp': on_corp,
        'last_notified_datetime': last_notified_datetime_str,
        'site': site, 'office': office, 'uptime': uptime,
        'root_disk_free': root_disk_free, 'user_disk_free': user_disk_free,
        'runtype': runtype,
    }
    connection_datetimes = range(1, common.CONNECTION_DATETIMES_LIMIT + 1)
    connection_dates = range(1, common.CONNECTION_DATES_LIMIT + 1)

    # bypass the db.run_in_transaction step
    self.stubs.Set(
        common.models.db, 'run_in_transaction',
        lambda fn, *args, **kwargs: fn(*args, **kwargs))

    mock_computer = self.MockModelStatic('Computer', 'get_by_key_name', uuid)
    mock_computer.connection_datetimes = connection_datetimes
    mock_computer.connection_dates = connection_dates
    mock_computer.connections_on_corp = 2
    mock_computer.connections_off_corp = 2
    mock_computer.preflight_count_since_postflight = 3
    mock_computer.put().AndReturn(None)

    self.mox.ReplayAll()
    common.LogClientConnection(
        event, client_id, user_settings=user_settings, ip_address=ip_address,
        report_feedback=report_feedback)
    self.assertEquals(uuid, mock_computer.uuid)
    self.assertEquals(ip_address, mock_computer.ip_address)
    self.assertEquals(runtype, mock_computer.runtype)
    self.assertEquals(hostname, mock_computer.hostname)
    self.assertEquals(serial, mock_computer.serial)
    self.assertEquals(owner, mock_computer.owner)
    self.assertEquals(track, mock_computer.track)
    self.assertEquals(config_track, mock_computer.config_track)
    self.assertEquals(site, mock_computer.site)
    self.assertEquals(office, mock_computer.office)
    self.assertEquals(os_version, mock_computer.os_version)
    self.assertEquals(client_version, mock_computer.client_version)
    self.assertEquals(
        last_notified_datetime, mock_computer.last_notified_datetime)
    # Verify on_corp/off_corp counts.
    self.assertEquals(2, mock_computer.connections_on_corp)
    self.assertEquals(2, mock_computer.connections_off_corp)
    self.assertEquals(
        datetime.datetime, type(mock_computer.last_on_corp_preflight_datetime))
    self.assertEquals(4, mock_computer.preflight_count_since_postflight)
    self.mox.VerifyAll()
Esempio n. 6
0
    def post(self):
        """Reports get handler.

    Returns:
      A webapp.Response() response.
    """
        session = gaeserver.DoMunkiAuth()
        uuid = main_common.SanitizeUUID(session.uuid)
        report_type = self.request.get('_report_type')
        feedback_requested = self.request.get('_feedback')
        message = None
        details = None
        client_id = None
        computer = None

        if report_type == 'preflight' or report_type == 'postflight':
            client_id_str = urllib.unquote(self.request.get('client_id'))
            client_id = common.ParseClientId(client_id_str, uuid=uuid)
            user_settings_str = self.request.get('user_settings')
            user_settings = None
            try:
                if user_settings_str:
                    user_settings = util.Deserialize(
                        urllib.unquote(str(user_settings_str)))
            except util.DeserializeError:
                logging.warning('Client %s sent broken user_settings: %s',
                                client_id_str, user_settings_str)

            pkgs_to_install = self.request.get_all('pkgs_to_install')
            apple_updates_to_install = self.request.get_all(
                'apple_updates_to_install')

            computer = models.Computer.get_by_key_name(uuid)
            ip_address = os.environ.get('REMOTE_ADDR', '')
            report_feedback = None
            if report_type == 'preflight':
                # if the UUID is known to be lost/stolen, log this connection.
                if models.ComputerLostStolen.IsLostStolen(uuid):
                    logging.warning('Connection from lost/stolen machine: %s',
                                    uuid)
                    models.ComputerLostStolen.LogLostStolenConnection(
                        computer=computer, ip_address=ip_address)

                # we want to get feedback now, before preflight_datetime changes.
                if feedback_requested:
                    client_exit = self.request.get('client_exit', None)
                    report_feedback = self.GetReportFeedback(
                        uuid,
                        report_type,
                        computer=computer,
                        ip_address=ip_address,
                        client_exit=client_exit)
                    self.response.out.write(report_feedback)

                    # if report feedback calls for a client exit, log it.
                    if report_feedback == common.ReportFeedback.EXIT:
                        if not client_exit:
                            # client didn't ask for an exit, which means server decided.
                            client_exit = 'Connection from defined exit IP address'
                        common.WriteClientLog(models.PreflightExitLog,
                                              uuid,
                                              computer=computer,
                                              exit_reason=client_exit)

            common.LogClientConnection(report_type,
                                       client_id,
                                       user_settings,
                                       pkgs_to_install,
                                       apple_updates_to_install,
                                       computer=computer,
                                       ip_address=ip_address,
                                       report_feedback=report_feedback)

        elif report_type == 'install_report':
            computer = models.Computer.get_by_key_name(uuid)

            self._LogInstalls(self.request.get_all('installs'), computer)

            for removal in self.request.get_all('removals'):
                common.WriteClientLog(models.ClientLog,
                                      uuid,
                                      computer=computer,
                                      action='removal',
                                      details=removal)

            for problem in self.request.get_all('problem_installs'):
                common.WriteClientLog(models.ClientLog,
                                      uuid,
                                      computer=computer,
                                      action='install_problem',
                                      details=problem)
        elif report_type == 'preflight_exit':
            # NOTE(user): only remains for older clients.
            message = self.request.get('message')
            computer = common.WriteClientLog(models.PreflightExitLog,
                                             uuid,
                                             exit_reason=message)
        elif report_type == 'broken_client':
            # Default reason of "objc" to support legacy clients, existing when objc
            # was the only broken state ever reported.
            reason = self.request.get('reason', 'objc')
            details = self.request.get('details')
            logging.warning('Broken Munki client (%s): %s', reason, details)
            common.WriteBrokenClient(uuid, reason, details)
        elif report_type == 'msu_log':
            details = {}
            for k in ['time', 'user', 'source', 'event', 'desc']:
                details[k] = self.request.get(k, None)
            common.WriteComputerMSULog(uuid, details)
        else:
            # unknown report type; log all post params.
            params = []
            for param in self.request.arguments():
                params.append('%s=%s' % (param, self.request.get_all(param)))
            common.WriteClientLog(models.ClientLog,
                                  uuid,
                                  action='unknown',
                                  details=str(params))

        # If the client asked for feedback, get feedback and respond.
        # Skip this if the report_type is preflight, as report feedback was
        # retrieved before LogComputerConnection changed preflight_datetime.
        if feedback_requested and report_type != 'preflight':
            self.response.out.write(
                self.GetReportFeedback(
                    uuid,
                    report_type,
                    message=message,
                    details=details,
                    computer=computer,
                ))
Esempio n. 7
0
    def post(self):
        """Reports get handler.

    Returns:
      A webapp.Response() response.
    """
        session = gaeserver.DoMunkiAuth()
        uuid = main_common.SanitizeUUID(session.uuid)
        report_type = self.request.get('_report_type')
        report_feedback = {}
        message = None
        details = None
        client_id = None
        computer = None

        if report_type == 'preflight' or report_type == 'postflight':
            client_id_str = urllib.unquote(self.request.get('client_id'))
            client_id = common.ParseClientId(client_id_str, uuid=uuid)
            user_settings_str = self.request.get('user_settings')
            user_settings = None
            try:
                if user_settings_str:
                    user_settings = util.Deserialize(
                        urllib.unquote(str(user_settings_str)))
            except util.DeserializeError:
                logging.warning('Client %s sent broken user_settings: %s',
                                client_id_str, user_settings_str)

            pkgs_to_install = self.request.get_all('pkgs_to_install')
            apple_updates_to_install = self.request.get_all(
                'apple_updates_to_install')

            computer = models.Computer.get_by_key_name(uuid)
            ip_address = os.environ.get('REMOTE_ADDR', '')
            if report_type == 'preflight':
                # we want to get feedback now, before preflight_datetime changes.
                client_exit = self.request.get('client_exit', None)
                report_feedback = self.GetReportFeedback(
                    uuid,
                    report_type,
                    computer=computer,
                    ip_address=ip_address,
                    client_exit=client_exit)

                if self.request.get('json') == '1':
                    self.response.out.write(JSON_PREFIX +
                                            json.dumps(report_feedback))
                else:
                    # For legacy clients that accept a single string, not JSON.
                    feedback_to_send = 'OK'
                    for feedback in LEGACY_FEEDBACK_LIST:
                        if report_feedback.get(feedback.lower()):
                            feedback_to_send = feedback
                    self.response.out.write(feedback_to_send)

                # if report feedback calls for a client exit, log it.
                if report_feedback.get('exit'):
                    if not client_exit:
                        # client didn't ask for an exit, which means server decided.
                        client_exit = 'Connection from defined exit IP address'
                    common.WriteClientLog(models.PreflightExitLog,
                                          uuid,
                                          computer=computer,
                                          exit_reason=client_exit)

            common.LogClientConnection(report_type,
                                       client_id,
                                       user_settings,
                                       pkgs_to_install,
                                       apple_updates_to_install,
                                       computer=computer,
                                       ip_address=ip_address,
                                       report_feedback=report_feedback)

        elif report_type == 'install_report':
            computer = models.Computer.get_by_key_name(uuid)

            self._LogInstalls(self.request.get_all('installs'), computer)

            for removal in self.request.get_all('removals'):
                common.WriteClientLog(models.ClientLog,
                                      uuid,
                                      computer=computer,
                                      action='removal',
                                      details=removal)

            for problem in self.request.get_all('problem_installs'):
                common.WriteClientLog(models.ClientLog,
                                      uuid,
                                      computer=computer,
                                      action='install_problem',
                                      details=problem)
        elif report_type == 'broken_client':
            # Default reason of "objc" to support legacy clients, existing when objc
            # was the only broken state ever reported.
            reason = self.request.get('reason', 'objc')
            details = self.request.get('details')
            logging.warning('Broken Munki client (%s): %s', reason, details)
            common.WriteBrokenClient(uuid, reason, details)
        elif report_type == 'msu_log':
            details = {}
            for k in ['time', 'user', 'source', 'event', 'desc']:
                details[k] = self.request.get(k, None)
            common.WriteComputerMSULog(uuid, details)
        else:
            # unknown report type; log all post params.
            params = []
            for param in self.request.arguments():
                params.append('%s=%s' % (param, self.request.get_all(param)))
            common.WriteClientLog(models.ClientLog,
                                  uuid,
                                  action='unknown',
                                  details=str(params))