import logging
import posixpath
from contextlib import closing

from parallels.common.actions.base.subscription_action import SubscriptionAction
from parallels.hsphere_migrator.remote_script import HsphereRunner
from parallels.common import MigrationError
from parallels.common.utils.migrator_utils import copy_directory_content_unix
from parallels.common.utils import ssh_utils
from parallels.common.utils import subscription_filter

logger = logging.getLogger(__name__)

class CopyUnixWebContent(SubscriptionAction):
	def get_description(self):
		return "Copy web files from Unix servers"

	def get_failure_message(self, global_context, subscription):
		return "Failed to copy web files for subscription '%s'" % (subscription.name)

	def filter_subscription(self, global_context, subscription):
		return subscription_filter.unix_with_virtual_hosting(
			subscription
		)

	def run(self, global_context, subscription):
		logger.debug(u"Get httpdocs of '%s' subscription on target node" % subscription.name)

		source_server = subscription.web_source_server
		target_server = subscription.web_target_server

		source_ip = source_server.ip()

		logger.debug(u"Get httpdocs of %s subscription on H-Sphere" % subscription.name)
		with closing(global_context.conn.hsphere.db()) as cursor:
			cursor.execute(u""" SELECT dir FROM domains
				JOIN parent_child ON domains.id = parent_child.child_id
				JOIN unix_user ON unix_user.id = parent_child.parent_id
				WHERE
					domains.name = '%s'
			""" % subscription.name)
			source_path = cursor.fetchone()[0]

			cursor.execute(u""" SELECT l_server_ips.ip FROM domains
				JOIN parent_child ON parent_child.parent_id = domains.id
				JOIN apache_vhost ON apache_vhost.id = parent_child.child_id
				JOIN l_server_ips ON l_server_ips.l_server_id = apache_vhost.host_id
				WHERE
					parent_child.child_type = 9
					AND domains.name = '%s'
			""" % subscription.name)
			# 9 - Hosting
			ip_row = cursor.fetchone()
			if ip_row is None:
				raise MigrationError(u"Can not determine IP address of '%s' subscription. Most probably reason: subscription has not hosting." % subscription.name)
			l_server_ip = ip_row[0]
			logger.debug(u"Detected subscription's server ip - '%s'" % l_server_ip)
			if source_server.ip() != l_server_ip:
				logger.debug(u"Change source ip address from '%s' to '%s'" % (source_server.ip(), l_server_ip))
				source_ip = l_server_ip

		logger.debug(u"Copy content for main domain for '%s' subscription." % subscription.name)
		sysuser_name = subscription.converted_backup.get_phosting_sysuser_name()
		if sysuser_name is None:
			logger.debug(u"'%s' subscription does not have sys user, so skip content migration." % subscription.name)
			return

		logger.debug(u"'%s' subscription's sys user: '%s'." % (subscription.name, sysuser_name))

		target_path = posixpath.join(
			target_server.vhosts_dir, subscription.name_idn
		)
		logger.debug(u"Source path: %s", source_path)
		logger.debug(u"Target path: %s", subscription)
		with source_server.runner() as runner_source:
			with target_server.runner() as runner_target:
				hsphere_runner = HsphereRunner(runner_source, source_ip)
				with ssh_utils.public_key_ssh_access_runner(
					runner_target, hsphere_runner
				) as key_pathname:
					try:
						copy_directory_content_unix(
							source_ip,
							source_server.user(),
							hsphere_runner,
							runner_target,
							source_path,
							target_path,
							key_pathname,
							['logs'] # exclude list
						)
					except Exception as e:
						logger.debug(u"Exception: ", exc_info=e)
						raise MigrationError((
							u"Rsync failed to copy files from the source (%s) to the target server (%s): %s\n"
							u"""1. This could happen because of a network connection issue. Retry copying the files with the help of the "copy-content" command.\n"""
							u"2. Check whether rsync is installed and configured on the source server."
						) % (source_ip, target_server.description(), str(e)))

		with target_server.runner() as runner_target:
			vhost_dir = posixpath.join(target_server.vhosts_dir, subscription.name_idn)
			runner_target.sh(u'/usr/bin/find %s -type d -user %s -not -group root -not -group psaserv -exec chown :psacln {} \; -exec chmod o+rx {} \;' % (
				vhost_dir, sysuser_name
			))
			runner_target.sh(u'/usr/bin/find %s -type f -user %s -not -group root -not -group psaserv -exec chown :psacln {} \; -exec chmod o+r {} \;' % (
				vhost_dir, sysuser_name
			))
