#! /usr/bin/env python
# Copyright (C) 2012 OpenStack, LLC.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.

# Synchronize Gerrit users from Launchpad.
# TODO items:
# 1. add a temporary (instance level) object store for the launchpad class
# 2. split out the two classes into separate files to be used as a library

import os
import sys
import ConfigParser
import StringIO
import paramiko
import json
import logging
import uuid
from launchpadlib.launchpad import Launchpad
from launchpadlib.uris import LPNET_SERVICE_ROOT

from datetime import datetime

from openid.consumer import consumer
from openid.cryptutil import randomString

GERRIT_USER = os.environ.get('GERRIT_USER', 'launchpadsync')
GERRIT_CONFIG = os.environ.get('GERRIT_CONFIG',
                                 '/home/gerrit2/review_site/etc/gerrit.config')
GERRIT_SECURE_CONFIG = os.environ.get('GERRIT_SECURE_CONFIG',
                                 '/home/gerrit2/review_site/etc/secure.config')
GERRIT_SSH_KEY = os.environ.get('GERRIT_SSH_KEY',
                                 '/home/gerrit2/.ssh/launchpadsync_rsa')
GERRIT_CACHE_DIR = os.path.expanduser(os.environ.get('GERRIT_CACHE_DIR',
                                '~/.launchpadlib/cache'))
GERRIT_CREDENTIALS = os.path.expanduser(os.environ.get('GERRIT_CREDENTIALS',
                                '~/.launchpadlib/creds'))
GERRIT_BACKUP_PATH = os.environ.get('GERRIT_BACKUP_PATH',
                                '/home/gerrit2/dbupdates')

logging.basicConfig(format='%(asctime)-6s: %(name)s - %(levelname)s - %(message)s', filename='/var/log/gerrit/update_users.log')
logger= logging.getLogger('update_users')
logger.setLevel(logging.INFO)

for check_path in (os.path.dirname(GERRIT_CACHE_DIR),
                   os.path.dirname(GERRIT_CREDENTIALS),
                   GERRIT_BACKUP_PATH):
  if not os.path.exists(check_path):
    os.makedirs(check_path)

def get_broken_config(filename):
  """ gerrit config ini files are broken and have leading tabs """
  text = ""
  with open(filename,"r") as conf:
    for line in conf.readlines():
      text = "%s%s" % (text, line.lstrip())

  fp = StringIO.StringIO(text)
  c=ConfigParser.ConfigParser()
  c.readfp(fp)
  return c

gerrit_config = get_broken_config(GERRIT_CONFIG)
secure_config = get_broken_config(GERRIT_SECURE_CONFIG)

DB_USER = gerrit_config.get("database", "username")
DB_PASS = secure_config.get("database","password")
DB_DB = gerrit_config.get("database","database")

def make_db_backup():
  db_backup_file = "%s.%s.sql" % (DB_DB, datetime.isoformat(datetime.now()))
  db_backup_path = os.path.join(GERRIT_BACKUP_PATH, db_backup_file)
  retval = os.system("mysqldump --opt -u%s -p%s %s | gzip -9 > %s.gz" %
                       (DB_USER, DB_PASS, DB_DB, db_backup_path))
  if retval != 0:
    logger.error("Problem taking a db dump, aborting db update")
    sys.exit(retval)

