#!/usr/libexec/platform-python
#
# Copyright (C) 2021 Olaf Kirch <okir@suse.de>

import susetest

susetest.requireAddressResource("ipv4_address")
susetest.optionalAddressResource("ipv6_address")

# boilerplate tests
susetest.template('selinux-verify-subsystem', 'ntp', nodeName = 'server')
susetest.template('verify-file', 'ntp_keys', nodeName = 'server')

@susetest.test
def ntp_server_start(driver):
	'''wait-start: that service can be started'''

	ntp = driver.server.managers.ntp
	if not ntp.start():
		driver.server.logFailure("NTP service failed to start")
		return
	
	if not ntp.is_okay():
		driver.server.logFailure("Cannot talk to NTP daemon")
		return

	driver.server.logInfo("The NTP daemon seems to be up and running")

@susetest.test
def ntp_server_synchronize(driver):
	'''wait-pool-synch: check that server can synchronize with pool'''

	ntp = driver.server.managers.ntp
	if not ntp.waitSynchronize():
		driver.server.logFailure("NTP service failed to synchronize")
		return

	driver.server.logInfo("The NTP daemon was able to synchronize with upstream")

@susetest.test
def ntp_display_sources(driver):
	'''display-sources: check that root user can display sources'''

	ntp = driver.server.managers.ntp
	if not ntp.showSources(user = "root"):
		driver.server.logFailure("unable to display sources")
		return
	
	susetest.say("Good, this seems to work as expected")

@susetest.test
def ntp_display_sources_testuser(driver):
	'''display-sources-user: check that test user can display sources'''

	ntp = driver.server.managers.ntp
	if not ntp.showSources():
		driver.server.logFailure("unable to display sources")
		return
	
	susetest.say("Good, this seems to work as expected")

# This is not a test in its own right; it's just a helper function
def __ntp_client_use_server(driver, attr_name, secure = False):
	def get_address(node):
		address = getattr(node, attr_name, None)
		if address is None:
			node.logInfo("%s not set; skipping" % attr_name)
			driver.skipTest()
		return address

	client_ntp = driver.client.managers.ntp
	client_ip = get_address(driver.client)
	if client_ip is None:
		return

	server_ntp = driver.server.managers.ntp
	server_ip = get_address(driver.server)
	if server_ip is None:
		return

	key_id = None
	if secure:
		key_id = "42"
		key = server_ntp.createKey(key_id)
		if key is None:
			driver.server.logFailure("cannot generate symmetrical key")
			return

		driver.server.logInfo(f"Generated key {key}")
		server_ntp.installKey(key_id, key)
		client_ntp.installKey(key_id, key)

	if not server_ntp.allowClient(client_ip):
		driver.server.logFailure("cannot configure NTP daemon to allow client %s" % client_ip)
		return

	server_options = ["iburst"]
	if key_id:
		server_options += ["key", key_id]

	if not client_ntp.useServer(server_ip, server_options):
		driver.client.logFailure("cannot configure NTP daemon to use server %s" % server_ip)
		return

	# actually, restart
	if not client_ntp.restart():
		driver.client.logFailure("NTP daemon failed to restart")
		return
	
	if not client_ntp.waitSynchronize():
		driver.client.logFailure("NTP service failed to synchronize")
		return

	client_ntp.showSources()

	driver.client.logInfo("The NTP daemon seems to be up and running")


@susetest.test
def ntp_client_use_server_ipv4(driver):
	'''client-use-server-ipv4: check that client can synchronize to server via IPv4'''
	__ntp_client_use_server(driver, 'ipv4_address')

@susetest.test
def ntp_client_use_server_ipv6(driver):
	'''client-use-server-ipv6: check that client can synchronize to server via IPv6'''
	__ntp_client_use_server(driver, 'ipv6_address')

@susetest.test
def ntp_use_keyed_communication(driver):
	'''keyed-communication: check that secure communication with symmetrical encryption keys works'''
	__ntp_client_use_server(driver, 'ipv4_address', secure = True)

if __name__ == '__main__':
	susetest.perform()
