#!/usr/bin/env python

# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you 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.


import os,logging,sys
from optparse import OptionParser
import MySQLdb
import subprocess
import glob

# ---- This snippet of code adds the sources path and the waf configured PYTHONDIR to the Python path ----
# ---- We do this so cloud_utils can be looked up in the following order:
# ---- 1) Sources directory
# ---- 2) waf configured PYTHONDIR
# ---- 3) System Python path
for pythonpath in (
		"@PYTHONDIR@",
		os.path.join(os.path.dirname(__file__),os.path.pardir,os.path.pardir,"python","lib"),
	):
		if os.path.isdir(pythonpath): sys.path.insert(0,pythonpath)
# ---- End snippet of code ----
from cloud_utils import check_selinux, CheckFailed, resolves_to_ipv6
import cloud_utils

# RUN ME LIKE THIS
# python setup/bindir/cloud-migrate-databases.in --config=client/tomcatconf/override/db.properties --resourcedir=setup/db  --dry-run
# --dry-run makes it so the changes to the database in the context of the migrator are rolled back

# This program / library breaks down as follows:
#   high-level breakdown:
#   the module calls main()
#   main processes command-line options
#   main() instantiates a migrator with a a list of possible migration steps
#   migrator discovers and topologically sorts migration steps from the given list
#   main() run()s the migrator
#      for each one of the migration steps:
#          the migrator instantiates the migration step with the context as first parameter
#          the instantiated migration step saves the context onto itself as self.context
#          the migrator run()s the instantiated migration step.  within run(), self.context is the context
#      the migrator commits the migration context to the database (or rollsback if --dry-run is specified)
#   that is it

# The specific library code is in cloud_utils.py
# What needs to be implemented is MigrationSteps
# Specifically in the FromInitialTo21 evolver.
# What Db20to21MigrationUtil.java does, needs to be done within run() of that class
# refer to the class docstring to find out how
# implement them below

class CloudContext(cloud_utils.MigrationContext):
	def __init__(self,host,port,username,password,database,configdir,resourcedir):
		self.host = host
		self.port = port
		self.username = username
		self.password = password
		self.database = database
		self.configdir = configdir
		self.resourcedir = resourcedir
		self.conn = MySQLdb.connect(host=self.host,
			user=self.username,
			passwd=self.password,
			db=self.database,
			port=self.port)
		self.conn.autocommit(False)
		self.db = self.conn.cursor()
		def wrapex(func):
			sqlogger = logging.getLogger("SQL")
			def f(stmt,parms=None):
				if parms: sqlogger.debug("%s | with parms %s",stmt,parms)
				else: sqlogger.debug("%s",stmt)
				return func(stmt,parms)
			return f
		self.db.execute = wrapex(self.db.execute)
	
	def __str__(self):
		return "CloudStack %s database at %s"%(self.database,self.host)
	
	def get_schema_level(self):
		return self.get_config_value('schema.level') or cloud_utils.INITIAL_LEVEL
	
	def set_schema_level(self,l):
		self.db.execute(
		"INSERT INTO configuration (category,instance,component,name,value,description) VALUES ('Hidden', 'DEFAULT', 'database', 'schema.level', %s, 'The schema level of this database') ON DUPLICATE KEY UPDATE value = %s", (l,l)
		)
		self.commit()

	def commit(self):
		self.conn.commit()
		#self.conn.close()
		
	def close(self):
		self.conn.close()
		
	def get_config_value(self,name):
		self.db.execute("select value from configuration where name = %s",(name,))
		try: return self.db.fetchall()[0][0]
		except IndexError: return
		
	def run_sql_resource(self,resource):
		sqlfiletext = file(os.path.join(self.resourcedir,resource)).read(-1)
		sqlstatements = sqlfiletext.split(";")
		for stmt in sqlstatements:
			if not stmt.strip(): continue # skip empty statements
			self.db.execute(stmt)


class FromInitialTo21NewSchema(cloud_utils.MigrationStep):
	def __str__(self): return "Altering the database schema"
	from_level = cloud_utils.INITIAL_LEVEL
	to_level = "2.1-01"
	def run(self): self.context.run_sql_resource("schema-20to21.sql")

class From21NewSchemaTo21NewSchemaPlusIndex(cloud_utils.MigrationStep):
	def __str__(self): return "Altering indexes"
	from_level = "2.1-01"
	to_level = "2.1-02"
	def run(self): self.context.run_sql_resource("index-20to21.sql")

class From21NewSchemaPlusIndexTo21DataMigratedPart1(cloud_utils.MigrationStep):
	def __str__(self): return "Performing data migration, stage 1"
	from_level = "2.1-02"
	to_level = "2.1-03"
	def run(self):	self.context.run_sql_resource("data-20to21.sql")

