from parallels.core import messages
import logging

from parallels.source.plesk.actions.suspend_subscriptions import SuspendSubscriptions
from parallels.core.actions.hosting_settings.check.check_database_conflicts import CheckDatabaseConflicts
from parallels.core.actions.hosting_settings.convert.cleanup_xml_for_ppa import CleanupBackupXMLForPPA
from parallels.core.actions.hosting_settings.convert.fix_windows_php53_isapi import FixWindowsPHP53ISAPI
from parallels.core.actions.hosting_settings.import_backups import ImportBackups
from parallels.core.actions.hosting_settings.remove_imported_backups import RemoveImportedBackups
from parallels.core.actions.hosting_settings.reset_hosting_for_nohosting_subscription import \
	ResetHostingForSubscriptionWithoutHosting
from parallels.core.actions.hosting_settings.restore_catch_all_smartermail_assimilate import \
	RestoreCatchAllSmartermailAssimilate
from parallels.core.actions.hosting_settings.restore_subscription_hosting_settings import \
	RestoreSubscriptionHostingSettings
from parallels.core.actions.hosting_settings.verify import VerifyHostingSettings
from parallels.core.actions.import_plans_not_supported import ImportPlansNotSupported
from parallels.core.actions.migration_list.check_migration_list_not_exists_for_generation import CheckMigrationListNotExistsForGeneration
from parallels.core.actions.migration_list.check_migration_list_exists_for_migration import CheckMigrationListExistsForMigration
from parallels.core.actions.migration_list.generate import GenerateMigrationList
from parallels.core.actions.print_subscription_status import PrintSubscriptionStatus
from parallels.core.actions.quick_check_cli_options import QuickCheckCLIOptions
from parallels.core.actions.read_ip_mapping import ReadIPMapping
from parallels.core.actions.restore.import_clients_and_subscriptions import ImportClientsAndSubscriptions
from parallels.core.actions.shutdown_windows_agents import ShutdownWindowsAgents
from parallels.core.actions.shutdown_windows_rsync_servers import ShutdownWindowsRsyncServers
from parallels.core.workflow.base_workflow import BaseWorkflow
from parallels.core.actions.utils.logging_properties \
	import LoggingProperties
from parallels.core.actions.base.legacy_action \
	import LegacyAction
from parallels.core.actions.base.compound_action \
	import CompoundAction
from parallels.core.actions.base.entry_point_action \
	import EntryPointAction
from parallels.core.actions.close_ssh_connections import CloseSSHConnections
from parallels.core.actions.hosting_settings.convert.dns \
	import DNS as ActionHostingSettingsConvertDNS
from parallels.source.plesk.actions.content.web.check_target_web_hosting \
	import CheckTargetWebHosting
from parallels.core.actions.backup.create_converted \
	import CreateConverted
from parallels.core.actions.backup.save_converted \
	import SaveConverted
from parallels.core.actions.backup.remove_content \
	import RemoveContent
from parallels.core.actions.hosting_settings.convert.remap_databases \
	import RemapDatabases
from parallels.core.actions.hosting_settings.convert.remove_subscription_to_plan_relation \
	import RemoveSubscriptionToPlanRelation
from parallels.core.actions.hosting_settings.convert.remove_subscription_default_db_server \
	import RemoveSubscriptionDefaultDBServer
from parallels.core.actions.hosting_settings.convert.remove_subscription_limits_and_permissions \
	import RemoveSubscriptionLimitsAndPermissions
from parallels.core.actions.hosting_settings.convert.remove_maillists \
	import RemoveMaillists
from parallels.core.actions.hosting_settings.convert.remove_domain_keys \
	import RemoveDomainKeys
from parallels.core.actions.hosting_settings.convert.change_webmail_to_horde \
	import ChangeWebmailToHorde
from parallels.core.actions.hosting_settings.convert.remove_disabled_mailsystem_without_resource \
	import RemoveDisabledMailsystemWithoutResource
from parallels.core.actions.hosting_settings.convert.change_catch_all_redirect \
	import ChangeCatchAllRedirect
from parallels.core.actions.hosting_settings.convert.change_subscription_ips \
	import ChangeSubscriptionIPs
from parallels.core.actions.hosting_settings.convert.remove_subscription_external_id \
	import RemoveSubscriptionExternalId
from parallels.core.actions.hosting_settings.convert.change_sysuser_password \
	import ChangeSysuserPassword
from parallels.core.actions.hosting_settings.convert.change_smartermail_password \
	import ChangeSmartermailPassword
from parallels.core.actions.hosting_settings.convert.remove_smartermail_unsupported_features \
	import RemoveSmartermailUnsupportedFeatures
from parallels.core.actions.hosting_settings.convert.change_sysuser_login \
	import ChangeSysuserLogin
from parallels.core.actions.hosting_settings.restore_sysuser_logins \
	import RestoreSysuserLogins
from parallels.core.actions.hosting_settings.check.catch_all_redirect \
	import CatchAllRedirect
from parallels.core.actions.hosting_settings.check.email_empty_password \
	import EmailEmptyPassword
from parallels.core.actions.hosting_settings.check.maillists \
	import Maillists
from parallels.core.actions.dns.forwarding.set_dns_forwarding_not_supported \
	import SetDNSForwardingNotSupported
from parallels.core.actions.dns.forwarding.undo_dns_forwarding_not_supported \
	import UndoDNSForwardingNotSupported
from parallels.core.actions.dns.timings.set_dns_timings_not_supported \
	import SetDNSTimingsNotSupported
from parallels.core.actions.remove_ssh_keys \
	import RemoveSSHKeys