class LaunchpadAction(object):
  def __init__(self):
    logger.info('Connecting to Launchpad')
    self.launchpad= Launchpad.login_with('Gerrit User Sync', LPNET_SERVICE_ROOT,
                                 GERRIT_CACHE_DIR,
                                 credentials_file = GERRIT_CREDENTIALS)

    logger.info('Getting Launchpad teams')
    self.lp_teams= self.get_all_sub_teams('openstack', [])

  def get_all_sub_teams(self, team, have_teams):
    for sub_team in self.launchpad.people[team].sub_teams:
      if sub_team.name not in have_teams:
         have_teams = self.get_all_sub_teams(sub_team.name, have_teams)
    have_teams.append(team)
    return have_teams

  def get_sub_teams(self, team):
    sub_teams= []
    for sub_team in self.launchpad.people[team].sub_teams:
      sub_teams.append(sub_team.name)
    return sub_teams

  def get_teams(self):
    return self.lp_teams

  def get_all_users(self):
    logger.info('Getting Launchpad users')
    users= []
    for team in self.lp_teams:
      for detail in self.launchpad.people[team].members_details:
        if (detail.status == 'Approved' or detail.status == 'Administrator'):
          name= detail.self_link.split('/')[-1]
          if ((users.count(name) == 0) and (name not in self.lp_teams)):
            users.append(name)
    return users

  def get_user_data(self, user):
    return self.launchpad.people[user]

  def get_team_members(self, team, gerrit):
    users= []
    for detail in self.launchpad.people[team].members_details:
      if (detail.status == 'Approved' or detail.status == 'Administrator'):
        name= detail.self_link.split('/')[-1]
        # if we found a subteam
        if name in self.lp_teams:
          # check subteam for implied subteams
          for implied_group in gerrit.get_implied_groups(name):
            if implied_group in self.lp_teams:
              users.extend(self.get_team_members(implied_group, gerrit))
          users.extend(self.get_team_members(name, gerrit))
          continue
        users.append(name)
    # check team for implied teams
    for implied_group in gerrit.get_implied_groups(team):
      if implied_group in self.lp_teams:
        users.extend(self.get_team_members(implied_group, gerrit))
    # filter out dupes
    users= list(set(users))
    return users

  def get_team_watches(self, team):
    users= []
    for detail in self.launchpad.people[team].members_details:
      if (detail.status == 'Approved' or detail.status == 'Administrator'):
        name= detail.self_link.split('/')[-1]
        if name in self.lp_teams:
          continue
        if users.count(name) == 0:
          users.append(name)
    return users

  def get_team_display_name(self, team):
    team_data = self.launchpad.people[team]
    return team_data.display_name

class GerritAction(object):
  def __init__(self):
    logger.info('Connecting to Gerrit')
    self.ssh= paramiko.SSHClient()
    self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    self.ssh.connect('localhost', username=GERRIT_USER, port=29418, key_filename=GERRIT_SSH_KEY)

  def cleanup(self):
    logger.info('Closing connection to Gerrit')
    self.ssh.close()

  def run_query(self, query):
    command= 'gerrit gsql --format JSON -c "{0}"'.format(query)
    stdin, stdout, stderr= self.ssh.exec_command(command)
