freeipa/ipatests/test_integration/test_nfs.py

304 lines
9.8 KiB
Python
Raw Normal View History

#
# Copyright (C) 2018 FreeIPA Contributors see COPYING for license
#
"""This module provides tests for NFS-related features like
krb5 NFS and automount locations.
Wishlist
* add automount direct and indirect maps
* add automount /home for the "seattle" location only
* validate it is not available in another location
* krb5 /home for IdM users in test_automount
* store nfs configuration in a single place
"""
from __future__ import absolute_import
import time
import re
from ipatests.test_integration.base import IntegrationTest
from ipatests.pytest_ipa.integration import tasks
from ipaplatform.paths import paths
import os
# give some time for units to stabilize
# otherwise we get transient errors
WAIT_AFTER_INSTALL = 5
WAIT_AFTER_UNINSTALL = WAIT_AFTER_INSTALL
class TestInit(IntegrationTest):
@classmethod
def fix_resolv_conf(cls, client, server):
contents = client.get_file_contents(paths.RESOLV_CONF,
encoding='utf-8')
nameserver = 'nameserver %s\n' % server.ip
if not contents.startswith(nameserver):
contents = nameserver + contents.replace(nameserver, '')
client.run_command([
'/usr/bin/cp', paths.RESOLV_CONF,
'%s.sav' % paths.RESOLV_CONF
])
client.put_file_contents(paths.RESOLV_CONF, contents)
@classmethod
def restore_resolv_conf(cls, client):
client.run_command([
'/usr/bin/cp',
'%s.sav' % paths.RESOLV_CONF,
paths.RESOLV_CONF
])
class TestNFS(TestInit):
num_replicas = 2
num_clients = 1
topology = 'star'
@classmethod
def install(cls, mh):
tasks.install_master(cls.master, setup_dns=True)
clients = (cls.clients[0], cls.replicas[0], cls.replicas[1])
for client in clients:
cls.fix_resolv_conf(client, cls.master)
tasks.install_client(cls.master, client)
client.run_command(["cat", "/etc/resolv.conf"])
def cleanup(self):
nfssrv = self.clients[0]
nfsclt = self.replicas[0]
automntclt = self.replicas[1]
nfsclt.run_command(["umount", "-a", "-t", "nfs4"])
nfsclt.run_command(["systemctl", "stop", "rpc-gssd"])
nfssrv.run_command(["systemctl", "stop", "nfs-server"])
nfssrv.run_command(["systemctl", "disable", "nfs-server"])
nfssrv.run_command([
"rm", "-f", "/etc/exports.d/krbnfs.exports",
"/etc/exports.d/stdnfs.exports"
])
nfssrv.run_command(["rm", "-rf", "/exports"])
tasks.uninstall_client(nfsclt)
tasks.uninstall_client(nfssrv)
self.master.run_command([
"ipa", "host-mod", automntclt.hostname,
"--location", "''"
])
# not strictly necessary, but this exercises automountlocation-del
self.master.run_command([
"ipa", "automountlocation-del", "seattle"
])
nfsclt.run_command(["systemctl", "restart", "nfs-utils"])
nfssrv.run_command(["systemctl", "restart", "nfs-utils"])
for client in (nfssrv, nfsclt, automntclt):
self.restore_resolv_conf(client)
tasks.uninstall_master(self.master)
def test_prepare_users(self):
users = {
"athena": "p",
"euripides": "s"
}
temp_pass = 'temppass'
for user in users:
self.master.run_command([
"ipa", "user-add",
"%s" % user, "--first", "%s" % user,
"--last", "%s" % users[user],
'--password'], stdin_text="%s\n%s\n" % (temp_pass, temp_pass)
)
self.master.run_command(["kdestroy", "-A"])
password = "Secret123"
user_kinit = "%s\n%s\n%s\n" % (temp_pass, password, password)
self.master.run_command(
['kinit', user], stdin_text=user_kinit
)
self.master.run_command(["kdestroy", "-A"])
tasks.kinit_admin(self.master)
def test_krb5_nfsd(self):
nfssrv = self.clients[0]
# NFS keytab management
self.master.run_command([
"ipa", "service-add", "nfs/%s" % nfssrv.hostname
])
nfssrv.run_command([
"ipa-getkeytab", "-p", "nfs/%s" % nfssrv.hostname,
"-k", "/etc/krb5.keytab"
])
nfssrv.run_command(["systemctl", "restart", "nfs-server"])
nfssrv.run_command(["systemctl", "enable", "nfs-server"])
time.sleep(WAIT_AFTER_INSTALL)
basedir = "exports"
exports = {
"krbnfs": "*(sec=krb5p,rw)",
"stdnfs": "*(ro)",
"home": "*(sec=krb5p,rw)"
}
for export in exports:
exportpath = os.sep.join(('', basedir, export))
exportfile = os.sep.join((
'', 'etc', 'exports.d', "%s.exports" % export
))
exportline = " ".join((exportpath, exports[export]))
nfssrv.run_command(["mkdir", "-p", exportpath])
nfssrv.run_command(["chmod", "770", exportpath])
nfssrv.put_file_contents(exportfile, exportline)
nfssrv.run_command(["cat", exportfile])
nfssrv.run_command(["exportfs", "-r"])
nfssrv.run_command(["exportfs", "-s"])
def test_krb5_nfs_manual_configuration(self):
nfssrv = self.clients[0]
nfsclt = self.replicas[0]
nfsclt.run_command(["systemctl", "restart", "rpc-gssd"])
time.sleep(WAIT_AFTER_INSTALL)
mountpoints = ("/mnt/krb", "/mnt/std", "/home")
for mountpoint in mountpoints:
nfsclt.run_command(["mkdir", "-p", mountpoint])
nfsclt.run_command([
"systemctl", "status", "gssproxy"
])
nfsclt.run_command([
"systemctl", "status", "rpc-gssd"
])
nfsclt.run_command([
"mount", "-t", "nfs4", "-o", "sec=krb5p,vers=4.0",
"%s:/exports/krbnfs" % nfssrv.hostname, "/mnt/krb", "-v"
])
nfsclt.run_command([
"mount", "-t", "nfs4", "-o", "sec=krb5p,vers=4.0",
"%s:/exports/home" % nfssrv.hostname, "/home", "-v"
])
def test_automount(self):
"""
Test if ipa-client-automount behaves as expected
"""
nfssrv = self.clients[0]
automntclt = self.replicas[1]
self.master.run_command([
"ipa", "automountlocation-add", "seattle"
])
self.master.run_command([
"ipa", "automountmap-add", "seattle", "auto.home"
])
self.master.run_command([
"ipa", "automountkey-add", "seattle", "auto.home",
"--key='*'", "--info=sec=krb5p,vers=4"
" 'rhel8-nfsserver0.laptop.example.org:/export/home/&'"
])
self.master.run_command([
"ipa", "automountkey-add", "seattle", "auto.master",
"--key=/home", "--info=auto.home"
])
self.master.run_command([
"ipa", "host-mod", automntclt.hostname,
"--location", "seattle"
])
# systemctl non-fatal errors will only be displayed
# if ipa-client-automount is launched with --debug
result1 = automntclt.run_command([
'ipa-client-automount', '--location', 'seattle',
'-U', '--debug'
])
time.sleep(WAIT_AFTER_INSTALL)
# systemctl non-fatal errors will show up like this:
# stderr=Failed to restart nfs-secure.service: \
# Unit nfs-secure.service not found.
# normal output:
# stderr=
m1 = re.search(r'(?<=stderr\=Failed).+', result1.stderr_text)
# maybe re-use m1.group(0) if it exists.
assert m1 is None
# https://pagure.io/freeipa/issue/7918
# check whether idmapd.conf was setup using the IPA domain
automntclt.run_command([
"grep", "Domain = %s" % self.master.domain.name, "/etc/idmapd.conf"
])
automntclt.run_command([
"mount", "-t", "nfs4", "-o", "sec=krb5p,vers=4.0",
"%s:/exports/home" % nfssrv.hostname, "/home", "-v"
])
# TODO leverage users
automntclt.run_command(["umount", "-a", "-t", "nfs4"])
result2 = automntclt.run_command([
'ipa-client-automount', '--uninstall', '-U', '--debug'
])
m2 = re.search(r'(?<=stderr\=Failed).+', result2.stderr_text)
assert m2 is None
time.sleep(WAIT_AFTER_UNINSTALL)
# https://pagure.io/freeipa/issue/7918
# test for --idmap-domain DNS
automntclt.run_command([
'ipa-client-automount', '--location', 'default',
'-U', '--debug', "--idmap-domain", "DNS"
])
time.sleep(WAIT_AFTER_INSTALL)
# check whether idmapd.conf was setup properly:
# grep must not find any configured Domain.
result = automntclt.run_command(
["grep", "^Domain =", "/etc/idmapd.conf"], raiseonerr=False
)
assert result.returncode == 1
automntclt.run_command([
'ipa-client-automount', '--uninstall', '-U', '--debug'
])
time.sleep(WAIT_AFTER_UNINSTALL)
# https://pagure.io/freeipa/issue/7918
# test for --idmap-domain exampledomain.net
nfs_domain = "exampledomain.net"
automntclt.run_command([
'ipa-client-automount', '--location', 'default',
'-U', '--debug', "--idmap-domain", nfs_domain
])
# check whether idmapd.conf was setup using nfs_domain
automntclt.run_command([
"grep", "Domain = %s" % nfs_domain, "/etc/idmapd.conf"
])
time.sleep(WAIT_AFTER_INSTALL)
automntclt.run_command([
'ipa-client-automount', '--uninstall', '-U', '--debug'
])
time.sleep(WAIT_AFTER_UNINSTALL)
self.cleanup()