from parallels.core.actions.content.mail.copy_content \
	import CopyMailContent
from parallels.core.actions.content.database.copy_database_content \
	import CopyDatabaseContent
from parallels.core.utils.backup_adapter import SubscriptionBackup
from parallels.core.utils.backup_adapter import SubscriptionBackupRaw
from parallels.core.actions.apache_restart_interval.restore import RestoreApacheRestartInterval
from parallels.core.actions.apache_restart_interval.set import SetApacheRestartInterval
from parallels.core.actions.hosting_analyser.analyse import AnalyseHosting
from parallels.core.actions.uninstall_dump_agent import UninstallDumpAgentAction

logger = logging.getLogger(__name__)


class SharedHostingWorkflow(BaseWorkflow):
	"""Common workflow for shared hosting migration"""

	def __init__(self):
		super(SharedHostingWorkflow, self).__init__()

		self._configure_shared_actions()
		self._configure_entry_points()

	def _configure_shared_actions(self):
		self._configure_shared_action_fetch_source()
		self._configure_shared_action_fetch_source_shallow()
		self._configure_shared_action_fetch_target()
		self._configure_shared_action_check_infrastructure()
		self._configure_shared_action_sync_web_content_assets()
		self._configure_shared_action_copy_web_files()
		self._configure_shared_action_copy_web_content()
		self._configure_shared_action_copy_mail_content()
		self._configure_shared_action_analyse_hosting()
		self._configure_shared_action_cleanup()
		self._configure_shared_action_copy_db_content()
		self._configure_shared_action_copy_content()
		self._configure_shared_action_check_updates()
		self._configure_shared_action_check_connections()
		self._configure_shared_action_check_sources()
		self._configure_shared_action_check_target()
		self._configure_shared_action_check_target_licenses()
		self._configure_shared_action_read_migration_list()
		self._configure_shared_action_read_ip_mapping()
		self._configure_shared_action_convert()
		self._configure_shared_action_convert_silent()
		self._configure_shared_action_verify_hosting()
		self._configure_shared_action_finalize()
		self._configure_shared_action_convert_hosting()
		self._configure_shared_action_initial_pre_checks()
		self._configure_shared_action_post_migration_finalize()
		self._configure_shared_action_post_migration_prepare()

	def _configure_entry_points(self):
		self._configure_entry_point_analyse_hosting()
		self._configure_entry_point_generate_migration_list()
		self._configure_entry_point_check()
		self._configure_entry_point_check_infrastructure()
		self._configure_entry_point_import_resellers()
		self._configure_entry_point_import_plans()
		self._configure_entry_point_transfer_accounts()
		self._configure_entry_point_copy_content()
		self._configure_entry_point_copy_mail_content()
		self._configure_entry_point_copy_web_content()
		self._configure_entry_point_copy_db_content()
		self._configure_entry_point_verify_hosting()
		self._configure_entry_point_set_dns_forwarding()
		self._configure_entry_point_undo_dns_forwarding()
		self._configure_entry_point_set_low_dns_timings()
		self._configure_entry_point_test_all()
		self._configure_entry_point_test_sites()
		self._configure_entry_point_test_dns()
		self._configure_entry_point_test_mail()
		self._configure_entry_point_test_users()
		self._configure_entry_point_test_databases()
		self._configure_entry_point_test_services()

	def _configure_shared_action_fetch_source(self):
		self.add_shared_action('fetch-source', CompoundAction(
			description=messages.FETCH_INFORMATION_FROM_SOURCE_PANEL))

	def _configure_shared_action_fetch_source_shallow(self):
		# By default, consider shallow backup is the same as full backup,
		# and fetch source shallow is the same as fetch source
		self.add_shared_action(
			'fetch-source-shallow',
			self.get_shared_action('fetch-source')
		)

	def _configure_shared_action_fetch_target(self):
		self.add_shared_action('fetch-target', LegacyAction(
			description=messages.FETCH_INFORMATION_FROM_TARGET_SERVERS,
			function=lambda ctx: ctx.migrator._fetch(ctx.options, ctx.options.reload_source_data)
		))

	def _configure_shared_action_check_infrastructure(self):
		self.add_shared_action('check-infrastructure', LegacyAction(
			description=messages.CHECK_INFRASTRUCTURE_CONNECTIONS_AND_DISK_SPACE,
			function=lambda ctx: ctx.migrator.check_infrastructure(ctx.options)
		))

	def _configure_shared_action_copy_content(self):
		self.add_shared_action('copy-content', CompoundAction(
			description=messages.COPY_WEB_DATABASE_AND_MAIL_CONTENT,
			run_by_subscription=True
		))
		self.get_shared_action('copy-content').insert_action(
			'web', self.get_shared_action_pointer('copy-web-content')
		)
		self.get_shared_action('copy-content').insert_action(
			'database', self.get_shared_action_pointer('copy-db-content')
		)
		self.get_shared_action('copy-content').insert_action(
			'mail', self.get_shared_action_pointer('copy-mail-content')
		)

	def _configure_shared_action_copy_web_files(self):
		self.add_shared_action('copy-web-files', CompoundAction(
			description='Copy web files'
		))

	def _configure_shared_action_copy_web_content(self):
		self.add_shared_action('copy-web-content', CompoundAction(
			description=messages.COPY_WEB_FILES_AND_SYNC_WEB))
		self.get_shared_action('copy-web-content').insert_action(
			'copy-web-files', self.get_shared_action('copy-web-files')
		)
		self.get_shared_action('copy-web-content').insert_action(
			'web-assets', self.get_shared_action('sync-web-content-assets')
		)

	def _configure_shared_action_sync_web_content_assets(self):
		self.add_shared_action('sync-web-content-assets', CompoundAction(
			description='Sync web content assets'
		))

	def _configure_shared_action_copy_mail_content(self):
		self.add_shared_action('copy-mail-content', CopyMailContent())

	def _configure_shared_action_analyse_hosting(self):
		self.add_shared_action('analyse-hosting', AnalyseHosting())

	def _configure_shared_action_cleanup(self):
		self.add_shared_action('cleanup', CompoundAction(
			description='Perform final clean up',
			logging_properties=LoggingProperties(compound=False)
		))
		self.get_shared_action('cleanup').insert_action(
			'uninstall-agent', UninstallDumpAgentAction()
		)
		self.get_shared_action('cleanup').insert_action(
			'remove-ssh-keys', RemoveSSHKeys()
		)
		self.get_shared_action('cleanup').insert_action(
			'close-ssh-connections', CloseSSHConnections()
		)
		self.get_shared_action('cleanup').insert_action(
			'shutdown-windows-rsync-servers', ShutdownWindowsRsyncServers()
		)
		self.get_shared_action('cleanup').insert_action(
			'shutdown-windows-agents', ShutdownWindowsAgents()
		)

	def _configure_shared_action_copy_db_content(self):
		self.add_shared_action('copy-db-content', CopyDatabaseContent())

	def _configure_shared_action_check_updates(self):
		self.add_shared_action('check-updates', LegacyAction(
			description='Check migrator updates',
			function=lambda ctx: ctx.migrator._check_updates(),
			is_critical=False
		))

	def _configure_shared_action_check_connections(self):
		self.add_shared_action('check-connections', LegacyAction(
			description='Check connections',
			function=lambda ctx: ctx.migrator._check_connections(ctx.options)
		))

	def _configure_shared_action_check_sources(self):
		self.add_shared_action('check-sources', LegacyAction(
			description='Check source connections',
			function=lambda ctx: ctx.migrator._check_sources()
		))

	def _configure_shared_action_check_target(self):
		self.add_shared_action('check-target', LegacyAction(
			description='Check target connections',
			function=lambda ctx: ctx.migrator._check_target()
		))

	def _configure_shared_action_check_target_licenses(self):
		self.add_shared_action('check-target-licenses', LegacyAction(
			description=messages.CHECK_LICENSES_TARGET_SERVERS,
			function=lambda ctx: ctx.migrator._check_target_licenses(ctx.options)
		))

	def _configure_shared_action_read_migration_list(self):
		self.add_shared_action('read-migration-list', LegacyAction(
			description='Read migration list',
			function=lambda ctx: ctx.migrator._read_migration_list_lazy(ctx.options)
		))

	def _configure_shared_action_read_ip_mapping(self):
		self.add_shared_action('read-ip-mapping', ReadIPMapping())

	def _configure_shared_action_convert(self):
		self.add_shared_action('convert', LegacyAction(
			description=messages.CONVERT_CLIENTS_AND_SUBSCRIPTIONS,
			function=lambda ctx: ctx.migrator.convert(ctx.options)
		))

	def _configure_shared_action_convert_silent(self):
		self.add_shared_action('convert-silent', LegacyAction(
			description=messages.CONVERT_CLIENTS_AND_SUBSCRIPTIONS_1,
			function=lambda ctx: ctx.migrator.convert(
				ctx.options,  # we do not want to see pre-migration and conversion
				# messages when calling commands except for  # 'transfer-accounts' and 'check', because user
				# should already executed 'transfer-accounts',  # or 'check' commands, which displayed these messages
				merge_pre_migration_report=False
			)
		))

	def _configure_shared_action_verify_hosting(self):
		self.add_shared_action('verify-hosting', VerifyHostingSettings())

	def _configure_shared_action_finalize(self):
		self.add_shared_action('finalize', LegacyAction(
			description=messages.COUNT_MIGRATION_STATISTICS_PRINT_REPORT,
			function=lambda ctx: ctx.migrator._finalize(True, ctx.options),
			logging_properties=LoggingProperties(info_log=False),
			is_critical=False,
		))

	def _configure_shared_action_post_migration_prepare(self):
		self.add_shared_action('post-migration-prepare', CompoundAction())
		self.get_shared_action('post-migration-prepare').insert_action(
			'check-migration-list', CheckMigrationListExistsForMigration()
		)
		self.get_shared_action('post-migration-prepare').insert_actions(
			self.get_shared_action('initial-pre-checks').get_all_actions()
		)
		self.get_shared_action('post-migration-prepare').insert_action(
			'fetch-source-shallow',
			self.get_shared_action_pointer('fetch-source-shallow')
		)
		self.get_shared_action('post-migration-prepare').insert_action(
			'read-migration-list',
			self.get_shared_action_pointer('read-migration-list')
		)
		self.get_shared_action('post-migration-prepare').insert_action(
			'read-ip-mapping',
			self.get_shared_action_pointer('read-ip-mapping')
		)
		self.get_shared_action('post-migration-prepare').insert_action(
			'fetch-source',
			self.get_shared_action('fetch-source')
		)
		self.get_shared_action('post-migration-prepare').insert_action(
			'fetch-target',
			self.get_shared_action_pointer('fetch-target')
		)
		self.get_shared_action('post-migration-prepare').insert_action(
			'read-migration-list',
			self.get_shared_action('read-migration-list')
		)
		self.get_shared_action('post-migration-prepare').insert_action(
			'convert',
			self.get_shared_action_pointer('convert-silent')
		)
		self.get_shared_action('post-migration-prepare').insert_action(
			'convert',
			self.get_shared_action_pointer('convert-hosting')
		)

	def _configure_shared_action_post_migration_finalize(self):
		self.add_shared_action('post-migration-finalize', CompoundAction())
		self.get_shared_action('post-migration-finalize').insert_action(
			'cleanup', self.get_shared_action('cleanup')
		)
		self.get_shared_action('post-migration-finalize').insert_action(
			'finalize',
			self.get_shared_action('finalize')
		)

	def _configure_shared_action_initial_pre_checks(self):
		self.add_shared_action('initial-pre-checks', CompoundAction())
		self.get_shared_action('initial-pre-checks').insert_action(
			'check-cli-options', QuickCheckCLIOptions()
		)
		self.get_shared_action('initial-pre-checks').insert_action(
			'check-updates',
			self.get_shared_action('check-updates')
		)
		self.get_shared_action('initial-pre-checks').insert_action(
			'check-connections',
			self.get_shared_action_pointer('check-connections')
		)
		self.get_shared_action('initial-pre-checks').insert_action(
			'check-target-licenses',
			self.get_shared_action('check-target-licenses')
		)

	def _configure_entry_point_generate_migration_list(self):
		self.add_entry_point('generate-migration-list', EntryPointAction())

		self.get_path('generate-migration-list').insert_action(
			'check-migration-list-exists', CheckMigrationListNotExistsForGeneration()
		)
		self.get_path('generate-migration-list').insert_action(
			'check-updates',
			self.get_shared_action('check-updates')
		)
		self.get_path('generate-migration-list').insert_action(
			'check-connections',
			self.get_shared_action_pointer('check-connections')
		)
		self.get_path('generate-migration-list').insert_action(
			'check-target-licenses',
			self.get_shared_action('check-target-licenses')
		)
		self.get_path('generate-migration-list').insert_action(
			'fetch-source',
			self.get_shared_action_pointer('fetch-source-shallow')
		)
		self.get_path('generate-migration-list').insert_action(
			'generate-migration-list', GenerateMigrationList(),
		)
		self.get_path('generate-migration-list').insert_action(
			'analyse-hosting', self.get_shared_action('analyse-hosting')
		)

		self.get_path('generate-migration-list').insert_action(
			'cleanup', self.get_shared_action('cleanup')
		)
		self.get_path('generate-migration-list').register_overall_shutdown('cleanup')

	def _configure_entry_point_check(self):
		self.add_entry_point('check', EntryPointAction())
		self.get_path('check').insert_action(
			'check-cli-options', QuickCheckCLIOptions()
		)
		self.get_path('check').insert_action(
			'check-migration-list', CheckMigrationListExistsForMigration()
		)
		self.get_path('check').insert_action(
			'check-updates',
			self.get_shared_action('check-updates')
		)
		self.get_path('check').insert_action(
			'check-connections',
			self.get_shared_action_pointer('check-connections')
		)
		self.get_path('check').insert_action(
			'check-target-licenses',
			self.get_shared_action('check-target-licenses')
		)
		self.get_path('check').insert_action(
			'fetch-source-shallow',
			self.get_shared_action_pointer('fetch-source-shallow')
		)
		self.get_path('check').insert_action(
			'read-migration-list',
			self.get_shared_action_pointer('read-migration-list')
		)
		self.get_path('check').insert_action(
			'read-ip-mapping',
			self.get_shared_action_pointer('read-ip-mapping')
		)
		self.get_path('check').insert_action(
			'fetch-source',
			self.get_shared_action('fetch-source')
		)
		self.get_path('check').insert_action(
			'fetch-target',
			self.get_shared_action_pointer('fetch-target')
		)
		self.get_path('check').insert_action('check-data', CompoundAction())
		self.get_path('check/check-data').insert_action('check-conflicts', LegacyAction(
			description=messages.CHECK_CONFLICTS_FOR_CLIENTS_SUBSCRIPTIONS_RESELLER,
			function=lambda ctx: ctx.migrator._convert_model(
				ctx.pre_check_report, ctx.target_existing_objects,
				ctx.options, soft_check=True
			)
		))
		self.get_path('check/check-data').insert_action(
			'check-catch-all-redirect',
			CatchAllRedirect(SubscriptionBackupRaw())
		)
		self.get_path('check/check-data').insert_action(
			'check-email-empty-password',
			EmailEmptyPassword(SubscriptionBackupRaw())
		)
		self.get_path('check/check-data').insert_action(
			'check-maillists',
			Maillists(SubscriptionBackupRaw())
		)
		self.get_path('check').insert_action(
			'cleanup', self.get_shared_action('cleanup')
		)
		self.get_path('check').insert_action(
			'print-report', LegacyAction(
				description='Print pre-migration report',
				function=lambda ctx: ctx.migrator.print_report(
					ctx.pre_check_report, "pre_migration_report_tree",
					show_no_issue_branches=False
				),
				is_critical=False
			)
		)
		self.get_path('check').register_overall_shutdown('cleanup')

	def _configure_entry_point_check_infrastructure(self):
		self.add_entry_point('check-infrastructure', EntryPointAction())
		self.get_path('check-infrastructure').insert_action(
			'check-infrastructure',
			self.get_shared_action_pointer('check-infrastructure')
		)

	def _configure_entry_point_import_resellers(self):
		self.add_entry_point('import-resellers', EntryPointAction())
		self.get_path('import-resellers').insert_actions(
			self.get_shared_action('initial-pre-checks').get_all_actions()
		)
		self.get_path('import-resellers').insert_action(
			'fetch-source',
			self.get_shared_action('fetch-source')
		)
		self.get_path('import-resellers').insert_action(
			'import-resellers',
			LegacyAction(
				description='Import resellers',
				function=lambda ctx: ctx.migrator._import_resellers(ctx.options)
			)
		)
		self.get_path('import-resellers').insert_action(
			'cleanup',
			self.get_shared_action('cleanup')
		)
		self.get_path('import-resellers').register_overall_shutdown('cleanup')

	def _configure_entry_point_import_plans(self):
		self.add_entry_point('import-plans', EntryPointAction())
		self.get_path('import-plans').insert_action(
			'check-target-panel', ImportPlansNotSupported()
		)

	def _configure_shared_action_convert_hosting(self):
		self.add_shared_action('convert-hosting', CompoundAction(
			description=messages.CONVERT_HOSTING_SETTINGS_TARGET_PANEL_FORMAT,
			run_by_subscription=False, # run by layer for better logging, no sense to run by subscription
			logging_properties=LoggingProperties(compound=False)
		))
		convert_hosting = self.get_shared_action(
			'convert-hosting'
		)
		convert_hosting.insert_actions([
			('create-converted-backup', CreateConverted(SubscriptionBackup())),
			('convert-dns', ActionHostingSettingsConvertDNS()),
			('remap-databases', RemapDatabases(SubscriptionBackup())),
			('remove-subscription-to-plan-relation', RemoveSubscriptionToPlanRelation(SubscriptionBackup())),
			('remove-subscription-default-db-server', RemoveSubscriptionDefaultDBServer(SubscriptionBackup())),
			('remove-subscription-limits-and-permissions',
				RemoveSubscriptionLimitsAndPermissions(SubscriptionBackup())),
			('remove-maillists', RemoveMaillists(SubscriptionBackup())),
			('remove-domain-keys', RemoveDomainKeys(SubscriptionBackup())),
			('change-webmail-to-horde', ChangeWebmailToHorde(SubscriptionBackup())),
			('remove-disabled-mailsystem-without-resource',
				RemoveDisabledMailsystemWithoutResource(SubscriptionBackup())),
			('change-catch-all-redirect', ChangeCatchAllRedirect(SubscriptionBackup())),
			('change-subscription-ips', ChangeSubscriptionIPs(SubscriptionBackup())),
			('remove-subscription-external-id', RemoveSubscriptionExternalId(SubscriptionBackup())),
			('change-sysuser-password', ChangeSysuserPassword(SubscriptionBackup())),
			('change-smartermail-password', ChangeSmartermailPassword(SubscriptionBackup())),
			('remove-smartermail-upsupported-features', RemoveSmartermailUnsupportedFeatures(SubscriptionBackup())),
			('fix-windows-php53-isapi', FixWindowsPHP53ISAPI(SubscriptionBackup())),
			('check-database-conflicts', CheckDatabaseConflicts(SubscriptionBackup())),
			('backup-remove-content', RemoveContent(SubscriptionBackup())),
			('cleanup-backup-xml-for-ppa', CleanupBackupXMLForPPA()),
			('save-backup', SaveConverted(SubscriptionBackup())),
			('check-catch-all-redirect', CatchAllRedirect(SubscriptionBackup())),
			('check-email-empty-password', EmailEmptyPassword(SubscriptionBackup())),
			('check-maillists', Maillists(SubscriptionBackup())),
		])

	def _configure_entry_point_transfer_accounts(self):
		self.add_entry_point('transfer-accounts', EntryPointAction())
		self.get_path('transfer-accounts').insert_action(
			'check-cli-options', QuickCheckCLIOptions()
		)
		self.get_path('transfer-accounts').insert_action(
			'check-migration-list', CheckMigrationListExistsForMigration()
		)
		self.get_path('transfer-accounts').insert_action(
			'check-updates',
			self.get_shared_action('check-updates')
		)
		self.get_path('transfer-accounts').insert_action(
			'check-connections',
			self.get_shared_action_pointer('check-connections')
		)
		self.get_path('transfer-accounts').insert_action(
			'check-target-licenses', LegacyAction(
				description=messages.CHECK_LICENSES_TARGET_SERVERS_1,
				function=lambda ctx: ctx.migrator._check_target_licenses(ctx.options)
			)
		)
		self.get_path('transfer-accounts').insert_action(
			'fetch-source-shallow',
			self.get_shared_action_pointer('fetch-source-shallow')
		)
		self.get_path('transfer-accounts').insert_action(
			'read-migration-list',
			self.get_shared_action_pointer('read-migration-list')
		)
		self.get_path('transfer-accounts').insert_action(
			'read-ip-mapping',
			self.get_shared_action_pointer('read-ip-mapping')
		)
		self.get_path('transfer-accounts').insert_action(
			'fetch-source', self.get_shared_action('fetch-source')
		)
		self.get_path('transfer-accounts').insert_action(
			'fetch-target',
			self.get_shared_action_pointer('fetch-target')
		)
		self.get_path('transfer-accounts').insert_action(
			'convert',
			self.get_shared_action_pointer('convert')
		)
		self.get_path('transfer-accounts').insert_action('check-main-node-disk-space-requirements', LegacyAction(
			description=messages.CHECK_DISK_SPACE_REQUIREMENTS_FOR_MAIN,
			function=lambda ctx: ctx.migrator.check_main_node_disk_space_requirements(ctx.options)
		))
		self.get_path('transfer-accounts').insert_action('set-apache-restart-interval', SetApacheRestartInterval())
		self.get_path('transfer-accounts').insert_action('suspend-source-subscription', SuspendSubscriptions())
		self.get_path('transfer-accounts').insert_action('restore', ImportClientsAndSubscriptions())
		self.get_path('transfer-accounts').insert_action('set-windows-security-policy', LegacyAction(
			description=messages.SET_SECURITY_POLICY_WINDOWS_NODES,
			function=lambda ctx: ctx.migrator.set_security_policy()
		))
		self.get_path('transfer-accounts').insert_action(
			'restore-hosting', CompoundAction("Restore hosting settings")
		)
		self.get_path('transfer-accounts/restore-hosting').insert_action(
			'convert-hosting',
			self.get_shared_action('convert-hosting')
		)
		self.get_path('transfer-accounts/restore-hosting').insert_action(
			'restore-sysuser-logins', CompoundAction(
				description=messages.RESTORE_LOGINS_SYSTEM_USERS,
				run_by_subscription=False
			)
		)
		self.get_path('transfer-accounts/restore-hosting/restore-sysuser-logins').insert_action(
			'change-sysuser-logins', RestoreSysuserLogins()
		)
		self.get_path('transfer-accounts/restore-hosting/restore-sysuser-logins').insert_action(
			'change-backup', ChangeSysuserLogin(SubscriptionBackup())
		)
		self.get_path('transfer-accounts/restore-hosting/restore-sysuser-logins').insert_action(
			'save-backup', SaveConverted(SubscriptionBackup()),
		)
		self.get_path('transfer-accounts/restore-hosting').insert_action(
			'windows-refresh-components', LegacyAction(
				description=messages.REFRESH_COMPONENTS_LIST_TARGET_WINDOWS_SERVERS,
				function=lambda ctx: ctx.migrator._refresh_service_node_components_for_windows(),
				logging_properties=LoggingProperties(compound=False),
				is_critical=False,
			)
		)
		self.get_path('transfer-accounts/restore-hosting').insert_action(
			'import-backups', ImportBackups()
		)
		self.get_path('transfer-accounts/restore-hosting').insert_action(
			'reset-hosting-for-subscription-without-hosting',
			ResetHostingForSubscriptionWithoutHosting()
		)
		self.get_path('transfer-accounts/restore-hosting').insert_action(
			'restore-hosting-settings', RestoreSubscriptionHostingSettings()
		)
		self.get_path('transfer-accounts/restore-hosting').insert_action(
			'restore-catch-all-smartermail-assimilate', RestoreCatchAllSmartermailAssimilate()
		)
		self.get_path('transfer-accounts').insert_action(
			'verify-hosting', self.get_shared_action_pointer('verify-hosting')
		)
		self.get_path('transfer-accounts').insert_action(
			'copy-content', self.get_shared_action_pointer('copy-content')
		)
		self.get_shared_action('sync-web-content-assets').insert_action(
			'check-target-web-hosting', CheckTargetWebHosting()
		)
		self.get_path('transfer-accounts').insert_action(
			'print-subscription-report', PrintSubscriptionStatus()
		)
		self.get_path('transfer-accounts').insert_action(
			'sync-subscription-plan', LegacyAction(
				description=messages.SYNCHRONIZE_SUBSCRIPTIONS_PLANS,
				function=lambda ctx: ctx.migrator._sync_subscription_plan(),
				logging_properties=LoggingProperties(compound=False),
				is_critical=False
			)
		)
		self.get_path('transfer-accounts').insert_action(
			'restore-status', LegacyAction(
				description=messages.RESTORE_STATUS_SUSPENDED_CLIENTS_AND_SUBSCRIPTIONS,
				function=lambda ctx: ctx.migrator.restore_status(
					ctx.options, finalize=False
				),
				logging_properties=LoggingProperties(compound=False),
				is_critical=False
			)
		)
		self.get_path('transfer-accounts').insert_action(
			'remove-imported-backups', RemoveImportedBackups()
		)
		self.get_path('transfer-accounts').insert_action(
			'restore-apache-restart-interval', RestoreApacheRestartInterval()
		)
		self.get_path('transfer-accounts').insert_action(
			'restore-windows-security-policy', LegacyAction(
				description=messages.RESTORE_SECURITY_POLICY_WINDOWS_NODES,
				function=lambda ctx: ctx.migrator.restore_security_policy(),
				logging_properties=LoggingProperties(compound=False),
				is_critical=False,
		))
		self.get_path('transfer-accounts').insert_action(
			'restart-iis-for-idn-domains', LegacyAction(
				description='Restart IIS for IDN domains',
				function=lambda ctx: ctx.migrator._fix_iis_idn_401_error(),
				logging_properties=LoggingProperties(compound=False),
				is_critical=False
			)
		)
		self.get_path('transfer-accounts').insert_action(
			'cleanup', self.get_shared_action('cleanup')
		)
		self.get_path('transfer-accounts').insert_action(
			'finalize',
			self.get_shared_action('finalize')
		)

		self.get_path('transfer-accounts').register_shutdown(
			'set-apache-restart-interval',
			'restore-apache-restart-interval'
		)
		self.get_path('transfer-accounts').register_shutdown(
			'set-windows-security-policy',
			'restore-windows-security-policy'
		)
		self.get_path('transfer-accounts').register_overall_shutdown('cleanup')

	def _configure_entry_point_copy_content(self):
		self.add_entry_point('copy-content', EntryPointAction())
		self.get_path('copy-content').insert_actions(
			self.get_shared_action('post-migration-prepare').get_all_actions()
		)
		self.get_path('copy-content').insert_action(
			'copy-content',
			self.get_shared_action_pointer('copy-content')
		)
		self.get_path('copy-content').insert_actions(
			self.get_shared_action('post-migration-finalize').get_all_actions()
		)
		self.get_path('copy-content').register_overall_shutdown('cleanup')

	def _configure_entry_point_copy_mail_content(self):
		self.add_entry_point('copy-mail-content', EntryPointAction())
		self.get_path('copy-mail-content').insert_actions(
			self.get_shared_action('post-migration-prepare').get_all_actions()
		)
		self.get_path('copy-mail-content').insert_action(
			'copy-mail-content',
			self.get_shared_action_pointer('copy-mail-content')
		)
		self.get_path('copy-mail-content').insert_actions(
			self.get_shared_action('post-migration-finalize').get_all_actions()
		)
		self.get_path('copy-mail-content').register_overall_shutdown('cleanup')

	def _configure_entry_point_copy_web_content(self):
		self.add_entry_point('copy-web-content', EntryPointAction())
		self.get_path('copy-web-content').insert_actions(
			self.get_shared_action('post-migration-prepare').get_all_actions()
		)
		self.get_path('copy-web-content').insert_action(
			'copy-web-content',
			self.get_shared_action_pointer('copy-web-content')
		)
		self.get_path('copy-web-content').insert_actions(
			self.get_shared_action('post-migration-finalize').get_all_actions()
		)
		self.get_path('copy-web-content').register_overall_shutdown('cleanup')

	def _configure_entry_point_copy_db_content(self):
		self.add_entry_point('copy-db-content', EntryPointAction())
		self.get_path('copy-db-content').insert_actions(
			self.get_shared_action('post-migration-prepare').get_all_actions()
		)
		self.get_path('copy-db-content').insert_action(
			'copy-db-content',
			self.get_shared_action_pointer('copy-db-content')
		)
		self.get_path('copy-db-content').insert_actions(
			self.get_shared_action('post-migration-finalize').get_all_actions()
		)
		self.get_path('copy-db-content').register_overall_shutdown('cleanup')

	def _configure_entry_point_verify_hosting(self):
		self.add_entry_point('verify-hosting', EntryPointAction())
		self.get_path('verify-hosting').insert_actions(
			self.get_shared_action('post-migration-prepare').get_all_actions()
		)
		self.get_path('verify-hosting').insert_action(
			'verify-hosting',
			self.get_shared_action_pointer('verify-hosting')
		)
		self.get_path('verify-hosting').insert_actions(
			self.get_shared_action('post-migration-finalize').get_all_actions()
		)
		self.get_path('verify-hosting').register_overall_shutdown('cleanup')

	def _configure_entry_point_analyse_hosting(self):
		self.add_entry_point('analyse-hosting', EntryPointAction())
		self.get_path('analyse-hosting').insert_action(
			'analyse-hosting',
			self.get_shared_action_pointer('analyse-hosting')
		)

	def _configure_entry_point_set_dns_forwarding(self):
		# Set up the DNS forwarding.
		#
		# Classic DNS forwarding just does not work by its design: source Plesk
		# server is authoritative for its zones - according to registrar - and
		# will not forward queries about these zones anywhere.  So the DNS
		# forwarding we do by turning source Plesk into slave mode for the
		# migrated zones.
		#
		# This step is separate from transfer-accounts because the
		# steps are following:
		# - transfer-accounts
		# - disable access to both source and target servers for the migrated
		# subscriptions MANUALLY
		# - set up DNS forwarding
		self.add_entry_point('set-dns-forwarding', EntryPointAction())
		self.get_path('set-dns-forwarding').insert_action(
			'check-source-not-supported', SetDNSForwardingNotSupported()
		)

	def _configure_entry_point_undo_dns_forwarding(self):
		self.add_entry_point('undo-dns-forwarding', EntryPointAction())
		# By default we don't have DNS forwarding support.
		# Should be overridden in child workflow for panels which support DNS forwarding.
		self.get_path('undo-dns-forwarding').insert_action(
			'check-source-not-supported', UndoDNSForwardingNotSupported()
		)

	def _configure_entry_point_set_low_dns_timings(self):
		# Set up low DNS timings
		self.add_entry_point('set-low-dns-timings', EntryPointAction())
		self.get_path('set-low-dns-timings').insert_action(
			'check-source-not-supported', SetDNSTimingsNotSupported()
		)

	def _configure_entry_point_test_all(self):
		self.add_entry_point('test-all', EntryPointAction())
		self.get_path('test-all').insert_actions(
			self.get_shared_action('post-migration-prepare').get_all_actions()
		)
		self.get_path('test-all').insert_action(
			'test-all',
			LegacyAction(
				description=messages.CHECK_THAT_SERVICES_AND_TRANSFERRED_DOMAINS,
				function=lambda ctx: ctx.migrator._test_all(ctx.options)
			)
		)
		self.get_path('test-all').insert_action(
			'cleanup', self.get_shared_action('cleanup')
		)
		self.get_path('test-all').insert_action(
			'print_report', LegacyAction(
				description='Print report',
				function=lambda ctx: ctx.migrator._print_post_migration_check_report('test_all_report'),
				logging_properties=LoggingProperties(info_log=False),
				is_critical=False
			)
		)
		self.get_path('test-all').register_overall_shutdown('cleanup')

	def _configure_entry_point_test_sites(self):
		self.add_entry_point('test-sites', EntryPointAction())
		self.get_path('test-sites').insert_actions(
			self.get_shared_action('post-migration-prepare').get_all_actions()
		)
		self.get_path('test-sites').insert_action(
			'test-sites',
			LegacyAction(
				description=messages.CHECKING_WHETHER_TRANSFERRED_WEBSITES_OPERATE_PROPERLY,
				function=lambda ctx: ctx.migrator._test_sites(ctx.options)
			)
		)
		self.get_path('test-sites').insert_action(
			'cleanup', self.get_shared_action('cleanup')
		)
		self.get_path('test-sites').insert_action(
			'print_report', LegacyAction(
				description='Print report',
				function=lambda ctx: ctx.migrator._print_post_migration_check_report('test_sites_report'),
				logging_properties=LoggingProperties(info_log=False),
				is_critical=False
			)
		)
		self.get_path('test-sites').register_overall_shutdown('cleanup')

	def _configure_entry_point_test_dns(self):
		self.add_entry_point('test-dns', EntryPointAction())
		self.get_path('test-dns').insert_actions(
			self.get_shared_action('post-migration-prepare').get_all_actions()
		)
		self.get_path('test-dns').insert_action(
			'test-dns',
			LegacyAction(
				description=messages.CHECK_THAT_DNS_QUERIES_FOR_TRANSFERRED,
				function=lambda ctx: ctx.migrator._test_dns(ctx.options)
			)
		)
		self.get_path('test-dns').insert_action(
			'cleanup', self.get_shared_action('cleanup')
		)
		self.get_path('test-dns').insert_action(
			'print_report', LegacyAction(
				description='Print report',
				function=lambda ctx: ctx.migrator._print_post_migration_check_report('test_dns_report'),
				logging_properties=LoggingProperties(info_log=False),
				is_critical=False
			)
		)
		self.get_path('test-dns').register_overall_shutdown('cleanup')

	def _configure_entry_point_test_mail(self):
		self.add_entry_point('test-mail', EntryPointAction())
		self.get_path('test-mail').insert_actions(
			self.get_shared_action('post-migration-prepare').get_all_actions()
		)
		self.get_path('test-mail').insert_action(
			'test-mail',
			LegacyAction(
				description=messages.CHECK_WHETHER_IMAP_SMTP_AND_POP,
				function=lambda ctx: ctx.migrator._test_mail(ctx.options)
			)
		)
		self.get_path('test-mail').insert_action(
			'cleanup', self.get_shared_action('cleanup')
		)
		self.get_path('test-mail').insert_action(
			'print_report', LegacyAction(
				description='Print report',
				function=lambda ctx: ctx.migrator._print_post_migration_check_report('test_mail_report'),
				logging_properties=LoggingProperties(info_log=False),
				is_critical=False
			)
		)
		self.get_path('test-mail').register_overall_shutdown('cleanup')

	def _configure_entry_point_test_users(self):
		self.add_entry_point('test-users', EntryPointAction())
		self.get_path('test-users').insert_actions(
			self.get_shared_action('post-migration-prepare').get_all_actions()
		)
		self.get_path('test-users').insert_action(
			'test-users',
			LegacyAction(
				description="Check that users are transferred correctly (FTP/SSH/RDP access)",
				function=lambda ctx: ctx.migrator._test_users(ctx.options)
			)
		)
		self.get_path('test-users').insert_action(
			'cleanup', self.get_shared_action('cleanup')
		)
		self.get_path('test-users').insert_action(
			'print_report', LegacyAction(
				description='Print report',
				function=lambda ctx: ctx.migrator._print_post_migration_check_report('test_users_report'),
				logging_properties=LoggingProperties(info_log=False),
				is_critical=False
			)
		)
		self.get_path('test-users').register_overall_shutdown('cleanup')

	def _configure_entry_point_test_databases(self):
		self.add_entry_point('test-databases', EntryPointAction())
		self.get_path('test-databases').insert_actions(
			self.get_shared_action('post-migration-prepare').get_all_actions()
		)
		self.get_path('test-databases').insert_action(
			'test-databases',
			LegacyAction(
				description=messages.CHECK_WHETHER_DATABASES_WERE_COPIED_CORRECTLY,
				function=lambda ctx: ctx.migrator._test_databases(ctx.options)
			)
		)
		self.get_path('test-databases').insert_action(
			'cleanup', self.get_shared_action('cleanup')
		)
		self.get_path('test-databases').insert_action(
			'print_report', LegacyAction(
				description='Print report',
				function=lambda ctx: ctx.migrator._print_post_migration_check_report('test_databases_report'),
				logging_properties=LoggingProperties(info_log=False),
				is_critical=False
			)
		)
		self.get_path('test-databases').register_overall_shutdown('cleanup')

	def _configure_entry_point_test_services(self):
		self.add_entry_point('test-services', EntryPointAction())

		self.get_path('test-services').insert_action(
			'check-updates',
			self.get_shared_action('check-updates')
		)
		self.get_path('test-services').insert_action(
			'check-sources',
			self.get_shared_action('check-sources')
		)
		self.get_path('test-services').insert_action(
			'check-target',
			self.get_shared_action('check-target')
		)
		self.get_path('test-services').insert_action(
			'check-target-licenses',
			self.get_shared_action('check-target-licenses')
		)
		self.get_path('test-services').insert_action(
			'test-services',
			LegacyAction(
				description=messages.CHECKING_WHETHER_SERVICE_OPERATE_PROPERLY,
				function=lambda ctx: ctx.migrator._test_services(ctx.options)
			)
		)
		self.get_path('test-services').insert_action(
			'cleanup', self.get_shared_action('cleanup')
		)
		self.get_path('test-services').insert_action(
			'print_report', LegacyAction(
				description='Print report',
				function=lambda ctx: ctx.migrator._print_test_services_report(),
				logging_properties=LoggingProperties(info_log=False),
				is_critical=False
			)
		)
		self.get_path('test-services').register_overall_shutdown('cleanup')
