From daca62f4b7f876bf675e5b29b643e3d472903597 Mon Sep 17 00:00:00 2001 From: Shwetha Panduranga Date: Wed, 8 Feb 2017 18:52:37 +0530 Subject: Adding a new test to VVT: 1) glusterbaseclass: - Making changes in glusterbaseclass to not necessarily have volume_type and mount_type. 2) volume_libs: - setup_volume don't have to export the volume. It just creates starts and setup's any operation on the volume. - Moved the sharing/exporting the volume to BaseClass 3) Renaming samba_ops to samba_libs to have better naming practice. 4) Adding nfs_ganesha_libs for any nfs related helper functions 5) Adding a new vvt case which creates, deteles, creates the volume. Change-Id: I238c349df7165d669d3bc7234d97845dba2f51a6 Signed-off-by: Shwetha Panduranga --- .../glustolibs/gluster/gluster_base_class.py | 400 +++++++++++---------- 1 file changed, 205 insertions(+), 195 deletions(-) (limited to 'glustolibs-gluster/glustolibs/gluster/gluster_base_class.py') diff --git a/glustolibs-gluster/glustolibs/gluster/gluster_base_class.py b/glustolibs-gluster/glustolibs/gluster/gluster_base_class.py index 65e7cc759..4ad6cc732 100644 --- a/glustolibs-gluster/glustolibs/gluster/gluster_base_class.py +++ b/glustolibs-gluster/glustolibs/gluster/gluster_base_class.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # Copyright (C) 2016 Red Hat, Inc. # # This program is free software; you can redistribute it and/or modify @@ -21,17 +20,20 @@ """ import unittest - -from glusto.core import Glusto as g import os import random -from glustolibs.gluster.peer_ops import (is_peer_connected, - peer_status) -from glustolibs.gluster.volume_libs import setup_volume, cleanup_volume -from glustolibs.gluster.volume_ops import volume_info, volume_status -from glustolibs.gluster.exceptions import ExecutionError, ConfigError import time import copy +from glusto.core import Glusto as g +from glustolibs.gluster.exceptions import ExecutionError, ConfigError +from glustolibs.gluster.peer_ops import is_peer_connected, peer_status +from glustolibs.gluster.volume_ops import volume_info +from glustolibs.gluster.volume_libs import (setup_volume, cleanup_volume, + log_volume_info_and_status) +from glustolibs.gluster.samba_libs import share_volume_over_smb +from glustolibs.gluster.nfs_libs import export_volume_through_nfs +from glustolibs.gluster.mount_ops import create_mount_objs +from glustolibs.io.utils import log_mounts_info class runs_on(g.CarteTestClass): @@ -63,38 +65,41 @@ class runs_on(g.CarteTestClass): class GlusterBaseClass(unittest.TestCase): + """GlusterBaseClass to be subclassed by Gluster Tests. + This class reads the config for variable values that will be used in + gluster tests. If variable values are not specified in the config file, + the variable are defaulted to specific values. + """ # these will be populated by either the runs_on decorator or # defaults in setUpClass() volume_type = None mount_type = None - volname = None - servers = None - voltype = None - mnode = None - mounts = None - clients = None @classmethod def setUpClass(cls): """Initialize all the variables necessary for testing Gluster """ + g.log.info("Setting up class: %s", cls.__name__) + # Get all servers cls.all_servers = None - if ('servers' in g.config and g.config['servers']): + if 'servers' in g.config and g.config['servers']: cls.all_servers = g.config['servers'] + cls.servers = cls.all_servers else: raise ConfigError("'servers' not defined in the global config") # Get all clients cls.all_clients = None - if ('clients' in g.config and g.config['clients']): + if 'clients' in g.config and g.config['clients']: cls.all_clients = g.config['clients'] + cls.clients = cls.all_clients else: raise ConfigError("'clients' not defined in the global config") # Get all servers info cls.all_servers_info = None - if ('servers_info' in g.config and g.config['servers_info']): + if 'servers_info' in g.config and g.config['servers_info']: cls.all_servers_info = g.config['servers_info'] else: raise ConfigError("'servers_info' not defined in the global " @@ -102,19 +107,31 @@ class GlusterBaseClass(unittest.TestCase): # All clients_info cls.all_clients_info = None - if ('clients_info' in g.config and g.config['clients_info']): + if 'clients_info' in g.config and g.config['clients_info']: cls.all_clients_info = g.config['clients_info'] else: raise ConfigError("'clients_info' not defined in the global " "config") - if cls.volume_type is None: - cls.volume_type = "distributed" - if cls.mount_type is None: - cls.mount_type = "glusterfs" + # Set mnode : Node on which gluster commands are executed + cls.mnode = cls.all_servers[0] - g.log.info("SETUP GLUSTER VOLUME: %s on %s" % (cls.volume_type, - cls.mount_type)) + # SMB Cluster info + try: + cls.smb_users_info = ( + g.config['gluster']['cluster_config']['smb']['users_info']) + except KeyError: + cls.smb_users_info = {} + cls.smb_users_info['root'] = {} + cls.smb_users_info['root']['password'] = 'foobar' + cls.smb_users_info['root']['acl'] = 'rwx' + + # NFS-Ganesha Cluster Info + try: + cls.enable_nfs_ganesha = bool(g.config['gluster']['cluster_config'] + ['nfs_ganesha']['enable']) + except KeyError: + cls.enable_nfs_ganesha = False # Defining default volume_types configuration. default_volume_type_config = { @@ -151,150 +168,136 @@ class GlusterBaseClass(unittest.TestCase): # Get the volume configuration. cls.volume = {} - found_volume = False - if 'gluster' in g.config: - if 'volumes' in g.config['gluster']: - for volume in g.config['gluster']['volumes']: - if volume['voltype']['type'] == cls.volume_type: - cls.volume = copy.deepcopy(volume) - found_volume = True - break - - if found_volume: - if 'name' not in cls.volume: + if cls.volume_type: + found_volume = False + if 'gluster' in g.config: + if 'volumes' in g.config['gluster']: + for volume in g.config['gluster']['volumes']: + if volume['voltype']['type'] == cls.volume_type: + cls.volume = copy.deepcopy(volume) + found_volume = True + break + + if found_volume: + if 'name' not in cls.volume: + cls.volume['name'] = 'testvol_%s' % cls.volume_type + + if 'servers' not in cls.volume: + cls.volume['servers'] = cls.all_servers + + if not found_volume: + try: + if g.config['gluster']['volume_types'][cls.volume_type]: + cls.volume['voltype'] = (g.config['gluster'] + ['volume_types'] + [cls.volume_type]) + except KeyError: + try: + cls.volume['voltype'] = (default_volume_type_config + [cls.volume_type]) + except KeyError: + raise ConfigError("Unable to get configs of volume " + "type: %s", cls.volume_type) cls.volume['name'] = 'testvol_%s' % cls.volume_type - - if 'servers' not in cls.volume: cls.volume['servers'] = cls.all_servers - if not found_volume: - cls.volume = { - 'name': ('testvol_%s' % cls.volume_type), - 'servers': cls.all_servers - } - try: - if g.config['gluster']['volume_types'][cls.volume_type]: - cls.volume['voltype'] = (g.config['gluster'] - ['volume_types'][cls.volume_type]) - except KeyError: - try: - cls.volume['voltype'] = (default_volume_type_config - [cls.volume_type]) - except KeyError: - raise ConfigError("Unable to get configs of volume type: " - "%s", cls.volume_type) - - # Set volume options - if 'options' not in cls.volume: - cls.volume['options'] = {} - - # Set nfs.disable to 'off' to start gluster-nfs server on start of the - # volume if the mount type is 'nfs' - if cls.mount_type == 'nfs': - cls.volume['options']['nfs.disable'] = 'off' - - # SMB Info - if cls.mount_type == 'cifs' or cls.mount_type == 'smb': - if 'smb' not in cls.volume: - cls.volume['smb'] = {} - cls.volume['smb']['enable'] = True - users_info_found = False - try: - if cls.volume['smb']['users_info']: - users_info_found = True - except KeyError: - users_info_found = False - - if not users_info_found: - cls.volume['smb']['users_info'] = {} - try: - cls.volume['smb']['users_info'] = ( - g.config['gluster']['cluster_config']['smb'] - ['users_info']) - except KeyError: - pass - - if not cls.volume['smb']['users_info']: - cls.volume['smb']['users_info']['root'] = {} - cls.volume['smb']['users_info']['root']['password'] = ( - 'foobar') - - # Define Volume variables. - cls.volname = cls.volume['name'] - cls.servers = cls.volume['servers'] - cls.voltype = cls.volume['voltype']['type'] - cls.mnode = cls.servers[0] - try: - cls.smb_users_info = cls.volume['smb']['users_info'] - except KeyError: - cls.smb_users_info = {} + # Set volume options + if 'options' not in cls.volume: + cls.volume['options'] = {} + + # Define Volume Useful Variables. + cls.volname = cls.volume['name'] + cls.voltype = cls.volume['voltype']['type'] + cls.servers = cls.volume['servers'] + cls.mnode = cls.servers[0] + cls.vol_options = cls.volume['options'] # Get the mount configuration. - cls.mounts_dict_list = [] cls.mounts = [] - found_mount = False - if 'gluster' in g.config: - if 'mounts' in g.config['gluster']: - for mount in g.config['gluster']['mounts']: - if mount['protocol'] == cls.mount_type: - temp_mount = {} - temp_mount['protocol'] = cls.mount_type - if ('volname' in mount and mount['volname']): - if mount['volname'] == cls.volname: - temp_mount = copy.deepcopy(mount) + if cls.mount_type: + cls.mounts_dict_list = [] + found_mount = False + if 'gluster' in g.config: + if 'mounts' in g.config['gluster']: + for mount in g.config['gluster']['mounts']: + if mount['protocol'] == cls.mount_type: + temp_mount = {} + temp_mount['protocol'] = cls.mount_type + if 'volname' in mount and mount['volname']: + if mount['volname'] == cls.volname: + temp_mount = copy.deepcopy(mount) + else: + continue else: - continue - else: - temp_mount['volname'] = cls.volname - if ('server' not in temp_mount or - (not temp_mount['server'])): - temp_mount['server'] = cls.mnode - if ('mountpoint' not in temp_mount or - (not temp_mount['mountpoint'])): - temp_mount['mountpoint'] = (os.path.join( - "/mnt", '_'.join([cls.volname, - cls.mount_type]))) - if ('client' not in temp_mount or - (not temp_mount['client'])): - temp_mount['client'] = ( - cls.all_clients_info[ - random.choice(cls.all_clients_info.keys())] - ) - cls.mounts_dict_list.append(temp_mount) - found_mount = True - if not found_mount: - for client in cls.all_clients_info.keys(): - mount = { - 'protocol': cls.mount_type, - 'server': cls.mnode, - 'volname': cls.volname, - 'client': cls.all_clients_info[client], - 'mountpoint': (os.path.join( - "/mnt", '_'.join([cls.volname, cls.mount_type]))), - 'options': '' - } - cls.mounts_dict_list.append(mount) - - if cls.mount_type == 'cifs' or cls.mount_type == 'smb': + temp_mount['volname'] = cls.volname + if ('server' not in temp_mount or + (not temp_mount['server'])): + temp_mount['server'] = cls.mnode + if ('mountpoint' not in temp_mount or + (not temp_mount['mountpoint'])): + temp_mount['mountpoint'] = (os.path.join( + "/mnt", '_'.join([cls.volname, + cls.mount_type]))) + if ('client' not in temp_mount or + (not temp_mount['client'])): + temp_mount['client'] = ( + cls.all_clients_info[ + random.choice( + cls.all_clients_info.keys())] + ) + cls.mounts_dict_list.append(temp_mount) + found_mount = True + if not found_mount: + for client in cls.all_clients_info.keys(): + mount = { + 'protocol': cls.mount_type, + 'server': cls.mnode, + 'volname': cls.volname, + 'client': cls.all_clients_info[client], + 'mountpoint': (os.path.join( + "/mnt", '_'.join([cls.volname, cls.mount_type]))), + 'options': '' + } + cls.mounts_dict_list.append(mount) + + if cls.mount_type == 'cifs' or cls.mount_type == 'smb': + for mount in cls.mounts_dict_list: + if 'smbuser' not in mount: + mount['smbuser'] = random.choice( + cls.smb_users_info.keys()) + mount['smbpasswd'] = ( + cls.smb_users_info[mount['smbuser']]['password']) + + cls.mounts = create_mount_objs(cls.mounts_dict_list) + + # Defining clients from mounts. + cls.clients = [] for mount in cls.mounts_dict_list: - if 'smbuser' not in mount: - mount['smbuser'] = random.choice(cls.smb_users_info.keys()) - mount['smbpasswd'] = ( - cls.smb_users_info[mount['smbuser']]['password']) + cls.clients.append(mount['client']['host']) + cls.clients = list(set(cls.clients)) + + # Log the baseclass variables for debugging purposes + g.log.debug("GlusterBaseClass Variables:\n %s", cls.__dict__) + + def setUp(self): + g.log.info("Starting Test: %s", self.id()) - from glustolibs.gluster.mount_ops import create_mount_objs - cls.mounts = create_mount_objs(cls.mounts_dict_list) + def tearDown(self): + g.log.info("Ending Test: %s", self.id()) - # Defining clients from mounts. - cls.clients = [] - for mount_dict in cls.mounts_dict_list: - cls.clients.append(mount_dict['client']['host']) - cls.clients = list(set(cls.clients)) + @classmethod + def tearDownClass(cls): + g.log.info("Teardown class: %s", cls.__name__) class GlusterVolumeBaseClass(GlusterBaseClass): + """GlusterVolumeBaseClass sets up the volume for testing purposes. + """ @classmethod def setUpClass(cls): + """Setup volume, shares/exports volume for cifs/nfs protocols, + mounts the volume. + """ GlusterBaseClass.setUpClass.im_func(cls) # Validate if peer is connected from all the servers @@ -303,72 +306,76 @@ class GlusterVolumeBaseClass(GlusterBaseClass): if not ret: raise ExecutionError("Validating Peers to be in Cluster " "Failed") + g.log.info("All peers are in connected state") - # Print Peer Status from mnode - _, _, _ = peer_status(cls.mnode) + # Peer Status from mnode + peer_status(cls.mnode) # Setup Volume ret = setup_volume(mnode=cls.mnode, all_servers_info=cls.all_servers_info, volume_config=cls.volume, force=True) if not ret: - raise ExecutionError("Setup volume %s failed" % cls.volname) + raise ExecutionError("Setup volume %s failed", cls.volname) time.sleep(10) - # Print Volume Info and Status - _, _, _ = volume_info(cls.mnode, cls.volname) - - _, _, _ = volume_status(cls.mnode, cls.volname) - - # Validate if volume is exported or not - if 'nfs' in cls.mount_type: - cmd = "showmount -e localhost" - _, _, _ = g.run(cls.mnode, cmd) - - cmd = "showmount -e localhost | grep %s" % cls.volname - ret, _, _ = g.run(cls.mnode, cmd) - if not ret: - raise ExecutionError("Volume %s not exported" % cls.volname) + # Export/Share the volume based on mount_type + if cls.mount_type != "glusterfs": + if "nfs" in cls.mount_type: + ret = export_volume_through_nfs( + mnode=cls.mnode, volname=cls.volname, + enable_ganesha=cls.enable_nfs_ganesha) + if not ret: + raise ExecutionError("Failed to export volume %s " + "as NFS export", cls.volname) - if 'cifs' in cls.mount_type: - cmd = "smbclient -L localhost" - _, _, _ = g.run(cls.mnode, cmd) + if "smb" in cls.mount_type or "cifs" in cls.mount_type: + ret = share_volume_over_smb(mnode=cls.mnode, + volname=cls.volname, + smb_users_info=cls.smb_users_info) + if not ret: + raise ExecutionError("Failed to export volume %s " + "as SMB Share", cls.volname) - cmd = ("smbclient -L localhost -U | grep -i -Fw gluster-%s " % - cls.volname) - ret, _, _ = g.run(cls.mnode, cmd) - if not ret: - raise ExecutionError("Volume %s not accessable via SMB/CIFS " - "share" % cls.volname) + # Log Volume Info and Status + ret = log_volume_info_and_status(cls.mnode, cls.volname) + if not ret: + raise ExecutionError("Logging volume %s info and status failed", + cls.volname) # Create Mounts - rc = True + _rc = True for mount_obj in cls.mounts: ret = mount_obj.mount() if not ret: - g.log.error("Unable to mount volume '%s:%s' on '%s:%s'" % - (mount_obj.server_system, mount_obj.volname, - mount_obj.client_system, mount_obj.mountpoint)) - rc = False - if not rc: - raise ExecutionError("Mounting volume %s on few clients failed" % + g.log.error("Unable to mount volume '%s:%s' on '%s:%s'", + mount_obj.server_system, mount_obj.volname, + mount_obj.client_system, mount_obj.mountpoint) + _rc = False + if not _rc: + raise ExecutionError("Mounting volume %s on few clients failed", cls.volname) + # Get info of mount before the IO + log_mounts_info(cls.mounts) + @classmethod def tearDownClass(cls, umount_vol=True, cleanup_vol=True): - """unittest tearDownClass override""" + """Teardown the mounts and volume. + """ + GlusterBaseClass.tearDownClass.im_func(cls) + # Unmount volume if umount_vol: - rc = True + _rc = True for mount_obj in cls.mounts: ret = mount_obj.unmount() if not ret: - g.log.error("Unable to unmount volume '%s:%s' on '%s:%s'" % - (mount_obj.server_system, mount_obj.volname, - mount_obj.client_system, mount_obj.mountpoint) - ) - rc = False - if not rc: + g.log.error("Unable to unmount volume '%s:%s' on '%s:%s'", + mount_obj.server_system, mount_obj.volname, + mount_obj.client_system, mount_obj.mountpoint) + _rc = False + if not _rc: raise ExecutionError("Unmount of all mounts are not " "successful") @@ -376,4 +383,7 @@ class GlusterVolumeBaseClass(GlusterBaseClass): if cleanup_vol: ret = cleanup_volume(mnode=cls.mnode, volname=cls.volname) if not ret: - raise ExecutionError("cleanup volume %s failed" % cls.volname) + raise ExecutionError("cleanup volume %s failed", cls.volname) + + # All Volume Info + volume_info(cls.mnode) -- cgit