def Handle(self, dn, attrs):
    """ Override of superclass.Handle() method.
    Args:
      dn: distinguished name of the user, usually from UserDB
      attrs: dictionary of all the user's attributes
    """
    self.dn = dn
    self.attrs = attrs
    try:
      logging.debug('about to CreateAccount for %s' % 
                    self.attrs['GoogleUsername'])
      moreargs = {}
      if 'GoogleQuota' in self.attrs:
        moreargs['quota'] = self.attrs['GoogleQuota']
      self._api.CreateAccountWithEmail(
          userdb.toUnicode(self.attrs['GoogleFirstName']),
          userdb.toUnicode(self.attrs['GoogleLastName']), 
          self.attrs['GooglePassword'],
          self.attrs['GoogleUsername'], **moreargs)
      self._result_queue.PutResult(self.dn, 'added', None, self.attrs)
      self._thread_stats.IncrementStat('adds', 1)
    except provisioning_errs.ProvisioningApiError, e:
      # report failure
      if str(e).find('UserAlreadyExists') >= 0:
        # TODO(rescorcio): what about DeletedUserExists errors?

        logging.info(
           'Attempted add of existing user.  Syncing attrs instead. %s' %
           str(e))

        # Make sure the account is unlocked if it is a valid user.
        # Note: users are exited in only one of two ways:
        # 1) the user matches an exit filter
        # 2) the user disappeared from the ldap search filter that lists all 
        #    users
        # This method is never called on an account in state #1.  
        # Consequently, we can safely unlock this account since
        # it must have reappeared in our ldap query result (hence rebecame a 
        # user) in order to be added.
        logging.info('Making sure this account unlocked: %s' %
            self.attrs['GoogleUsername'])
        self._api.UnlockAccount(self.attrs['GoogleUsername'])

        logging.debug('Updating account %s' % self.dn)
        # Make sure that the user's attributes are synced because there is 
        # no other time that this will get done.
        try:
          updated_user_google_action.Update(self._api, attrs)
        except Exception, e:
          logging.error('error during update: %s' % str(e)) 
          self._thread_stats.IncrementStat('add_fails', 1)
          self._result_queue.PutResult(self.dn, 'added', str(e))
          return

        logging.debug('Marking account %s add a success' % self.dn)

        # trying to add a user that is already there is not an error
        self._result_queue.PutResult(self.dn, 'added', None, self.attrs)
        self._thread_stats.IncrementStat('adds', 1)
        return
def Update(api, attrs):
  """ Update the Google Account given by dn with attrs.
  Args:
    attrs: dictionary of all the user's attributes
  """
  mapping_for_updates = {'firstName': 'GoogleFirstName', 
                         'lastName': 'GoogleLastName',
                         'password': '******'}
  fields = {}
  for (key, google_key) in mapping_for_updates.iteritems():
    if google_key in attrs and attrs[google_key]:
      if key == 'password':
        fields[key] = attrs[google_key]
      else:
        fields[key] = userdb.toUnicode(attrs[google_key])
  logging.debug('about to UpdateAccount for %s' % attrs['GoogleUsername'])
  api.UpdateAccount(attrs['GoogleUsername'], fields)