from parallels.core.actions.base.common_action import CommonAction
from parallels.plesk.utils.xml_rpc.plesk.core import PleskError
from parallels.plesk.utils.xml_rpc.plesk.operator import DnsOperator
from parallels.plesk.source.plesk import messages


class AddSourceToTargetDNSACL(CommonAction):
	def get_description(self):
		return messages.ACTION_ADD_SOURCE_SERVER_TO_TARGET_DNS_ACL_DESCRIPTION

	def get_failure_message(self, global_context):
		"""
		:type global_context: parallels.core.global_context.GlobalMigrationContext
		"""
		return messages.ACTION_ADD_SOURCE_SERVER_TO_TARGET_DNS_ACL_FAILURE

	def filter_action(self, global_context):
		"""Check whether we should run this action or not. By default True - action should be executed.

		:type global_context: parallels.core.global_context.GlobalMigrationContext
		:rtype: bool
		"""
		return not global_context.conn.target.is_windows

	def run(self, global_context):
		"""
		:type global_context: parallels.core.global_context.GlobalMigrationContext
		"""
		api = global_context.conn.target.plesk_api()

		source_dns_ips = set()
		for subscription in global_context.iter_all_subscriptions():
			source_dns_ips.update(subscription.source_dns_ips)

		if len(source_dns_ips) == 0:
			return

		results = api.send(
			DnsOperator.AddToACL(
				filter=DnsOperator.FilterByHost(source_dns_ips)
			)
		)

		for result in results:
			try:
				result.check()
			except PleskError as e:
				if e.code == 1007:
					# Ignore situation when IP address already exists.
					pass
				else:
					raise
