def LogClientConnection(
    event, client_id, user_settings=None, pkgs_to_install=None,
    apple_updates_to_install=None, ip_address=None, report_feedback=None,
    computer=None, delay=0):
  """Logs a host checkin to Simian.

  Args:
    event: str name of the event that prompted a client connection log.
    client_id: dict client id with fields: uuid, hostname, owner.
    user_settings: optional dict of user settings.
    pkgs_to_install: optional list of string packages remaining to install.
    apple_updates_to_install: optional list of string Apple updates remaining
        to install.
    ip_address: str IP address of the connection.
    report_feedback: dict ReportFeedback commands sent to the client.
    computer: optional models.Computer object.
    delay: int. if > 0, LogClientConnection call is deferred this many seconds.
  """
  if delay:
    now_str = datetime.datetime.utcnow().strftime('%Y-%m-%d-%H-%M-%S')
    deferred_name = 'log-client-conn-%s-%s' % (client_id['uuid'], now_str)
    deferred.defer(
        LogClientConnection, event, client_id, user_settings=user_settings,
        pkgs_to_install=pkgs_to_install, ip_address=ip_address,
        apple_updates_to_install=apple_updates_to_install,
        report_feedback=report_feedback, _name=deferred_name, _countdown=delay)
    return

  if not client_id['uuid']:
    logging.warning('LogClientConnection: uuid is unknown, skipping log')
    return

  def __UpdateComputerEntity(
      event, _client_id, _user_settings, _pkgs_to_install,
      _apple_updates_to_install, _ip_address, _report_feedback, c=None):
    """Update the computer entity, or create a new one if it doesn't exists."""
    now = datetime.datetime.utcnow()
    is_new_client = False
    if c is None:
      c = models.Computer.get_by_key_name(_client_id['uuid'])
    if c is None:  # First time this client has connected.
      c = models.Computer(key_name=_client_id['uuid'])
      is_new_client = True
    c.uuid = _client_id['uuid']
    c.hostname = _client_id['hostname']
    c.serial= _client_id['serial']
    c.owner = _client_id['owner']
    c.track = _client_id['track']
    c.site = _client_id['site']
    c.office = _client_id['office']
    c.config_track = _client_id['config_track']
    c.client_version = _client_id['client_version']
    c.os_version = _client_id['os_version']
    c.uptime = _client_id['uptime']
    c.root_disk_free = _client_id['root_disk_free']
    c.user_disk_free = _client_id['user_disk_free']
    c.runtype = _client_id['runtype']
    c.ip_address = _ip_address

    last_notified_datetime = _client_id['last_notified_datetime']
    if last_notified_datetime:  # might be None
      try:
        last_notified_datetime = datetime.datetime.strptime(
            last_notified_datetime, '%Y-%m-%d %H:%M:%S')  # timestamp is UTC.
        c.last_notified_datetime = last_notified_datetime
      except ValueError:  # non-standard datetime sent.
        logging.warning(
            'Non-standard last_notified_datetime: %s', last_notified_datetime)

    # Update event specific (preflight vs postflight) report values.
    if event == 'preflight':
      c.preflight_datetime = now
      if _client_id['on_corp'] == True:
        c.last_on_corp_preflight_datetime = now

      # Increment the number of preflight connections since the last successful
      # postflight, but only if the current connection is not going to exit due
      # to report feedback (WWAN, GoGo InFlight, etc.)
      if not _report_feedback or not _report_feedback.get('exit'):
        if c.preflight_count_since_postflight is not None:
          c.preflight_count_since_postflight += 1
        else:
          c.preflight_count_since_postflight = 1

    elif event == 'postflight':
      c.preflight_count_since_postflight = 0
      c.postflight_datetime = now

      # Update pkgs_to_install.
      if _pkgs_to_install:
        c.pkgs_to_install = _pkgs_to_install
        c.all_pkgs_installed = False
      else:
        c.pkgs_to_install = []
        c.all_pkgs_installed = True
      # Update all_apple_updates_installed and add Apple updates to
      # pkgs_to_install. It's important that this code block comes after
      # all_pkgs_installed is updated above, to ensure that all_pkgs_installed
      # is only considers Munki updates, ignoring Apple updates added below.
      # NOTE: if there are any pending Munki updates then we simply assume
      # there are also pending Apple Updates, even though we cannot be sure
      # due to the fact that Munki only checks for Apple Updates if all regular
      # updates are installed
      if not pkgs_to_install and not _apple_updates_to_install:
        c.all_apple_updates_installed = True
      else:
        c.all_apple_updates_installed = False
        # For now, let's store Munki and Apple Update pending installs together,
        # using APPLESUS_PKGS_TO_INSTALL_FORMAT to format the text as desired.
        for update in _apple_updates_to_install:
          c.pkgs_to_install.append(APPLESUS_PKGS_TO_INSTALL_FORMAT % update)

      # Keep the last CONNECTION_DATETIMES_LIMIT connection datetimes.
      if len(c.connection_datetimes) == CONNECTION_DATETIMES_LIMIT:
        c.connection_datetimes.pop(0)
      c.connection_datetimes.append(now)

      # Increase on_corp/off_corp count appropriately.
      if _client_id['on_corp'] == True:
        c.connections_on_corp = (c.connections_on_corp or 0) + 1
      elif _client_id['on_corp'] == False:
        c.connections_off_corp = (c.connections_off_corp or 0) + 1

      # Keep the last CONNECTION_DATES_LIMIT connection dates
      # (with time = 00:00:00)
      # Use newly created datetime.time object to set time to 00:00:00
      now_date = datetime.datetime.combine(now, datetime.time())
      if now_date not in c.connection_dates:
        if len(c.connection_dates) == CONNECTION_DATES_LIMIT:
          c.connection_dates.pop(0)
        c.connection_dates.append(now_date)
    else:
      logging.warning('Unknown event value: %s', event)

    c.put()
    if is_new_client:  # Queue welcome email to be sent.
      deferred.defer(
          _SaveFirstConnection, client_id=_client_id, computer=c,
          _countdown=300, _queue='first')

  try:
    db.run_in_transaction(
        __UpdateComputerEntity,
        event, client_id, user_settings, pkgs_to_install,
        apple_updates_to_install, ip_address, report_feedback, c=computer)
  except (db.Error, apiproxy_errors.Error, runtime.DeadlineExceededError) as e:
    logging.warning(
        'LogClientConnection put() error %s: %s', e.__class__.__name__, str(e))
    LogClientConnection(
        event, client_id, user_settings, pkgs_to_install,
        apple_updates_to_install, ip_address, report_feedback,
        delay=DATASTORE_NOWRITE_DELAY)
dataset/ETHPy150Open google/simian/src/simian/mac/munki/common.py/LogClientConnection/original