#   trying to get stdout return code or stderr can hang with large result sets
#    for line in stderr:
#      logger.error(line)
    return stdout

  def get_groups(self):
    logger.info('Getting Gerrit groups')
    groups= []
    query= "select name from account_groups"
    stdout= self.run_query(query)
    for line in stdout:
      row= json.loads(line)
      if row['type'] == 'row':
        group= row['columns']['name']
        groups.append(group)
    return groups

  def get_users(self):
    logger.info('Getting Gerrit users')
    users= []
    query= "select external_id from account_external_ids"
    stdout= self.run_query(query)
    for line in stdout:
      row= json.loads(line)
      if row['type'] == 'row':
        user= row['columns']['external_id'].replace('username:','')
        users.append(user)
    return users

  def get_group_id(self, group_name):
    query= "select group_id from account_groups where name='{0}'".format(group_name)
    stdout= self.run_query(query)
    line= stdout.readline()
    row= json.loads(line)
    if row['type'] == 'row':
      return row['columns']['group_id']
    else:
      return 0

  def get_user_id(self, user_name):
    query= "select account_id from account_external_ids where external_id='username:{0}'".format(user_name)
    stdout= self.run_query(query)
    line= stdout.readline()
    row= json.loads(line)
    return row['columns']['account_id']

  def get_users_from_group(self, group_name):
    logger.info('Getting Gerrit users from group %s', group_name)
    users= []
    gid= self.get_group_id(group_name)

    query= "select external_id from account_external_ids join account_group_members on account_group_members.account_id=account_external_ids.account_id where account_group_members.group_id={0} and external_id like 'username%%'".format(gid)
    stdout= self.run_query(query)
    for line in stdout:
      row= json.loads(line)
      if row['type'] == 'row':
        user= row['columns']['external_id'].replace('username:','')
        users.append(user)
    return users

  def get_users_from_watches(self, group_name):
    logger.info('Getting Gerrit users from watch list %s', group_name)
    users= []
    if group_name.endswith("-core"):
      group_name = group_name[:-5]
    group_name = "openstack/{0}".format(group_name)

    query= "select external_id from account_external_ids join account_project_watches on account_project_watches.account_id=account_external_ids.account_id where account_project_watches.project_name like '{0}' and external_id like 'username%%'".format(group_name)
    stdout= self.run_query(query)
    for line in stdout:
      row= json.loads(line)
      if row['type'] == 'row':
        user= row['columns']['external_id'].replace('username:','')
        users.append(user)
    return users


  def get_implied_groups(self, group_name):
    gid= self.get_group_id(group_name)
    groups= []
    query= "select name from account_groups join account_group_includes on account_group_includes.include_id=account_groups.group_id where account_group_includes.group_id={0}".format(gid)
    stdout= self.run_query(query)
    for line in stdout:
      row= json.loads(line)
      if row['type'] == 'row':
        group= row['columns']['name']
        groups.append(group)
    return groups

  def add_group(self, group_name, group_display_name):
    logger.info('New group %s (%s)', group_display_name, group)
    query= "insert into account_group_id (s) values (NULL)"
    stdout= self.run_query(query)
    row= json.loads(stdout.readline())
    if row['rowCount'] is not 1:
      print "Could not get a new account group ID"
      raise
    query= "select max(s) from account_group_id"
    stdout= self.run_query(query)
    row= json.loads(stdout.readline())
    gid= row['columns']['max(s)']
    full_uuid= "{0}{1}".format(uuid.uuid4().hex, uuid.uuid4().hex[:8])
    query= "insert into account_groups (group_id, group_type, owner_group_id, name, description, group_uuid) values ({0}, 'INTERNAL', 1, '{1}', '{2}', '{3}')". format(gid, group_name, group_display_name, full_uuid)
    self.run_query(query)
    query= "insert into account_group_names (group_id, name) values ({0}, '{1}')".format(gid, group_name)
    self.run_query(query)

  def add_user(self, user_name, user_data):
    logger.info("Adding Gerrit user %s", user_name)
    openid_consumer = consumer.Consumer(dict(id=randomString(16, '0123456789abcdef')), None)
    openid_request = openid_consumer.begin("https://launchpad.net/~%s" % user_data.name)
    user_openid_external_id = openid_request.endpoint.getLocalID()
    query= "select account_id from account_external_ids where external_id in ('{0}')".format(user_openid_external_id)
    stdout= self.run_query(query)
    row= json.loads(stdout.readline())
    if row['type'] == 'row':
      # we have a result so this is an updated user name
      account_id= row['columns']['account_id']
      query= "update account_external_ids set external_id='{0}' where external_id like 'username%%' and account_id = {1}".format('username:%s' % user_name, account_id)
      self.run_query(query)
    else:
      # we really do have a new user
      user_ssh_keys= ["%s %s %s" % ('ssh-%s' % key.keytype.lower(), key.keytext, key.comment) for key in user_data.sshkeys]
      user_email= None
      try:
        user_email = user_data.preferred_email_address.email
      except ValueError:
        pass
      query= "insert into account_id (s) values (NULL)"
      self.run_query(query)
      query= "select max(s) from account_id"
      stdout= self.run_query(query)
      row= json.loads(stdout.readline())
      uid= row['columns']['max(s)']
      query= "insert into accounts (account_id, full_name, preferred_email) values ({0}, '{1}', '{2}')".format(uid, user_name, user_email)
      self.run_query(query)
      keyno= 1
      for key in user_ssh_keys:
        query= "insert into account_ssh_keys (ssh_public_key, valid, account_id, seq) values ('{0}', 'Y', {1}, {2})".format(key.strip(), uid, keyno)
        self.run_query(query)
        keyno = keyno + 1
      query= "insert into account_external_ids (account_id, email_address, external_id) values ({0}, '{1}', '{2}')".format(uid, user_email, user_openid_external_id)
      self.run_query(query)
      query= "insert into account_external_ids (account_id, external_id) values ({0}, '{1}')".format(uid, "username:%s" % user_name)
      self.run_query(query)
      if user_email is not None:
        query= "insert into account_external_ids (account_id, email_address, external_id) values ({0}. '{1}', '{2}')".format(uid, user_email, "mailto:%s" % user_email)
    return None

  def add_user_to_group(self, user_name, group_name):
    logger.info("Adding Gerrit user %s to group %s", user_name, group_name)
    uid= self.get_user_id(user_name)
    gid= self.get_group_id(group_name)
    if gid is 0:
      print "Trying to add user {0} to non-existent group {1}".format(user_name, group_name)
      raise
    query= "insert into account_group_members (account_id, group_id) values ({0}, {1})".format(uid, gid)
    self.run_query(query)

  def add_user_to_watch(self, user_name, group_name):
    logger.info("Adding Gerrit user %s to watch group %s", user_name, group_name)
    uid= self.get_user_id(user_name)
    if group_name.endswith("-core"):
      group_name = group_name[:-5]
    group_name = "openstack/{0}".format(group_name)
    query= "insert into account_project_watches VALUES ('Y', 'N', 'N', {0}, '{1}', '*')". format(uid, group_name)
    self.run_query(query)


  def del_user_from_group(self, user_name, group_name):
    logger.info("Deleting Gerrit user %s from group %s", user_name, group_name)
    uid= self.get_user_id(user_name)
    gid= self.get_group_id(group_name)
    query= "delete from account_group_members where account_id = {0} and group_id = {1}".format(uid, gid)
    self.run_query(query)
    if group_name.endswith("-core"):
      group_name = group_name[:-5]
    group_name= "openstack/{0}".format(group_name)
    query= "delete from account_project_watches where account_id = {0} and project_name= '{1}'".format(uid, group_name)
    self.run_query(query)

  def rebuild_sub_groups(self, group, sub_groups):
    gid= self.get_group_id(group)
    for sub_group in sub_groups:
      sgid= self.get_group_id(sub_group)
      query= "select group_id from account_group_includes where group_id={0} and include_id={1}".format(gid, sgid)
      stdout= self.run_query(query)
      row= json.loads(stdout.readline())
      if row['type'] != 'row':
        logger.info('Adding implied group %s to group %s', group, sub_group)
        query= "insert into account_group_includes (group_id, include_id) values ({0}, {1})".format(gid, sgid)
        self.run_query(query)


