#!/usr/share/ucs-test/runner python
## desc: ucs-school-printermoderator-module-check
## roles: [domaincontroller_master, domaincontroller_backup, domaincontroller_slave, memberserver]
## tags: [apptest,ucsschool]
## exposure: dangerous
## packages:  [ucs-school-umc-printermoderation, ucs-school-import]

from mimetypes import MimeTypes
from univention.lib.umc_connection import UMCConnection
import os
import socket
import subprocess
import sys
import tempfile
import time
import univention.testing.strings as uts
import univention.testing.ucr as ucr_test
import univention.testing.ucsschool as utu
import univention.testing.utils as utils

def dir(userName):
	path = '/var/spool/cups-pdf/%s' % (userName)
	files = []
	for root, _ , filenames in os.walk(path):
		for f in filenames:
			files.append(os.path.relpath(os.path.join(root, f), path))
	return files

# Order print job for postscript test page and check if it is stored in the 
# user spool directory
def orderPrint(printer, userName, file):
	oldPrintJobs = dir(userName)
	job = []
	cmd = ['lpr', '-P', printer, '-U', userName, file]
	retval = subprocess.call(cmd)
	if retval:
		utils.fail('Orderprint failure')
	for waitingTime in range(60):
		job = [x for x in dir(userName) if x != oldPrintJobs]
		if job == []:
			time.sleep(1)
			continue
		else:
			break
	if job == []:
		utils.fail('Ordered print job was not able to be stored in user spool directory')


# add / del / modify Printer
def doPrinter(operation, printer_name, schoolName, spool_host, domainname):
	localIp = socket.gethostbyname(socket.gethostname())
	uri = '%s://%s' % ('lpd', localIp)
	print_server = '%s.%s' % (spool_host, domainname)
	f = tempfile.NamedTemporaryFile(suffix='.csv')
	line = '%s\t%s\t%s\t%s\t%s\n' % (operation, schoolName, print_server,
			printer_name, uri)
	f.write(line)
	f.flush()
	cmd = ['/usr/share/ucs-school-import/scripts/import_printer', f.name]
	retval = subprocess.call(cmd)
	f.close()
	if retval:
		utils.fail('Unexpected error while acting on Printer')
	utils.wait_for_replication_and_postrun()

# check the existance of the created printer
def printerExist(connection, printerName):
	requestResult = connection.request('printermoderation/printers')
	printerFound = [d for d in requestResult if d['label'] == printerName]
	if printerFound:
		return True
	else:
		return False

# get the current printed jobs
def queryPrintJobs(
		connection,
		printerName,
		cName,
		schoolName,
		pattern,
		basedn):
	if cName != 'None':
		cdn = 'cn=%s,cn=klassen,cn=schueler,cn=groups,ou=%s,%s' % (
				cName,
				schoolName,
				basedn)
	else:
		cdn = cName
	param = {
			'school': schoolName,
			'class': cdn,
			'pattern': pattern
			}
	return connection.request('printermoderation/query', param)

# delete a specific printjob
def delPrintJob(connection, userName, printJob):
	param = {
			'username': userName,
			'printjob': printJob
			}
	if not connection.request('printermoderation/delete', param):
		utils.fail('Could not delete print jobs')

# Check the file type of the printed pdf
def checkPrintJobs(printJobs):
	mime = MimeTypes()
	for job in printJobs:
		mime_type, _ = mime.guess_type(job)
		if not '/pdf' in mime_type:
			utils.fail('Unexpected file type')

# Bug #34498: no file type is check at the moment
# download print jobs
def downloadPrintJobs(connection, userName, printJob):
	param = {
			'username': userName,
			'printjob': printJob
			}
	try:
		connection.request('printermoderation/download', param)
	except Exception as e:
		ex_en = 'No JSON object could be decoded'
		if not ex_en in e:
			utils.fail('Enexpected exception:', e)

# get print jobs for a specific user
def getPrintJobs(alljobs, userName):
	return ([x['id'] for x in alljobs if x['username']==userName])

# Accept printjobs and send them to the hard printer
def acceptprint(
		connection,
		userName,
		printJobPath,
		printerName,
		spoolHost,
		domainname):
	printJob = printJobPath.split('/')[-1]
	printerURI = '%s.%s://%s' % (spoolHost, domainname, printerName)
	param = {
			'username': userName,
			'printjob': printJob,
			'printer': printerURI
			}
	reqResult = connection.request('printermoderation/print', param)
	print 'reqResult = ', reqResult
	if not reqResult:
		utils.fail('Could not pass print jobs to hard printer')


def main():
	with utu.UCSTestSchool()  as schoolenv:
		newPrinterName = uts.random_string()
		default_printer = 'PDFDrucker'
		test_file = 'testpage.ps'
		ucr = ucr_test.UCSTestConfigRegistry()
		ucr.load()
		host = ucr.get('hostname')
		domainname = ucr.get('domainname')
		basedn = ucr.get('ldap/base')
		schoolName, oudn = schoolenv.create_ou(name_edudc=host)
		tea, _ = schoolenv.create_user(schoolName, classes='1A', is_teacher=True)
		stu1, _ = schoolenv.create_user(schoolName, classes='1A')
		stu2, _ = schoolenv.create_user(schoolName, classes='2B')

		utils.wait_for_replication_and_postrun()

		co = UMCConnection(host)
		co.auth(tea ,'univention')

		# add new printer
		doPrinter('A', newPrinterName, schoolName, host, domainname)

		# check if the printer exists
		if not printerExist(co, newPrinterName):
			utils.fail('Printer not found')

		# order print jobs
		orderPrint(default_printer, stu1, test_file)
		orderPrint(default_printer, stu2, test_file)

		# query all orderd print jobs
		alljobs = queryPrintJobs(
				co,
				newPrinterName,
				'None',
				schoolName,
				"",
				basedn)
		# query all orderd print jobs from classes 1A
		alljobs1A = queryPrintJobs(
				co,
				newPrinterName,
				'1A',
				schoolName,
				"",
				basedn)
		if alljobs1A == alljobs:
			utils.fail('Unexpected job query result')

		# get print jobs
		printJobs1 = getPrintJobs(alljobs, stu1)
		printJobs2 = getPrintJobs(alljobs, stu2)

		# check file type for the printjobs files
		checkPrintJobs(printJobs1)
		checkPrintJobs(printJobs2)

		# download print jobs for stu1 and check the filetype
		downloadPrintJobs(co, stu1, printJobs1[0])

		# accepting a print job from stu1
		acceptprint(co, stu1, printJobs1[0], newPrinterName, host, domainname)

		# delete a print job for stu 1
		delPrintJob(co, stu1, printJobs1[0])

		# delete a print job for stu 2
		delPrintJob(co, stu2, printJobs2[0])

		# delete the created printer
		doPrinter('D', newPrinterName, schoolName, host, domainname)

if __name__ == '__main__':
	sys.exit(main())
