c1d2f79c22
Change-Id: Idff27970dc0d41288444fc3ed18585e3f3a1a0ad
177 lines
6.6 KiB
Python
177 lines
6.6 KiB
Python
# Copyright 2021 Canonical Ltd.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
|
|
"""Encapsulate ``Ceph NFS`` testing."""
|
|
|
|
import logging
|
|
import subprocess
|
|
import tenacity
|
|
from typing import Dict
|
|
import unittest
|
|
import yaml
|
|
import zaza
|
|
import zaza.utilities.installers
|
|
|
|
|
|
class NfsGaneshaTest(unittest.TestCase):
|
|
mount_dir = '/mnt/test'
|
|
share_protocol = 'nfs'
|
|
mounts_share = False
|
|
created_share = None
|
|
|
|
def tearDown(self):
|
|
if self.mounts_share:
|
|
try:
|
|
zaza.utilities.generic.run_via_ssh(
|
|
unit_name='ubuntu/0',
|
|
cmd='sudo umount /mnt/test && sudo rmdir /mnt/test')
|
|
zaza.utilities.generic.run_via_ssh(
|
|
unit_name='ubuntu/1',
|
|
cmd='sudo umount /mnt/test && sudo rmdir /mnt/test')
|
|
except subprocess.CalledProcessError:
|
|
logging.warning("Failed to cleanup mounts")
|
|
if self.created_share:
|
|
zaza.model.run_action_on_leader(
|
|
'ceph-nfs',
|
|
'delete-share',
|
|
action_params={
|
|
'name': self.created_share,
|
|
'purge': True
|
|
})
|
|
|
|
def _create_share(self, name: str, size: int = 10,
|
|
access_ip: str = '0.0.0.0') -> Dict[str, str]:
|
|
action = zaza.model.run_action_on_leader(
|
|
'ceph-nfs',
|
|
'create-share',
|
|
action_params={
|
|
'name': name,
|
|
'size': size,
|
|
'allowed-ips': access_ip,
|
|
})
|
|
self.assertEqual(action.status, 'completed')
|
|
self.created_share = name
|
|
results = action.results
|
|
logging.debug("Action results: {}".format(results))
|
|
return results
|
|
|
|
def _grant_access(self, share_name: str, access_ip: str):
|
|
action = zaza.model.run_action_on_leader(
|
|
'ceph-nfs',
|
|
'grant-access',
|
|
action_params={
|
|
'name': share_name,
|
|
'client': access_ip,
|
|
})
|
|
self.assertEqual(action.status, 'completed')
|
|
|
|
def _mount_share(self, unit_name: str, share_ip: str,
|
|
export_path: str, retry: bool = True):
|
|
self._install_dependencies(unit_name)
|
|
ssh_cmd = (
|
|
'sudo mkdir -p {0} && '
|
|
'sudo mount -t {1} -o nfsvers=4.1,proto=tcp {2}:{3} {0}'.format(
|
|
self.mount_dir,
|
|
self.share_protocol,
|
|
share_ip,
|
|
export_path))
|
|
if retry:
|
|
for attempt in tenacity.Retrying(
|
|
stop=tenacity.stop_after_attempt(5),
|
|
wait=tenacity.wait_exponential(multiplier=3,
|
|
min=2, max=10)):
|
|
with attempt:
|
|
zaza.utilities.generic.run_via_ssh(
|
|
unit_name=unit_name,
|
|
cmd=ssh_cmd)
|
|
else:
|
|
zaza.utilities.generic.run_via_ssh(
|
|
unit_name=unit_name,
|
|
cmd=ssh_cmd)
|
|
self.mounts_share = True
|
|
|
|
def _install_dependencies(self, unit: str):
|
|
logging.debug("About to install nfs-common on {}".format(unit))
|
|
zaza.utilities.generic.run_via_ssh(
|
|
unit_name=unit,
|
|
cmd='sudo apt-get install -yq nfs-common')
|
|
|
|
@tenacity.retry(
|
|
stop=tenacity.stop_after_attempt(5),
|
|
wait=tenacity.wait_exponential(multiplier=3, min=2, max=10))
|
|
def _write_testing_file_on_instance(self, instance_name: str):
|
|
zaza.utilities.generic.run_via_ssh(
|
|
unit_name=instance_name,
|
|
cmd='echo -n "test" | sudo tee {}/test'.format(self.mount_dir))
|
|
|
|
@tenacity.retry(
|
|
stop=tenacity.stop_after_attempt(5),
|
|
wait=tenacity.wait_exponential(multiplier=3, min=2, max=10))
|
|
def _verify_testing_file_on_instance(self, instance_name: str):
|
|
run_with_juju_ssh = zaza.utilities.installers.make_juju_ssh_fn(
|
|
'ubuntu/1', sudo=True
|
|
)
|
|
output = run_with_juju_ssh(
|
|
'sudo cat {}/test'.format(self.mount_dir))
|
|
logging.info("Verification output: {}".format(output))
|
|
self.assertEqual('test', output.strip())
|
|
|
|
def test_create_share(self):
|
|
logging.info("Creating a share")
|
|
# Todo - enable ACL testing
|
|
ubuntu_0_ip = zaza.model.get_unit_public_address(
|
|
zaza.model.get_unit_from_name('ubuntu/0')
|
|
)
|
|
ubuntu_1_ip = zaza.model.get_unit_public_address(
|
|
zaza.model.get_unit_from_name('ubuntu/1')
|
|
)
|
|
share = self._create_share('test_ganesha_share', access_ip=ubuntu_0_ip)
|
|
# share = self._create_share('test_ganesha_share')
|
|
zaza.model.wait_for_application_states(states={
|
|
'ubuntu': {
|
|
"workload-status-message-regex": "^$",
|
|
}
|
|
})
|
|
export_path = share['path']
|
|
ip = share['ip']
|
|
logging.info("Mounting share on ubuntu units")
|
|
self._mount_share('ubuntu/0', ip, export_path)
|
|
logging.info("writing to the share on ubuntu/0")
|
|
self._write_testing_file_on_instance('ubuntu/0')
|
|
# Todo - enable ACL testing
|
|
try:
|
|
self._mount_share('ubuntu/1', ip, export_path, retry=False)
|
|
self.fail('Mounting should not have succeeded')
|
|
except: # noqa: E722
|
|
pass
|
|
self._grant_access('test_ganesha_share', access_ip=ubuntu_1_ip)
|
|
|
|
self._mount_share('ubuntu/1', ip, export_path)
|
|
logging.info("reading from the share on ubuntu/1")
|
|
self._verify_testing_file_on_instance('ubuntu/1')
|
|
|
|
def test_list_shares(self):
|
|
self._create_share('test_ganesha_list_share')
|
|
action = zaza.model.run_action_on_leader(
|
|
'ceph-nfs',
|
|
'list-shares',
|
|
action_params={})
|
|
self.assertEqual(action.status, 'completed')
|
|
results = action.results
|
|
logging.debug("Action results: {}".format(results))
|
|
logging.debug("exports: {}".format(results['exports']))
|
|
exports = yaml.safe_load(results['exports'])
|
|
self.assertIn('test_ganesha_list_share',
|
|
[export['name'] for export in exports])
|