# Actual work starts here!

lp= LaunchpadAction()
gerrit= GerritAction()

logger.info('Making DB backup')
make_db_backup()

logger.info('Starting group reconcile')
lp_groups= lp.get_teams()
gerrit_groups= gerrit.get_groups()

group_diff= filter(lambda a: a not in gerrit_groups, lp_groups)
for group in group_diff:
  group_display_name= lp.get_team_display_name(group)
  gerrit.add_group(group, group_display_name)

for group in lp_groups:
  sub_group= lp.get_sub_teams(group)
  if sub_group:
    gerrit.rebuild_sub_groups(group, sub_group)

logger.info('End group reconcile')

logger.info('Starting user reconcile')
lp_users= lp.get_all_users()
gerrit_users= gerrit.get_users()

user_diff= filter(lambda a: a not in gerrit_users, lp_users)
for user in user_diff:
  gerrit.add_user(user, lp.get_user_data(user))

logger.info('End user reconcile')

logger.info('Starting user to group reconcile')
lp_groups= lp.get_teams()
for group in lp_groups:
  # First find users to attach to groups
  gerrit_group_users= gerrit.get_users_from_group(group)
  lp_group_users= lp.get_team_members(group, gerrit)

  group_diff= filter(lambda a: a not in gerrit_group_users, lp_group_users)
  for user in group_diff:
    gerrit.add_user_to_group(user, group)
  # Second find users to attach to watches
  lp_group_watches= lp.get_team_watches(group)
  gerrit_group_watches= gerrit.get_users_from_watches(group)
  group_diff= filter(lambda a: a not in gerrit_group_watches, lp_group_watches)
  for user in group_diff:
    gerrit.add_user_to_watch(user, group)
  # Third find users to remove from groups/watches
  group_diff= filter(lambda a: a not in lp_group_users, gerrit_group_users)
  for user in group_diff:
    gerrit.del_user_from_group(user, group)

logger.info('Ending user to group reconcile')

gerrit.cleanup()
