from parallels.source.hsphere import messages
import logging
import posixpath
from contextlib import closing

from parallels.core.actions.base.subscription_action import SubscriptionAction
from parallels.source.hsphere.remote_script import HsphereRunner
from parallels.core import MigrationError
from parallels.core.utils.migrator_utils import copy_directory_content_unix
from parallels.core.utils import ssh_utils
from parallels.core.utils import subscription_filter
from parallels.core.utils import unix_utils


logger = logging.getLogger(__name__)


class CopyUnixWebContent(SubscriptionAction):
	def get_description(self):
		return messages.COPY_WEB_FILES_FROM_UNIX_SERVERS

	def get_failure_message(self, global_context, subscription):
		return messages.FAILED_TO_COPY_WEB_FILES % subscription.name

	def is_critical(self):
		"""If action is critical or not

		If action is critical and it failed for a subscription, migration tool
		won't run the next operations for the subscription.

		:rtype: bool
		"""
		return False

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

	def run(self, global_context, subscription):
		logger.debug(messages.GET_HTTPDOCS_ON_TARGET_NODE % subscription.name)

		source_server = subscription.web_source_server
		target_server = subscription.web_target_server

		source_ip = source_server.ip()

		logger.debug(messages.GET_HTTPDOCS_ON_SOURCE % 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(
					messages.CANNOT_DETERMINE_IP_ADDRESS_OF_SUBSCRIPTION % subscription.name
				)
			l_server_ip = ip_row[0]
			logger.debug(messages.DETECTED_SUBSCRIPTIONS_SERVER_IP % l_server_ip)
			if source_server.ip() != l_server_ip:
				logger.debug(messages.CHANGE_SOURCE_IP_ADDRESS % (source_server.ip(), l_server_ip))
				source_ip = l_server_ip

		logger.debug(messages.COPY_CONTENT_FOR_MAIN_DOMAIN % subscription.name)
		sysuser_name = subscription.converted_backup.get_phosting_sysuser_name()
		if sysuser_name is None:
			logger.debug(messages.SUBSCRIPTION_HAS_NO_SYSUSER % 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)

				# It would be better to take the same logic as here:
				# parallels.core.actions.content.web.copy_unix_content_base.CopyUnixWebContentBase
				# but now we simply check H-Sphere Debian -> PPA CentOS case
				if unix_utils.is_debian(hsphere_runner):

					user_mapping = {'www-data': 'apache'}
					group_mapping = {'www-data': 'apache'}
				else:
					user_mapping = {}
					group_mapping = {}

				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,
							exclude=['logs'],
							user_mapping=user_mapping,
							group_mapping=group_mapping,
						)
					except Exception as e:
						logger.debug(u"Exception: ", exc_info=e)
						raise MigrationError((
							messages.RSYNC_FAILED_TO_COPY_FILES_FROM_SOURCE) % (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
				)
			)
