import logging

from parallels.hosting_check import DomainIssue
from parallels.hosting_check import Severity
from parallels.hosting_check import RDPAuthIssueType
from parallels.hosting_check.messages import MSG
from parallels.hosting_check.utils.list_utils import none_list

logger = logging.getLogger(__name__)

class RDPAuthChecker(object):
	"""Check RDP access for users

	RDP auth checker is simple. It checks only that users are assigned to a
	group. In the future it may have more complex checks by actually trying to
	log in to a system by RDP, but they are much more complex to implement (and
	complex to make them work on all platforms).
	"""
	def check(self, domains_to_check):
		issues = []

		for domain_to_check in domains_to_check:
			self._check_single_domain(domain_to_check, issues)
		return issues

	def _check_single_domain(self, domain_to_check, issues):
		if not self._check_web_ip_present(domain_to_check, issues):
			return 

		if domain_to_check.runner is None:
			return

		for user in domain_to_check.users:
			try:
				user_in_group = self._check_rdp_group(
					domain_to_check.runner, domain_to_check.web_server_ip, user
				)
				if not user_in_group:
					issues.append(DomainIssue(
						domain_name=domain_to_check.domain_name, 
						severity=Severity.ERROR, 
						category=RDPAuthIssueType.ACTIVE_USER_NOT_CONFIGURED, 
						problem=MSG(
							RDPAuthIssueType.ACTIVE_USER_NOT_CONFIGURED,
							server_ip=domain_to_check.web_server_ip,
							login=user.login, 
							reason=MSG('rdp_auth_user_not_in_group')
						)
					))
			except KeyboardInterrupt:
				# for compatibility with python 2.4
				raise
			except Exception, e:
				logger.debug(u"Exception:", exc_info=e)
				issues.append(DomainIssue(
					domain_name=domain_to_check.domain_name,
					severity=Severity.WARNING, 
					category=RDPAuthIssueType.INTERNAL_ERROR,
					problem=MSG(
						RDPAuthIssueType.INTERNAL_ERROR,
						server_ip=domain_to_check.web_server_ip,
						login=user.login, error_message=str(e)
					)
				))
		for user in none_list(domain_to_check.inactive_users):
			try:
				user_in_group = self._check_rdp_group(
					domain_to_check.runner, domain_to_check.web_server_ip, user
				)
				if user_in_group:
					issues.append(DomainIssue(
						domain_name=domain_to_check.domain_name, 
						severity=Severity.ERROR, 
						category=RDPAuthIssueType.INACTIVE_USER_CONFIGURED, 
						problem=MSG(
							RDPAuthIssueType.INACTIVE_USER_CONFIGURED,
							server_ip=domain_to_check.web_server_ip,
							login=user.login,
							reason=MSG('rdp_auth_user_in_group')
						)
					))
			except KeyboardInterrupt:
				# for compatibility with python 2.4
				raise
			except Exception, e:
				logger.debug(u"Exception:", exc_info=e)
				issues.append(DomainIssue(
					domain_name=domain_to_check.domain_name,
					severity=Severity.WARNING, 
					category=RDPAuthIssueType.INTERNAL_ERROR,
					problem=MSG(
						RDPAuthIssueType.INTERNAL_ERROR,
						server_ip=domain_to_check.web_server_ip,
						login=user.login, error_message=str(e)
					)
				))

	def _check_web_ip_present(self, domain_to_check, issues):
		if domain_to_check.web_server_ip is None:
			issues.append(
				DomainIssue(
					domain_name=domain_to_check.domain_name,
					severity=Severity.WARNING, 
					category=RDPAuthIssueType.WEB_IP_NOT_DEFINED,
					problem=MSG(RDPAuthIssueType.WEB_IP_NOT_DEFINED)
				)
			)
			return False
		return True

	@classmethod
	def _check_rdp_group(cls, runner, server_ip, user):
		runner.connect()
		try:
			logger.debug(MSG(
				'rdp_log_checking', 
				user=user.login, server_ip=server_ip
			))
			users_list = runner.sh(
				'cmd /c net localgroup "Remote Desktop Users"'
			)
			return user.login in users_list
		finally:
			runner.disconnect()
