#!/usr/bin/python2.7

import os
import sys
import subprocess
import glob
import time
import getopt
import sqlite3
from urllib2 import urlopen
from xml.dom import minidom
import json

def fmt_date():
  return time.strftime("%Y%m%d")

# get all of the installed software types by checking the SR urls
# return a list, and run routine on all of them
def discover_software():
  conn = sqlite3.connect("/opt/slapos/slapproxy.db")
  cur = conn.cursor()
  qry = cur.execute("SELECT DISTINCT software_release FROM partition11")
  return [row[0] for row in qry]

def get_connection_information(software_release):
  conn = sqlite3.connect("/opt/slapos/slapproxy.db")
  cur = conn.cursor()
  qry = cur.execute("SELECT connection_xml FROM partition11 WHERE connection_xml IS NOT NULL AND software_release=?", (software_release,) )
  for row in qry:
    xml = str(row[0])
    break 
  instance = minidom.parseString(xml)

  try:
    el = instance.getElementsByTagName('parameter')[0]
    value = el.childNodes[0].nodeValue
  except:
    return "error"
  if not value.startswith("{"):
    value = "\"" + value + "\""
  json_text = json.loads(value)

  if 'family-admin' in json_text:
    return (json_text['family-admin'], json_text['inituser-password'])
  elif 'insecure' in json_text:
    return (json_text, None)
  else:
    return (None, None)

def check_tables():
  conn = sqlite3.connect("/opt/slapos/slapproxy.db")
  cur = conn.cursor()
  qry = cur.execute("SELECT CASE WHEN tbl_name = 'partition11' THEN 1 ELSE 0 END FROM sqlite_master WHERE tbl_name = 'partition11' AND type = 'table'")

  if qry is None:
    print "tables aren't ready yet, your build may have failed, check logs in /opt/slapos/log/"
    sys.exit(0)

def get_build_status():
  try:
    f = open("/opt/slapos/log/slapos-node-software-" + fmt_date() + ".log")
  except:
    f = open("/opt/slapos/log/slapos-node-software.log")
  lines = f.readlines()
  if "Finished software releases" not in lines[-1]:
    return False
  if "ERROR" in lines[-3]:
    return "error"
  return True

# Check if the last two lines show the software finished building.
# If an error came just before this, we'll report failure.
# Otherwise it passed and we can move on.
# We want to open today's log, as it is most up to date

def status(software_release):
  build = get_build_status()
  if build:
    zope_ip, pw = get_connection_information(software_release)
    print ("Build successful, connect to:\n"
           "  " + zope_ip)
    if pw is not None:
      print (" with\n"
             "  username: zope  password: " + pw)
  elif not build:
    print "Your software is still building, be patient it can take awhile"
    sys.exit(2)
  elif build == "error":
    print "An error occurred while building, check /opt/slapos/log/slapos-node-software-" + \
          fmt_date() + ".log for details"
    sys.exit(2)

  # check if the services are actually running (run slapos node and parse output)
  if pw is None:
    zope_ip = "https://" + zope_ip[zope_ip.index("@")+1:]
  r1 = urlopen(zope_ip)
  if r1.getcode() != 200:
    print "At least one of your services isn't running! Check with slapos node"
    print "restart a service with slapos node restart slappart:service"

def info(software_release):
  if get_build_status():
    print get_connection_information(software_release)
  else:
    print "Information unavailable at this time, run " + sys.argv[0] + " -s for details"

def usage():
  print ("Get the status and information of your ERP5 build\n"
         "Usage:")
  print ("  --help    (-h):  Print this message and exit\n"
         "  --status  (-s):  Print the status of the build\n"
         "  --info    (-i):  Print the partition tables\n"
         "  --dump    (-d):  Dump the entire database (alias for slapos proxy show)\n") 

def dump():
  subprocess.call(["slapos", "proxy", "show", "-u", "/opt/slapos/slapproxy.db"])

def main(argv):
  # parse command line options
  try:
    opts, args = getopt.getopt(argv, "sihd", ["status", "info", "help", "dump"])
  except getopt.error, msg:
    usage()
    sys.exit(2)
  if len(opts) == 0:
    usage()
    sys.exit(2)
  # process arguments
  for opt, arg in opts:
    if opt in ("-h", "--help"):
       usage()
       sys.exit()
    elif opt in ("-s", "--status"):
      check_tables()
      for sr in discover_software():
        status(sr)
    elif opt in ("-i", "--info"):
      check_tables()
      for sr in discover_software():
        info(sr)
    elif opt in ("-d", "--dump"):
      dump()
 
if __name__ == "__main__":
  main(sys.argv[1:])