class From21step1toTo21datamigrated(cloud_utils.MigrationStep):
	def __str__(self): return "Performing data migration, stage 2"
	from_level = "2.1-03"
	to_level = "2.1-04"
	
	def run(self):
		systemjars = "@SYSTEMJARS@".split()
		pipe = subprocess.Popen(["build-classpath"]+systemjars,stdout=subprocess.PIPE)
		systemcp,throwaway = pipe.communicate()
		systemcp = systemcp.strip()
		if pipe.wait(): # this means that build-classpath failed miserably
			systemcp = "@SYSTEMCLASSPATH@"
		pcp = os.path.pathsep.join( glob.glob( os.path.join ( "@PREMIUMJAVADIR@" , "*" ) ) )
		mscp = "@MSCLASSPATH@"
		depscp = "@DEPSCLASSPATH@"
		migrationxml = "@SERVERSYSCONFDIR@"
		conf = self.context.configdir
		cp = os.path.pathsep.join([pcp,systemcp,depscp,mscp,migrationxml,conf])
		cmd = ["java"]
		cmd += ["-cp",cp]
		cmd += ["com.cloud.migration.Db20to21MigrationUtil"]
		logging.debug("Running command: %s"," ".join(cmd))
		subprocess.check_call(cmd)

class From21datamigratedTo21postprocessed(cloud_utils.MigrationStep):
	def __str__(self): return "Postprocessing migrated data"
	from_level = "2.1-04"
	to_level = "2.1"
	def run(self): self.context.run_sql_resource("postprocess-20to21.sql")

class From21To213(cloud_utils.MigrationStep):
	def __str__(self): return "Dropping obsolete indexes"
	from_level = "2.1"
	to_level = "2.1.3"
	def run(self): self.context.run_sql_resource("index-212to213.sql")

class From213To22data(cloud_utils.MigrationStep):
	def __str__(self): return "Migrating data"
	from_level = "2.1.3"
	to_level = "2.2-01"
	def run(self): self.context.run_sql_resource("data-21to22.sql")

class From22dataTo22(cloud_utils.MigrationStep):
	def __str__(self): return "Migrating indexes"
	from_level = "2.2-01"
	to_level = "2.2"
	def run(self): self.context.run_sql_resource("index-21to22.sql")

# command line harness functions

def setup_logging(level):
	l = logging.getLogger()
	l.setLevel(level)
	h = logging.StreamHandler(sys.stderr)
	l.addHandler(h)


def setup_optparse():
	usage = \
"""%prog [ options ... ]

This command migrates the CloudStack database."""
	parser = OptionParser(usage=usage)
	parser.add_option("-c", "--config", action="store", type="string",dest='configdir',
		default=os.path.join("@MSCONF@"),
		help="Configuration directory with a db.properties file, pointing to the CloudStack database")
	parser.add_option("-r", "--resourcedir", action="store", type="string",dest='resourcedir',
		default="@SETUPDATADIR@",
		help="Resource directory with database SQL files used by the migration process")
	parser.add_option("-d", "--debug", action="store_true", dest='debug',
		default=False,
		help="Increase log level from INFO to DEBUG")
	parser.add_option("-e", "--dump-evolvers", action="store_true", dest='dumpevolvers',
		default=False,
		help="Dump evolvers in the order they would be executed, but do not run them")
	#parser.add_option("-n", "--dry-run", action="store_true", dest='dryrun',
		#default=False,
		#help="Run the process as it would normally run, but do not commit the final transaction, so database changes are never saved")
	parser.add_option("-f", "--start-at-level", action="store", type="string",dest='fromlevel',
		default=None,
		help="Rather than discovering the database schema level to start from, start migration from this level.  The special value '-' (a dash without quotes) represents the earliest schema level")
	parser.add_option("-t", "--end-at-level", action="store", type="string",dest='tolevel',
		default=None,
		help="Rather than evolving the database to the most up-to-date level, end migration at this level")
	return parser


def main(*args):
	"""The entry point of this program"""
	
	parser = setup_optparse()
	opts, args = parser.parse_args(*args)
	if args: parser.error("This command accepts no parameters")

	if opts.debug: loglevel = logging.DEBUG
	else: loglevel = logging.INFO
	setup_logging(loglevel)
	
	# FIXME implement
	opts.dryrun = False

	configdir = opts.configdir
	resourcedir = opts.resourcedir
	
	try:
		props = cloud_utils.read_properties(os.path.join(configdir,'db.properties'))
	except (IOError,OSError),e:
		logging.error("Cannot read from config file: %s",e)
		logging.error("You may want to point to a specific config directory with the --config= option")
		return 2
	
	if not os.path.isdir(resourcedir):
		logging.error("Cannot find directory with SQL files %s",resourcedir)
		logging.error("You may want to point to a specific resource directory with the --resourcedir= option")
		return 2
	
	host = props["db.cloud.host"]
	port = int(props["db.cloud.port"])
	username = props["db.cloud.username"]
	password = props["db.cloud.password"]
	database = props["db.cloud.name"]
	
	# tell the migrator to load its steps from the globals list
	migrator = cloud_utils.Migrator(globals().values())
	
	if opts.dumpevolvers:
		print "Evolution steps:"
		print "	%s	%s	%s"%("From","To","Evolver in charge")
		for f,t,e in migrator.get_evolver_chain():
			print "	%s	%s	%s"%(f,t,e)
		return
	
	#initialize a context with the read configuration
	context = CloudContext(host=host,port=port,username=username,password=password,database=database,configdir=configdir,resourcedir=resourcedir)
	try:
	    try:
		migrator.run(context,dryrun=opts.dryrun,starting_level=opts.fromlevel,ending_level=opts.tolevel)
	    finally:
		context.close()
	except (cloud_utils.NoMigrationPath,cloud_utils.NoMigrator),e:
		logging.error("%s",e)
		return 4

if __name__ == "__main__":
	retval = main()
	if retval: sys.exit(retval)
	else: sys.exit()
