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
