diff options
-rwxr-xr-x | ATFCleanup.py | 25 | ||||
-rwxr-xr-x | ATFExecute.py | 68 | ||||
-rwxr-xr-x | ATFInit.py | 233 | ||||
-rwxr-xr-x | ATFSetup.py | 52 | ||||
-rwxr-xr-x | Glusterfs/TestUnits/Replication/Main.py | 93 | ||||
-rwxr-xr-x | Libraries/ClientUtils/ATFClientUtils.py | 213 | ||||
-rwxr-xr-x | Libraries/GlusterCommands/ATFGlusterPeer.py | 38 | ||||
-rwxr-xr-x | Libraries/GlusterCommands/ATFGlusterVolume.py | 230 | ||||
-rwxr-xr-x | Libraries/GlusterCommands/ATFGlusterd.py | 103 | ||||
-rwxr-xr-x | Libraries/Log/ATFLog.py | 221 | ||||
-rwxr-xr-x | Libraries/Ssh/ATFSsh.py | 177 | ||||
-rwxr-xr-x | Libraries/TestEnv/ATFTestEnv.py | 460 | ||||
-rwxr-xr-x | Libraries/Tests/ATFTests.py | 105 | ||||
-rwxr-xr-x | Libraries/Utils/ATFUtils.py | 402 | ||||
-rw-r--r-- | Libraries/Validate/ATFValidate.py | 79 | ||||
-rwxr-xr-x | Templates/GlobalParam.cfg | 95 | ||||
-rwxr-xr-x | Templates/config.cfg | 99 | ||||
-rwxr-xr-x | atf.py | 319 |
18 files changed, 3012 insertions, 0 deletions
diff --git a/ATFCleanup.py b/ATFCleanup.py new file mode 100755 index 0000000..c15f970 --- /dev/null +++ b/ATFCleanup.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python + +import ATFUtils + +def cleanup(): + """ + Description: + * Stop Glusterd on all Servers + * Stop Glusterd on all Clients + * Disconnect all SSH Connections + * Remove all Logger File Handlers + + Parameters: + None + + Returns: 0 + """ + + ATFUtils.stopserversglusterd() + ATFUtils.stopclientsglusterd() + ATFUtils.SshObj.closeall() + ATFUtils.LogObj.remove_detaillog_handler('ATF_LOG') + + return 0 + diff --git a/ATFExecute.py b/ATFExecute.py new file mode 100755 index 0000000..0f3a913 --- /dev/null +++ b/ATFExecute.py @@ -0,0 +1,68 @@ +#!/usr/bin/env python + +import os +import sys +import ATFUtils + +def execute(): + """ + Description: + Execute the TestsCases for Specified TestUnits. + Keyword is used to select the testscases under each TestUnit + + Parameters: + None + + Returns: + Success: 0 ( Successful Execution of all TestUnits ) + Failure: 1 ( Unsuccessful Test Runs ) + """ + + testunits = ATFUtils.TestsObj.get_testunits() + atfroot = ATFUtils.get_environ('ATF_ROOT') + + for unit in testunits: + testdir = atfroot + "/Glusterfs/TestUnits/" + unit + cwd = os.getcwd() + try: + os.chdir(testdir) + + except OSError as (errno, errstr): + ATFUtils.Logger.warning("OSError: [Error %d] %s: %s" % (errno, + errstr, testdir)) + ATFUtils.Logger.warning("Ignoring TestUnit:" + testdir) + continue + + else: + ATFUtils.set_environ(ATF_WORKUNIT=testdir) + try: + os.mkdir('Log') + + except OSError as (errno, errstr): + ATFUtils.Logger.debug("Log Directory already exist") + + ATFUtils.LogObj.add_detaillog_handler('ATF_LOG') + + ATFUtils.Logger.info("Starting Tests in TestUnit: " + testdir) + + sys.path.append(testdir) + import Main + + returncode = Main.main() + + if returncode: + ATFUtils.Logger.error("Test Runs Unsuccessful in TestUnit: " + + testdir) + ATFUtils.Logger.info("Ending Tests in TestUnit: " + testdir) + ATFUtils.LogObj.remove_detaillog_handler('ATF_LOG') + continue + + else: + ATFUtils.Logger.info("Test Runs Successful in TestUnit: " + + testdir) + ATFUtils.Logger.info("Ending Tests in TestUnit: " + testdir) + ATFUtils.LogObj.remove_detaillog_handler('ATF_LOG') + continue + + return 0 + diff --git a/ATFInit.py b/ATFInit.py new file mode 100755 index 0000000..7f28aca --- /dev/null +++ b/ATFInit.py @@ -0,0 +1,233 @@ +#!/usr/bin/env python + +import re +import ConfigParser +import ATFUtils + +######################################################################## +## GlobalParameter file ConfigParser Object +######################################################################## +Config = ConfigParser.ConfigParser() + +def initialize(): + """ + Description: + Initialize ATFUtils.Logger, TestEnvironments + + Parameters: + None + + Returns: + Success: 0 + Failure: 1 + """ + + if ATFUtils.LogObj.create('ATF_LOG'): + return 1 + + if parseGPFile(): + return 1 + + ATFUtils.TestEnvObj.create_servershostlist() + ATFUtils.TestEnvObj.create_clientshostlist() + return 0 + +def ConfigSectionMap(section): + """ + Description: + Get the key=value pair for the Section 'section' + in the GlobalParam File + + Parameters: + section: Section Name in the GlobalParam File + + Returns: + Success: Dictionary: List of key=value pairs from section 'section' + Failure: 1 + """ + + dict1 = {} + + try: + options = Config.options(section) + + except ConfigParser.NoSectionError: + return 1 + + else: + for option in options: + dict1[option] = Config.get(section, option, raw=True) + + return dict1 + +def parseGPFile(): + """ + Description: + Parse Global Parameter file + + Parameters: + filename: Name of GlobalParam File + + Returns: + Success: 0 + Failure: 1 + """ + + filename = ATFUtils.TestEnvObj.get_globalparamfile() + status = Config.read(filename) + + if len(status) == 0: + ATFUtils.Logger.error("GlobalParam File: " + filename + "Not Found") + return 1 + else: + ### Parse Section: [Hosts] ### + Map = ConfigSectionMap('Hosts') + + if Map == 1: + ATFUtils.Logger.error( + "Section [Hosts] Not Found In GlobalParam File: " + + filename) + return 1 + else: + for key in Map.keys(): + name = key + host = Map[key] + name = name.lower() + ATFUtils.TestEnvObj.add_host(name, host) + + ### Parse Section: [Users] ### + Map = ConfigSectionMap("Users") + + if Map == 1: + ATFUtils.Logger.error( + "Section [Users] Not Found In GlobalParam File") + return 1 + else: + for key in Map.keys(): + name = key + user = Map[key] + name = name.lower() + ATFUtils.TestEnvObj.add_user(name, user) + + ### Parse Section: [Servers] ### + + Map = ConfigSectionMap('Servers') + + if Map == 1: + ATFUtils.Logger.error( + "Section [Servers] Not Found In GlobalParam File") + return 1 + else: + for key in Map.keys(): + name = key + value = Map[key] + user, host = re.split('@', value) + name = name.lower() + if ATFUtils.TestEnvObj.add_server(name, host, user): + return 1 + else: + continue + + ### Parse Section: [Clients] ### + Map = ConfigSectionMap('Clients') + + if Map == 1: + ATFUtils.Logger.error( + "Section [Clients] Not Found in GlobalParam File") + return 1 + else: + for key in Map.keys(): + name = key + value = Map[key] + user, host = re.split('@', value) + name = name.lower() + + if ATFUtils.TestEnvObj.add_client(name, host, user): + return 1 + else: + continue + + ### Parse Section: [ExportDirs] ### + Map = ConfigSectionMap('ExportDirs') + + if Map == 1: + ATFUtils.Logger.error( + "Section [ExportDirs] Not Found in GlobalParam File") + return 1 + else: + for key in Map.keys(): + exportname = key + exportdir = Map[key] + exportname = exportname.lower() + ATFUtils.TestEnvObj.add_exportdir(exportname, exportdir) + + ### Parse Section: [MountPoints] ### + Map = ConfigSectionMap('MountPoints') + + if Map == 1: + ATFUtils.Logger.error( + "Section [MountPoints] Not Found in GlobalParam File") + return 1 + else: + for key in Map.keys(): + mountname = key + mountpoint = Map[key] + mountname = mountname.lower() + ATFUtils.TestEnvObj.add_mountpoint(mountname, mountpoint) + + ### Parse Section: [Volumes] ### + Map = ConfigSectionMap('Volumes') + + if Map == 1: + ATFUtils.Logger.error( + "Section [Volumes] Not Found in GlobalParam File") + return 1 + else: + for key in Map.keys(): + volumekey = key + volumename = Map[volumekey] + volumekey = volumekey.lower() + ATFUtils.TestEnvObj.add_volume(volumekey, volumename) + + ### Parse Section: [GlusterfsVersion] ### + Map = ConfigSectionMap('GlusterfsVersion') + + if Map == 1: + ATFUtils.Logger.warning("Section: [GlusterfsVersion] Not Found") + else: + GlusterfsVersion = Map['version'] + if GlusterfsVersion == None: + GlusterfsVersion = '' + + ATFUtils.TestsObj.set_version(GlusterfsVersion) + + try: + fhr = open(filename, "r") + + except IOError: + ATFUtils.Logger.error("IOError:Cannot Open GlobalParam File " + + filename + "For Logging to Summary Log") + + else: + summarylog = ATFUtils.get_environ('ATF_SUMMARYLOG') + try: + fhw = open(summarylog, "a") + + except: + print "IOError: Cannot Open Summary Log FIle " + summarylog + ATFUtils.Logger.warning ( + "Unable to write GlobalParam Contents to SummaryLog: " + + summarylog) + + fhr.close() + + else: + lines = fhr.readlines() + fhw.write(("-" * 50) + "\nExported GlobalParam File: \n" + + ("-" * 50) + "\n") + fhw.writelines(lines) + + fhw.close() + fhr.close() + + return 0 diff --git a/ATFSetup.py b/ATFSetup.py new file mode 100755 index 0000000..502154d --- /dev/null +++ b/ATFSetup.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python + +import ATFUtils + +def setup(): + """ + Description: + * Setup SSH Connections to all Servers + * Setup SSH Connection to all Clients + * Cleanup Glusterd on all Servers + * Cleanup Glusterd on all Clients + * Stop Glusterd on all Servers + * Stop Glusterd on all Clients + * Start Glusterd on all Servers + * Start Glusterd on all Clients + * Peer Probe from a Server to Other Servers + + Returns: + Success: 0 ( If all the Setup Phases are Successful) + Failure: 1 ( If any of the Setup Phase is unsuccessful) + """ + + if ATFUtils.sshservers(): + return 1 + + if ATFUtils.sshclients(): + return 1 + + if ATFUtils.cleanupserversglusterd(): + return 1 + + if ATFUtils.cleanupclientsglusterd(): + return 1 + + if ATFUtils.stopserversglusterd(): + return 1 + + if ATFUtils.stopclientsglusterd(): + return 1 + + if ATFUtils.startserversglusterd(): + return 1 + + if ATFUtils.startclientsglusterd(): + return 1 + + if ATFUtils.peerprobe(): + return 1 + + return 0 + + diff --git a/Glusterfs/TestUnits/Replication/Main.py b/Glusterfs/TestUnits/Replication/Main.py new file mode 100755 index 0000000..fa1888c --- /dev/null +++ b/Glusterfs/TestUnits/Replication/Main.py @@ -0,0 +1,93 @@ +#!/usr/bin/env python + +import ATFGlusterVolume +import ATFClientUtils +import ATFValidate +import ATFUtils +import logging + +def test1(): + """ + Description: Simple Replication Test + Setup:: + * create export directories export1, export2 + * create replicate volume with replica = 2 and transport = tcp + * start replicate volume + * create mount point on the client machine + * mount the replicate volume + + Execution: + * create a file + + Validation: + * Check whether the file is created on export1 and export2 + + Expected: + * File exists on export1 and export2 + + """ + + ATFUtils.Logger.debug("Starting TestCase : [Test001]") + ATFUtils.Logger.debug("Comment: Basic Replication Test") + + if ATFGlusterVolume.create_exportdirs("export1", "export2", host="host1"): + return 1 + + if ATFUtils.set_environ(ATF_HOST = "host1"): + return 1 + + if ATFGlusterVolume.create_volume("volume1", "host1:export1", + "host1:export2", voltype = 'replica 2', + transport = 'transport tcp'): + return 1 + + if ATFGlusterVolume.start_volume("volume1"): + return 1 + + if ATFClientUtils.create_mountpoint("mount1"): + return 1 + + if ATFClientUtils.mount("mount1", "glusterfs", "host1:volume1"): + return 1 + + if ATFClientUtils.touch("file1.txt", user = "root"): + return 1 + + ### Validate ### + + if ATFValidate.validate_replication(f1 = 'host1:export1:file1.txt', f2 = 'host1:export2:file1.txt'): + return 1 + + return 0 + +def cleanup(): + """ Cleanup Phase: + + Description: + * Unmount the client mount point + * Stop the replicate volume + """ + + ATFClientUtils.umount("mount1") + if ATFGlusterVolume.stop_volume("volume1", host="host1"): + return 1 + return 0 + +if __name__ == "__main__": + main() + + +def main(): + + status = 0 + status = test1() + status = cleanup() + return status + + + + + + + + diff --git a/Libraries/ClientUtils/ATFClientUtils.py b/Libraries/ClientUtils/ATFClientUtils.py new file mode 100755 index 0000000..e3a1bfe --- /dev/null +++ b/Libraries/ClientUtils/ATFClientUtils.py @@ -0,0 +1,213 @@ +#!/usr/bin/env python + +import re +import ATFUtils + +def create_mountpoint(mountname, **arguments): + """ + Description: + Create a Mount Point On the Client + + Parameter: + mountname: Name of the MountPoint + **arguments: key=value pair for specifying server, host, user + + Example: + mountname=mount1 + server=server1 + host=host1 + user=user1 + + Returns: + Success: 0 + Failure: 1 + """ + + command = "mkdir -p" + mountpoint = ATFUtils.TestEnvObj.get_mountpoint(mountname) + + if mountpoint == '': + ATFUtils.Logger.error("MountPoint: %s Not defined in GlobalParam File" + % mountname) + return 1 + else: + command = command + " " + mountpoint + + arguments['user'] = 'root' + status, stdin, stdout, stderr = ATFUtils.execute_command(command, + **arguments) + + if status == 1: + return 1 + else: + output = ATFUtils.parse_output(stdout, stderr) + return ATFUtils.set_environ(ATF_MOUNTPOINT = mountname) + +def umount(mountname, **arguments): + """ + Description: + Unmount a mount point + + Parameters: + mountname: Name of the mountpoint to unmount + **arguments: key=value pair for specifying server, host, user + + Example: + mountname=mount1 + server=server1 + host=host1 + user=user1 + + Returns: + Success: 0 + Failure: 1 + """ + + command = "umount" + + mountpoint = ATFUtils.TestEnvObj.get_mountpoint(mountname) + + if mountpoint == '': + ATFUtils.Logger.error("MountPoint: %s Not defined in GlobalParam File" + % mountname) + return 1 + else: + command = command + " " + mountpoint + + arguments['user'] = 'root' + status, stdin, stdout, stderr = ATFUtils.execute_command(command, + **arguments) + + if status == 1: + return 1 + else: + return ATFUtils.parse_output(stdout, stderr) + + +def mount(mountname, fstype, hostvolume, **arguments): + """ + Description: + Mount a filesystem + + Parameter: + mountname: Absolute Path of the mount point + fstype: FileSystem type + hostvolume: HostVolumeName to mount on mountpoint + **arguments: key=value pair for specifying host, user + + Returns: + Success: 0 + Failure: 1 + """ + + command = "mount" + mounttype = " -t " + fstype + command = command + mounttype + hostkey, volumekey = re.split(":", hostvolume) + + host = ATFUtils.TestEnvObj.get_host(hostkey) + if host == '': + ATFUtils.Logger.error("Host %s Not defined in GlobalParam File" % + hostkey) + return 1 + + volumename = ATFUtils.TestEnvObj.get_volume(volumekey) + if volumename == '': + ATFUtils.Logger.error("Volume %s Not defined in GlobalParam File" % + volumekey) + return 1 + + mountpoint = ATFUtils.TestEnvObj.get_mountpoint(mountname) + if mountpoint == '': + ATFUtils.Logger.error("MountPoint: %s Not defined in GlobalParam File" + % mountname) + return 1 + + hostvolume = host + ":" + volumename + command = command + " " + hostvolume + " " + mountpoint + arguments['user'] = 'root' + status, stdin, stdout, stderr = ATFUtils.execute_command(command, + **arguments) + + if status == 1: + return 1 + else: + return ATFUtils.parse_output(stdout, stderr) + + +def touch(filename, mountname='', **arguments): + """ + Description: + Creates a File. + + Parameters: + filename: Name of a file + mountname : Name of the MountPoint + **arguments: key=value pair for specifying host, user + + Returns: + Success: 0 + Failure: 1 + """ + + command = "touch" + + if mountname == '': + mountname = ATFUtils.get_environ('ATF_MOUNTPOINT') + if mountname == 1: + return 1 + + mountpoint = ATFUtils.TestEnvObj.get_mountpoint(mountname) + if mountpoint == '': + ATFUtils.Logger.error("MountPoint: %s Not defined in GlobalParam File" + % mountname) + return 1 + + abspath = mountpoint + "/" + filename + command = command + " " + abspath + status, stdin, stdout, stderr = ATFUtils.execute_command(command, + **arguments) + + if status == 1: + return 1 + else: + return ATFUtils.parse_output(stdout, stderr) + +def mkdir(dirname, mountname='', **arguments): + """ + Description: + Create a Directory under the mountpoint + + Parameters: + dirname: directory path (Relative path from the mount point) + mountname: Name of the Mount Point + **arguments: key=value pair for specifying host, user + + Returns: + Success: 0 + Failure: 1 + """ + + command = "mkdir" + + if mountname == '': + mountname = ATFUtils.get_environ('ATF_MOUNTPOINT') + if mountname == 1: + return 1 + + mountpoint = ATFUtils.TestEnvObj.get_mountpoint(mountname) + if mountpoint == '': + ATFUtils.Logger.error("MountPoint: %s Not defined in GlobalParam File" + % mountname) + return 1 + + abspath = mountpoint + "/" + dirname + command = command + " " + abspath + status, stdin, stdout, stderr = ATFUtils.execute_command(command, + **arguments) + + if status == 1: + return 1 + else: + return ATFUtils.parse_output(stdout, stderr) + diff --git a/Libraries/GlusterCommands/ATFGlusterPeer.py b/Libraries/GlusterCommands/ATFGlusterPeer.py new file mode 100755 index 0000000..9e40f50 --- /dev/null +++ b/Libraries/GlusterCommands/ATFGlusterPeer.py @@ -0,0 +1,38 @@ +#!/usr/bin/env python +import ATFUtils +import ATFTestEnv + +def probe(): + """ + Description: + probe peer specified by <HOSTNAME> + + Parameters: + None + + Returns: + Success: 0 + Failure: 1 + """ + + command = "gluster peer probe " + servers = ATFUtils.TestEnvObj.get_servershostlist() + + length = len(servers) + if (length == 1): + ATFUtils.Logger.warning("Self Probing of Server Not Required") + return 0 + else: + fromhost = servers.pop(0) + for host in servers: + command = command + host + " " + + status, stdin, stdout, stderr = ATFUtils.execute_command(command, + host=fromhost, + user='root') + + if (status == 1): + return 1 + else: + return ATFUtils.parse_output(stdout, stderr) + diff --git a/Libraries/GlusterCommands/ATFGlusterVolume.py b/Libraries/GlusterCommands/ATFGlusterVolume.py new file mode 100755 index 0000000..20bfd4f --- /dev/null +++ b/Libraries/GlusterCommands/ATFGlusterVolume.py @@ -0,0 +1,230 @@ +#!/usr/bin/env python +import ATFUtils +import ATFTestEnv +import re + +def create_volume(volumekey, *exportdirs, **arguments): + """ + Description: + Create a new Volume of specified type with mentioned bricks + + Parameters: + volumekey: Name of the Volume + + exportdirs: List of exportdirs to be used to create Volume + + arguments: Key=Value pair for "Volume Type" and "Transport Type". + 'voltype' = stripe|replica|distribute + 'transport' = tcp|rdma|tcp,rdma + 'host' = Server_IP + 'user' = User + + Return: + Success: 0 + Failure: 1 + + Example: + create('Replicate', + 'host1:export1', + 'host2:export1, + voltype='replica 2', + transport='transport tcp' + host = 'host(1..n)' + server = 'server(1..n)' + ) + """ + + command = "gluster volume create" + + volumename = ATFUtils.TestEnvObj.get_volume(volumekey) + if ( volumename == ''): + ATFUtils.Logger.error("Volume %s Not defined in GlobalParam File" % + volumekey) + return 1 + else: + command = command + " " + volumename + + if (arguments.has_key('voltype')): + command = command + " " + arguments.pop('voltype') + + if (arguments.has_key('transport')): + command = command + " " + arguments.pop('transport') + + exportdirlist = [] + for exportdir in exportdirs: + hostkey, exportkey = re.split(':', exportdir) + + host = ATFUtils.TestEnvObj.get_host(hostkey) + if ( host == '' ): + ATFUtils.Logger.error("Host %s Not defined in GlobalParam File" % + hostkey) + return 1 + + export = ATFUtils.TestEnvObj.get_exportdir(exportkey) + if (export == '' ): + ATFUtils.Logger.error( + "ExportDir %s Not defined in GlobalParam File" % exportkey) + return 1 + + exportdirlist.append(host + ":" +export) + + for exportdir in exportdirlist: + command = command + " " + exportdir + + arguments['user'] = 'root' + status, stdin, stdout, stderr = ATFUtils.execute_command(command, + **arguments) + + if (status == 1): + return 1 + else: + return ATFUtils.parse_output(stdout, stderr) + +def start_volume(volumekey, force='', **arguments): + """ + Description: + Start volume specified by volumename + + Parameters: + volumekey: Name of the Volume + + Returns: + Success: 0 + Failure: 1 + """ + + command = "gluster volume start" + + volumename = ATFUtils.TestEnvObj.get_volume(volumekey) + if ( volumename == ''): + ATFUtils.Logger.error("Volume %s Not defined in GlobalParam File" % + volumekey) + return 1 + else: + command = command + " " + volumename + " " + force + + arguments['user'] = 'root' + status, stdin, stdout, stderr = ATFUtils.execute_command(command, + **arguments) + + if (status == 1): + return 1 + else: + return ATFUtils.parse_output(stdout, stderr) + +def stop_volume(volumekey, force='', **arguments): + """ + Description: + Stop volume specified by volumename + + Parameters: + volumekey: Name of the Volume + force: force stop Gluster Volume + + Returns: + Success: 0 + Failure: 1 + """ + + command = "gluster volume stop" + + volumename = ATFUtils.TestEnvObj.get_volume(volumekey) + if ( volumename == ''): + ATFUtils.Logger.error("Volume %s Not defined in GlobalParam File" % + volumekey) + return 1 + else: + command = command + " " + volumename + " " + force + + arguments['user'] = 'root' + status, stdin, stdout, stderr = ATFUtils.execute_command(command, + **arguments) + + if (status == 1): + return 1 + else: + stdin.write("y\n") + return ATFUtils.parse_output(stdout, stderr) + + +def delete_volume(volumekey, **arguments): + """ + Description: + Delete volume specified by volumename + + Parameters: + volumekey: Name of the Volume + + Returns: + Success: 0 + Failure: 1 + """ + + command = "gluster volume delete" + + volumename = ATFUtils.TestEnvObj.get_volume(volumekey) + if ( volumename == ''): + ATFUtils.Logger.error("Volume %s Not defined in GlobalParam File" % + volumekey) + return 1 + else: + command = command + " " + volumename + + arguments['user'] = 'root' + status, stdin, stdout, stderr = ATFUtils.execute_command(command, + **arguments) + + if (status == 1): + return 1 + else: + stdin.write("y\n") + return ATFUtils.parse_output(stdout, stderr) + +def create_exportdirs(*exportdirs, **arguments): + """ + Description: + Create Bricks on the Server 'server' + + Parameters: + server: IP Address of Server where bricks has to be created + username: User on Server 'server' + bricks: List of Bricks to be created + + Return: + Success: 0 + Failure: 1 + """ + + command = "mkdir -p" + cleanup_command = "rm -rf" + exportdirlist = [] + + for exportkey in exportdirs: + exportdir = ATFUtils.TestEnvObj.get_exportdir(exportkey) + if (exportdir == '' ): + ATFUtils.Logger.error( + "ExportDir %s Not defined in GlobalParam File" % exportkey) + return 1 + else: + exportdirlist.append(exportdir) + + for exportdir in exportdirlist: + command = command + " " + exportdir + cleanup_command = cleanup_command + " " + exportdir + + arguments['user'] = 'root' + status, stdin, stdout, stderr = ATFUtils.execute_command(cleanup_command, + **arguments) + status, stdin, stdout, stderr = ATFUtils.execute_command(command, + **arguments) + + if (status == 1): + return 1 + else: + return ATFUtils.parse_output(stdout, stderr) + + + + + + diff --git a/Libraries/GlusterCommands/ATFGlusterd.py b/Libraries/GlusterCommands/ATFGlusterd.py new file mode 100755 index 0000000..fe2a838 --- /dev/null +++ b/Libraries/GlusterCommands/ATFGlusterd.py @@ -0,0 +1,103 @@ +#!/usr/bin/env python +import ATFUtils + +def start_glusterd(**arguments): + """ + Objective : + Start Glusterd process on the server + + Parameter : + arguments: key = value pair. + server = 'server(1..n)' + host = 'host(1..n)' + Return: + Success : 0 + Failure : 1 + """ + + command = "/etc/init.d/glusterd start" + arguments['user'] = 'root' + status, stdin, stdout, stderr = ATFUtils.execute_command(command, + **arguments) + + if (status == 1): + return 1 + else: + return ATFUtils.parse_output(stdout, stderr) + +def stop_glusterd(**arguments): + """ + Description: + Stop Glusterd process on the server + + Parameter: + arguments: key = value pair. + server = 'server(1..n)' + host = 'host(1..n)' + + Return: + Success : 0 + Failure : 1 + """ + + command = "/etc/init.d/glusterd stop" + arguments['user'] = 'root' + status, stdin, stdout, stderr = ATFUtils.execute_command(command, + **arguments) + + if (status == 1): + return 1 + else: + return ATFUtils.parse_output(stdout, stderr) + +def restart_glusterd(**arguments): + """ + Description: + Restart Glusterd process on the server + + Parameter: + arguments: key = value pair. + server = 'server(1..n)' + host = 'host(1..n)' + + Return: + Success : 0 + Failure : 1 + """ + + command = "/etc/init.d/glusterd restart" + arguments['user'] = 'root' + status, stdin, stdout, stderr = ATFUtils.execute_command(command, + **arguments) + + if (status == 1): + return 1 + else: + return ATFUtils.parse_output(stdout, stderr) + +def cleanup_glusterd(**arguments): + """ + Description: + Cleans up the glusterd directory on Servers + + Parameter: + arguments: key = value pair. + server = 'server(1..n)' + host = 'host(1..n)' + + Return: + Success : 0 + Failure : 1 + """ + + command = "rm -rf /etc/glusterd/*" + arguments['user'] = 'root' + status, stdin, stdout, stderr = ATFUtils.execute_command(command, + **arguments) + + if (status == 1): + return 1 + else: + return ATFUtils.parse_output(stdout, stderr) + + diff --git a/Libraries/Log/ATFLog.py b/Libraries/Log/ATFLog.py new file mode 100755 index 0000000..9165a7c --- /dev/null +++ b/Libraries/Log/ATFLog.py @@ -0,0 +1,221 @@ +#!/usr/bin/env python + +import logging +import ATFUtils + +####################################################################### +## ATFLog class contains variables and methods for Logging +## the events during the test run. +## +## Variables: +## SummaryLog: [filename, loglevel, format] +## +## DetailLog: [filename, loglevel, format] +## +## StdoutLog: [loglevel, format] +## +###################################################################### +class Log(): + + + def __init__(self): + self.SummaryLog = {'format': + '%(asctime)s %(levelname)s : %(filename)s %(lineno)d - \ + \'%(message)s\''} + self.DetailLog = {'format': + '%(asctime)s %(levelname)s : %(pathname)s %(funcName)s \ + %(lineno)d - \'%(message)s\''} + self.StdoutLog = {'logstatus':'false', 'format':'%(asctime)s \ + %(levelname)s : %(filename)s %(lineno)d - \'%(message)s\''} + self.loggers = [] + + def get_loglevel(self, loglevel): + """ + Description: + Returns logging.(LogLevel) for loglevel + + Parameters: + loglevel: String specifying the loglevel + + Returns: + logging.(Loglevel) + """ + + LEVELS = {'DEBUG': logging.DEBUG, + 'INFO': logging.INFO, + 'WARNING': logging.WARNING, + 'ERROR': logging.ERROR, + 'CRITICAL': logging.CRITICAL, + 'debug': logging.DEBUG, + 'info': logging.INFO, + 'warning': logging.WARNING, + 'error': logging.ERROR, + 'critical': logging.CRITICAL} + return LEVELS.get(loglevel, logging.NOTSET) + + def set_summarylog(self, filename='SummaryLog.out', loglevel='INFO'): + """ + Description: + Set Summary Log Name and Log Level + + Parameters: + filename: SummaryLog File Name + loglevel : Log level to be set for summary log + """ + + self.SummaryLog['filename'] = filename + self.SummaryLog['loglevel'] = self.get_loglevel(loglevel) + + def set_detaillog(self, filename='DetailLog.out', loglevel = 'DEBUG'): + """ + Description: + Set Detail Log Name and Log Level + + Parameters: + filename: DetailLog FIle name + loglevel: Log level to be set for detail log + """ + + self.DetailLog['filename'] = filename + self.DetailLog['loglevel'] = self.get_loglevel(loglevel) + + def set_stdoutlog(self, loglevel='INFO'): + """ + Description: + Set Log Level for logging to STDOUT + + Parameters: + loglevel: Log level for logging to STDOUT + """ + + self.StdoutLog['loglevel'] = self.get_loglevel(loglevel) + self.StdoutLog['logstatus'] = 'true' + + def create(self, logname='ATF_LOG'): + """ + Description: + Create a Logger with LogName 'logname' + + Parameters: + logname: Name of the Logger + + Return: + Success: 0 (Successful creation of logger with name : 'logname') + Failure: 1 (Unable to create logger with name: logname) + """ + + # Create a Logger Object with name "logname". + # Set the log level to 'DEBUG' + logger = logging.getLogger(logname) + logger.setLevel(logging.DEBUG) + self.loggers.append({'logname': logname}) + + # Create Summary Log File Handler + # Set the Log Level + # Set the Log Record format for Summary Log + atfrootdir = ATFUtils.get_environ('ATF_ROOT') + abspath = atfrootdir + "/" + self.SummaryLog['filename'] + + try: + summary_handler = logging.FileHandler(abspath, mode='a') + + except IOError as (errno, errstr): + print "I/0 error({0}): {1}".format(errno, errstr) + return 1 + + else: + summary_handler.setLevel(self.SummaryLog['loglevel']) + summary_formatter = logging.Formatter(self.SummaryLog['format']) + summary_handler.setFormatter(summary_formatter) + logger.addHandler(summary_handler) + for log in self.loggers: + if log['logname'] == logname: + log['summary_handler'] = summary_handler + break + + # Create Stdout Log StreamHandler if log to stdout is defined + # Set the Log Level + # Set the Log Record format for STDOUT + if self.StdoutLog['logstatus'] == 'true': + stdout_handler = logging.StreamHandler() + stdout_handler.setLevel(self.StdoutLog['loglevel']) + stdout_formatter = logging.Formatter(self.StdoutLog['format']) + stdout_handler.setFormatter(stdout_formatter) + logger.addHandler(stdout_handler) + for log in self.loggers: + if log['logname'] == logname: + log['stdout_handler'] = stdout_handler + break + + ATFUtils.Logger = logger + return 0 + + def add_detaillog_handler(self, logname): + """ + Description: + Add a Detail Log FileHandler to Logger with logname 'logname' + + Parameters: + logname: Name of the Logger + + Returns: + Success: 0 + Failure: 1 + """ + + logger = logging.getLogger(logname) + + # Create Detail Log File Handler + # Set the Log Level + # Set the Log Record format for Detail Log + atfworkdir = ATFUtils.get_environ('ATF_WORKUNIT') + abspath = atfworkdir + "/Log/" + self.DetailLog['filename'] + + try: + detail_handler = logging.FileHandler(abspath, mode='w') + + except IOError as (errno, errstr): + logger.error("IOError ({0}): {1}".format(errno, errstr)) + return 1 + + else: + detail_handler.setLevel(self.DetailLog['loglevel']) + detail_formatter = logging.Formatter(self.DetailLog['format']) + detail_handler.setFormatter(detail_formatter) + logger.addHandler(detail_handler) + + for log in self.loggers: + if log['logname'] == logname: + log['detail_handler'] = detail_handler + break + + logger.debug("Detail Log File Handler Successfully Added") + + ATFUtils.Logger = logger + return 0 + + def remove_detaillog_handler(self, logname): + """ + Description: + Remove Detail Log File Handler from Logger with + logname 'logname' + + Parameters: + logname: Name of the Logger + """ + + logger = logging.getLogger(logname) + Map = {} + for log in self.loggers: + Map = log + + if Map.has_key('detail_handler'): + detail_handler = log.pop('detail_handler') + logger.removeHandler(detail_handler) + logger.info("DetailLog Handler Removed for the Logger: " + + logname) + else: + logger.warning("DetailLog Handler Not Found for the Logger: " + + logname) + return + diff --git a/Libraries/Ssh/ATFSsh.py b/Libraries/Ssh/ATFSsh.py new file mode 100755 index 0000000..63e690b --- /dev/null +++ b/Libraries/Ssh/ATFSsh.py @@ -0,0 +1,177 @@ +#!/usr/bin/env python +import paramiko +import logging + +################################################################### +## ATFSsh.Ssh Class contains variables and methods for +## Connecting to remote machine using SSH +## +## Variables: +## connections: List of Dictionaries. +## Each Dictionary contains {host, user, conn} information. +## host : Server IP address +## user : User on host +## conn : SSH Conn Object to user@host +################################################################### +class Ssh(): + + + def __init__(self): + self.connections = [] + + def connect(self, host, user): + """ + Objective: + SSH to Server "host" as User "user" + + Parameter: + host: Server IP Address + user: Login Username + + Return: + Success: 0 + Failure: 1 + """ + + logger = logging.getLogger('ATF_LOG') + connection = paramiko.SSHClient() + connection.set_missing_host_key_policy(paramiko.AutoAddPolicy()) + + try: + connection.connect(host, username=user) + + except paramiko.BadHostKeyException as result: + logger.exception( + "BadHostKeyException: Unable to Connect to Server: '" + host + + "' as User: '" + user + "'") + return 1 + + except paramiko.AuthenticationException: + logger.exception("AuthenticationException: Unable to Authenticate " + + user + "@" + host) + return 1 + + except paramiko.SSHException: + logger.exception("SSHException: Unknown server " + host) + return 1 + + else: + self.connections.append({'host':host, 'user': user, 'conn': + connection}) + logger.info("Successfully Able to SSH to: " + user + "@" + host) + + return 0 + + def close(self, host, user): + """ + Objective: + Close SSH Connections for User "username" + on the Server "server" + + Parameters: + server: Server IP Address + username: User on the Server + + Return: + Success: 0 + Failure: 1 + """ + + logger = logging.getLogger('ATF_LOG') + index = 0 + + for conn in self.connections: + if conn['host'] == host and conn['user'] == user: + conn['conn'].close() + logger.info("Closing SSH Connection: " + conn['user'] + "@" + + conn['host']) + self.connection[index:(index + 1)] = [] + index = index - 1 + + index = index + 1 + + return 0 + + def closeall(self): + """ + Objective: + Close All Existing SSH Connections + + Parameters: + None. + + Return: + Success: 0 + Failure: 1 + """ + + logger = logging.getLogger('ATF_LOG') + + for conn in self.connections: + conn['conn'].close() + logger.info("Closing SSH Connection: " + conn['user'] + "@" + + conn['host']) + + self.connections[:] = [] + + return 0 + + def getconnection(self, host, user): + """ + Objective: + Return SSH connection object for username@server + + Parameters: + host: Server IP Address + user: User on the Server + + Return: + Success:SSH connection Object If SSH Connection Object exists + for username@server + Failure: 1 (If SSH Connection doesn't exist) + """ + + for conn in self.connections: + if conn['host'] == host and conn['user'] == user: + return conn['conn'] + + else: + return 1 + + def executecommand(self, command, host, user): + """ + Objective: + Execute Command "comamnd" on user@host + + Parameters: + host: IP address of Server/Client + user: username of user on Host 'host' + command: command to execute + + Return: + Success: 0 + Failure: 1 + """ + + logger = logging.getLogger('ATF_LOG') + output = [] + conn = self.getconnection(host, user) + + if conn == 1: + logger.error("SSH Connection Not Established to:" + user + "@" + + host) + output = [1, 0, 0, 0] + return output + + try: + stdin, stdout, stderr = conn.exec_command(command) + + except paramiko.SSHException: + logger.exception("Unable to Execute Command: " + command) + output = [1, 0, 0, 0] + return output + + else: + output = [0, stdin, stdout, stderr] + return output + diff --git a/Libraries/TestEnv/ATFTestEnv.py b/Libraries/TestEnv/ATFTestEnv.py new file mode 100755 index 0000000..09c5b79 --- /dev/null +++ b/Libraries/TestEnv/ATFTestEnv.py @@ -0,0 +1,460 @@ +#!/usr/bin/env python + +######################################################################## +## TestEnv Class contains variables and methods for storing and retrieving +## information about the Test Environment. +## +## Variables: +## Hosts: List of Dictionaries. +## Each Dictionary contains {'name':name, 'host':host} +## information +## +## Users: List of Dictionaries +## Each Dictionary contains {'name':name, 'user':user} +## information +## +## Servers: List of Dictionaries. +## Each Dictionary contains {'name': name, 'host': host, +## 'user': user} information +## +## Clients: List of Dictionaries. +## Each Dictionary contains {'name': name, 'host': host, +## 'user': user} information +## +## ExportDirs: List of Dictionaries. +## Each Dictionary contains {'exportname': exportname, +## 'exportdir': exportdir} information +## +## ServersHostList: Unique List of Hosts derieved from Servers List +## +## ClientsHostList: Unique List of Hosts derieved from Clients List +## +## +######################################################################## + +class TestEnv(): + + + def __init__(self): + self.Hosts = [] + self.Users = [] + self.Servers = [] + self.Clients = [] + self.ExportDirs = [] + self.ServersHostList = [] + self.ClientsHostList = [] + self.MountPoints = [] + self.Volumes = [] + self.GlobalParamFile = '' + + def set_globalparamfile(self, filename): + """ + Description: + Sets GlobalParameter file name + + Parameter: + filename: Name of the GlobalParam File + + Returns: + """ + + self.GlobalParamFile = filename + return + + def get_globalparamfile(self): + """ + Description: + Return GlobalParamFileName + + Parameter: + None + + Returns: + GlobalParamFIleName + """ + + return self.GlobalParamFile + + def add_host(self, name, host): + """ + Description: + Add a host to Hosts List + + Parameters: + name: Name of the host Ex: host1, host2 + host: Address of the host Ex: 192.168.1.5 + + Return: + """ + + self.Hosts.append({'name': name, 'host': host}) + return + + def get_host(self, name): + """ + Description: + Return host with name 'name' + + Parameters: + name: Name of the host to return + + Returns: + Success: host + Failure: '' + """ + + output = '' + + for host in self.Hosts: + if host['name'] == name: + output = host['host'] + break + + return output + + def get_hostslist(self): + """ + Description: + Returns self.Servers List + Returns: + self.Servers + """ + + return self.Hosts + + def add_user(self, name, user): + """ + Description: + Add a user to Users List + + Parameters: + name: key to recognize a user Ex: user1/user2 + user: Username + + Return: + """ + + self.Users.append({'name': name, 'user': user}) + return + + def get_user(self, name): + """ + Description: + Return user with key 'name' + + Parameters: + name: key used to recognize the user + + Returns: + Success: user + Failure: '' + """ + + output = '' + + for user in self.Users: + if user['name'] == name: + output = user['user'] + break + + return output + + def add_server(self, name, hostkey, userkey): + """ + Description: + Add a server to Servers List + + Parameters: + name: Name of the server (Example: Server1/Server2) + host: IP Address of the server + user: Username of User on 'host' + + Returns: + Success: 0 + Failure: 1 + """ + + host = self.get_host(hostkey) + user = self.get_user(userkey) + + if host == '' or user == '': + ATFUtils.Logger.error("%s or %s Not Defined " % (hostkey, userkey)) + return 1 + + self.Servers.append({'name': name, 'host': host, 'user': user}) + return 0 + + def get_server(self, name): + """ + Description: + Returns [host, user] tuple for Server Name 'name' + + Parameters: + name: Name of the Server + + Returns: + Success: Returns [host, user] tuple + Failure: ['', ''] tuple + """ + + output = ['', ''] + + for server in self.Servers: + if server['name'] == name: + output = [server['host'], server['user']] + break + + return output + + def get_serverslist(self): + """ + Description: + Returns self.Servers List + + Parameters: + None + + Returns: + self.Servers + """ + + return self.Servers + + def add_client(self, name, hostkey, userkey): + """ + Description: + Add a client to Clients List + + Parameters: + name: Name of the client (Example: Client1/Client2) + host: IP Address of the client + user: Username of User on 'host' + + Returns: + Success: 0 + Failure: 1 + """ + + host = self.get_host(hostkey) + user = self.get_user(userkey) + + if host == '' or user == '': + ATFUtils.Logger.error("%s or %s Not Defined " % (hostkey, userkey)) + return 1 + + self.Clients.append({'name': name, 'host': host, 'user': user}) + return 0 + + def get_client(self, name): + """ + Description: + Returns [host, user] tuple for Client Name 'name' + + Parameters: + name: Name of the Client + + Returns: + Success: Returns [host, user] tuple + Failure: ['', ''] tuple + """ + + output = ['', ''] + + for client in self.Clients: + if client['name'] == name: + output = [client['host'], client['user']] + break + + return output + + def get_clientslist(self): + """ + Description: + Returns self.Clients List + + Parameters: + None + + Returns: + self.Clients + """ + + return self.Clients + + def add_exportdir(self, exportname, dirname): + """ + Description: + Add a Export Directory to the Export Directory List + + Parameters: + exportname: Name of a Export Directory(Example: export1/export2) + dirname: Absolute Path of the Export DIrecotry + + Returns: + """ + + self.ExportDirs.append({'exportname': exportname, 'dirname': dirname}) + return + + def get_exportdir(self, exportname): + """ + Description: + Return Dir Name of the Export Directory Name 'exportname' + + Parameters: + exportname: Name of a Export Directory + + Returns: + Success: Absolute Path of Export DIrectory + Failure: '' + """ + + output = '' + + for exportdir in self.ExportDirs: + if exportdir['exportname'] == exportname: + output = exportdir['dirname'] + break + + return output + + def add_mountpoint(self, mountname, dirname): + """ + Description: + Add a Mount Point to the MountPoint List + + Parameters: + mountname: Name of a MountPoint(Example: mount1/mount2) + dirname: Absolute Path of the Mount Point + + Returns: + """ + + self.MountPoints.append({'mountname': mountname, 'dirname': dirname}) + return + + def get_mountpoint(self, mountname): + """ + Description: + Return MountPoint with Name 'mountname' + + Parameters: + mountname: Name of a MountPoint + + Returns: + Success: Absolute Path of MountPoint + Failure: '' + """ + + output = '' + + for mountpoint in self.MountPoints: + if mountpoint['mountname'] == mountname: + output = mountpoint['dirname'] + break + + return output + + def add_volume(self, volumekey, volumename): + """ + Description: + Add a Volume to Volumes List + + Parameters: + volumekey: key used to recognize the volumename Ex: volume1 + volumename: Volume Name Ex: Replicate_Volume + + Returns: + """ + + self.Volumes.append({'volumekey': volumekey, 'volumename': volumename}) + return + + def get_volume(self, volumekey): + """ + Description: + Returns Volumename with Volumekey 'volumekey' + + Parameters: + volumekey: VolumeKey + + Returns: + Success: Volumename + Failure: '' + """ + + output = '' + + for volume in self.Volumes: + if volume['volumekey'] == volumekey: + output = volume['volumename'] + break + + return output + + def create_servershostlist(self): + """ + Description: + Creats a Unique List of Hosts from the Servers List + + Parameters: + None + + Returns: + """ + + for server in self.Servers: + host = server['host'] + + if host not in self.ServersHostList: + self.ServersHostList.append(host) + + return + + def create_clientshostlist(self): + """ + Description: + Creats a Unique List of Hosts from the Clients List + + Parameters: + None + + Returns: + """ + + for client in self.Clients: + host = client['host'] + + if host not in self.ClientsHostList: + self.ClientsHostList.append(host) + + return + + def get_servershostlist(self): + """ + Description: + Returns ServersHostList + + Parameters: + None + + Returns: + Return ServersHostList + """ + + return self.ServersHostList + + def get_clientshostlist(self): + """ + Description: + Returns ClientsHostList + + Parameters: + None + + Returns: + Return ClientsHostList + """ + + return self.ClientsHostList + diff --git a/Libraries/Tests/ATFTests.py b/Libraries/Tests/ATFTests.py new file mode 100755 index 0000000..245e96a --- /dev/null +++ b/Libraries/Tests/ATFTests.py @@ -0,0 +1,105 @@ +#!/usr/bin/env python + +############################################################################## +## ATFTests Class contains variables and methods for storing and retrieving +## information about "TESTS" that has to be executed. +## +## Variables: +## TestUnits: List of TestUnits to be run. +## +## KeyWords: List of keywords to be used to select tests under each +## TestUnit. +## +## Version: Glusterfs version. This is used to select tests based on version +## of Glusterfs. +############################################################################## + +class Tests(): + def __init__(self): + self.TestUnits = [] + self.KeyWords = [] + self.Version = '' + + def add_testunits(self, testunit): + """ + Description: + Add a testunit to TestUnits List + + Parameter: + testunit: Name of the Testing Unit + + Returns: + """ + + self.TestUnits.append(testunit) + return + + def sort_testunits(self): + """ + Description: + Sort the TestUnit List in Descending Order + + Parameter: + + Returns: + """ + + self.TestUnits.sort() + self.TestUnits.reverse() + return + + def get_testunits(self): + """ + Description: + Return TestUnits List + + Parameters: + + Returns: + Success: Testunit Name + Failure: '' + """ + + return self.TestUnits + + def add_keywords(self, keyname): + """ + Description: + Add Keywords to KeyWords List + + Parameters: + keyname: Keyword + + Returns: + """ + + self.KeyWords.append(keyname) + return + + def set_version(self, version): + """ + Description: + Set Glusterfs Version under test. + + Parameters: + version: Glusterfs version + + Returns: + """ + + self.Version = version + return + + def get_version(self): + """ + Description: + Returns Glusterfs Vesrion under test + + Parameters: + + Returns: + Glusterfs Version + """ + + return self.Version + diff --git a/Libraries/Utils/ATFUtils.py b/Libraries/Utils/ATFUtils.py new file mode 100755 index 0000000..0afcf22 --- /dev/null +++ b/Libraries/Utils/ATFUtils.py @@ -0,0 +1,402 @@ +#!/usr/bin/env python + +import os +import re +import logging +import ATFLog +import ATFTests +import ATFTestEnv +import ATFSsh +import ATFGlusterd +import ATFGlusterPeer + +######################################################################### +## ATFLog.Log Object +######################################################################### +LogObj = ATFLog.Log() + +######################################################################### +## ATFTests.Tests Object +######################################################################### +TestsObj = ATFTests.Tests() + +######################################################################### +## ATFTestEnv.TestEnv Object +######################################################################### +TestEnvObj = ATFTestEnv.TestEnv() + +######################################################################### +## ATFSsh.Ssh Object +######################################################################### +SshObj = ATFSsh.Ssh() + +######################################################################### +## Logger for 'ATF_LOG' +######################################################################### +Logger = logging.getLogger('ATF_LOG') + +def set_environ(**arguments): + """ + Description: + Set the Env Variable 'envvar' to Value 'value' + + Parameters: + **arguments: key=value pairs. + key: Environment Variable name + value: Value of the Environment Valiable + + Return: + Success: 1 (Successfully Set the envar to value) + Failure: 0 (Unable to set the envvar to value) + + Example: + ATFUtils.set_environ(ATF_USER = user1 ,ATF_SERVER = server1) + """ + + envvars = sorted(arguments.keys()) + + for var in envvars: + try: + os.environ[var] = arguments[var] + + except KeyError as (key): + Logger.error("Unable to Export Environment Variable '" + key + "'") + return 1 + + else: + Logger.debug("Exported Environment Variable '" + var + "' = " + + arguments[var]) + + return 0 + +def get_environ(envvar, log = 1): + """ + Description: + Return the Value of Environment Variable 'envvar' + + Parameters: + name: Name of the Environment Variable + log: To keep track of whether to log the error message or not + + Return: + Success : Value of Environment Variable 'envvar' + Failure: 1 + """ + + try: + value = os.environ[envvar] + + except KeyError: + if log == 1: + Logger.error("Key Error: Environment Variable %s Not Defined" % + envvar) + value = 1 + + except OSError as key: + if log == 1: + Logger.error("Environment Variable '" + key + "' Not Defined") + value = 1 + + else: + Logger.debug("Returning " + envvar + " = " + value) + + return value + +def parse_output(stdout, stderr): + """ + Description: + Parse the STDOUT and STDERR ChannelFiles + + Parameter: + stdout: ChannelFile for stdout + stderr: ChannelFile for stderr + + Return: + Success: 0 (STDOUT has DATA) + Failure: 1 (STDERR has DATA) + """ + + output = stderr.readlines() + + if len(output) == 0: + for line in stdout.readlines(): + Logger.debug(line) + return 0 + else: + for line in output: + Logger.error(line) + return 1 + +def execute_command(command, **arguments): + """ + Description: + + Parameter: + command: Command to be executed + **arguments: key=value pair for specifying server, host, user + + Returns: + Success: 0 + Failure: 1 + """ + + output = [1, 0, 0, 0] + ip_string = '(?:[\d]{1,3})\.(?:[\d]{1,3})\.(?:[\d]{1,3})\.(?:[\d]{1,3})' + serverkey = hostkey = userkey = '' + serverkeyfound = hostkeyfound = 0 + + if arguments.has_key('server'): + serverkey = arguments['server'] + serverkeyfound = 1 + elif arguments.has_key('host'): + hostkey = arguments['host'] + hostkeyfound = 1 + else: + serverkey = get_environ('ATF_SERVER', log = 0) + + if serverkey == 1: + serverkeyfound = 0 + hostkey = get_environ('ATF_HOST') + + if hostkey == 1: + Logger.error("Server/Host not defined for command execution") + return output + else: + hostkeyfound = 1 + else: + serverkeyfound = 1 + + if serverkeyfound == 1: + host, user = TestEnvObj.get_server(serverkey) + + if host == '' or user == '': + Logger.error("Server: " + serverkey + + "Not Defined in GlobalParam File") + return output + elif hostkey != '': + if re.match(ip_string, hostkey): + host = hostkey + else : + host = TestEnvObj.get_host(hostkey) + if host == '': + Logger.error("Host: " + hostkey + + "Not Defined in GlobalParam File") + return output + + if arguments.has_key('user'): + userkey = arguments['user'] + else: + userkey = get_environ('ATF_USER') + if userkey == 1: + Logger.error( + "Ignoring KeyError: Environment Variable ATF_USER Not " + + "Defined for command execution") + return output + + if userkey != 'root': + user = TestEnvObj.get_user(userkey, log = 0) + if user == '': + Logger.error("User: " + userkey + + "Not Defined in GlobalParam File") + return output + else: + user = 'root' + + Logger.info("Executing Command: " + command + " - " + user + "@" + host) + status, stdin, stdout, stderr = SshObj.executecommand(command, host, user) + output = [status, stdin, stdout, stderr] + return output + +def sshservers(): + """ + Description: + SSH to all Servers in the ServersList + + Parameters: + None + + Returns: + Success: 0 + Failure: 1 + """ + + for server in TestEnvObj.get_serverslist(): + host = server['host'] + user = server['user'] + + if SshObj.connect(host, user): + return 1 + else: + continue + + return 0 + +def sshclients(): + """ + Description: + SSH to all Clients in the ClientsList + + Parameters: + None + + Returns: + Success: 0 + Failure: 1 + """ + + for client in TestEnvObj.get_clientslist(): + host = client['host'] + user = client['user'] + + if SshObj.connect(host, user): + return 1 + else: + continue + + return 0 + +def cleanupserversglusterd(): + """ + Descriptions: + Cleanup glusterd directory on all Servers in ServersList + + Parameters: + None + + Returns: + Success: 0 + Failure: 1 + """ + + for host in TestEnvObj.get_servershostlist(): + if ATFGlusterd.cleanup_glusterd(host = host): + return 1 + else: + continue + + return 0 + +def cleanupclientsglusterd(): + """ + Description: + Cleanup Glusted directory on all the Clients in ClientsList + + Parameters: + None + + Returns: + Success: 0 + Failure: 1 + """ + + for host in TestEnvObj.get_clientshostlist(): + if ATFGlusterd.cleanup_glusterd(host = host): + return 1 + else: + continue + + return 0 + +def stopserversglusterd(): + """ + Description: + Stop Glusterd on all the Servers in ServersList + + Parameters: + None + + Returns: + Success: 0 + Failure: 1 + """ + + for host in TestEnvObj.get_servershostlist(): + if ATFGlusterd.stop_glusterd(host = host): + return 1 + else: + continue + + return 0 + +def stopclientsglusterd(): + """ + Description: + Stop Glusted on all the Clients in ClientsList + + Parameters: + None + + Returns: + Success: 0 + Failure: 1 + """ + + for host in TestEnvObj.get_clientshostlist(): + if ATFGlusterd.stop_glusterd(host = host): + return 1 + else: + continue + + return 0 + +def startserversglusterd(): + """ + Description: + Start Glusterd on all the Servers in ServersList + + Parameters: + None + + Returns: + Success: 0 + Failure: 1 + """ + + for host in TestEnvObj.get_servershostlist(): + if ATFGlusterd.start_glusterd(host = host): + return 1 + else: + continue + + return 0 + +def startclientsglusterd(): + """ + Description: + Start GLusterd on all Clients in ClientsList + + Parameters: + None + + Returns: + Success: 0 + Failure: 1 + """ + + for host in TestEnvObj.get_clientshostlist(): + if ATFGlusterd.start_glusterd(host = host): + return 1 + else: + continue + + return 0 + +def peerprobe(): + """ + Description: + PeerProbe to all Servers in ServerList from one of the server + in the ServerList + + Parameters: + None + + Returns: + Success: 0 + Failure: 1 + """ + + if ATFGlusterPeer.probe(): + return 1 + else: + return 0 + diff --git a/Libraries/Validate/ATFValidate.py b/Libraries/Validate/ATFValidate.py new file mode 100644 index 0000000..9cebbf8 --- /dev/null +++ b/Libraries/Validate/ATFValidate.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python + +import re +import ATFUtils + +def validate_replication(**arguments): + """ + Description: + Validate whether the files are replicated or not + + Parameters: + arguments: key=value pair. + key: file1..filen + value: host:exportdir:filename comabination + + Example:f1 = 'host1:export1:file1.txt', f2 = 'host1:export2:file1.txt + + Returns: + Success: 0 + Failure: 1 + """ + + Map = [] + command = "ls" + + for key in arguments.keys(): + value = arguments[key] + hostkey, exportkey, filename = re.split(":", value) + + host = ATFUtils.TestEnvObj.get_host(hostkey) + if (host == ''): + ATFUtils.Logger.error("Host %s Not defined in GlobalParam File" % + hostkey) + return 1 + + exportdir = ATFUtils.TestEnvObj.get_exportdir(exportkey) + if (exportdir == ''): + ATFUtils.Logger.error( + "ExportDir %s Not defined in GlobalParam File" % exportkey) + return 1 + else: + abspath = exportdir + "/" + filename + Map.append({'host':host, 'path':abspath}) + + + for item in Map: + arguments['host'] = item['host'] + arguments['user'] = 'root' + abspath = item['path'] + val_command = command + " " + abspath + + status, stdin, stdout, stderr = ATFUtils.execute_command(val_command, + **arguments) + + if ( status == 1): + ATFUtils.Logger.error("Error in Validation") + else: + status = False + readout = stdout.readlines() + readerr = stderr.readlines() + + if( len(readerr) == 0): + for line in readout: + if ( re.match(abspath, line)): + status = True + else: + status = False + + if (status == False): + ATFUtils.Logger.error("Validation Failed: Path Not found - %s" % abspath) + return + else: + continue + + if(status == True): + ATFUtils.Logger.info("Validate_replication Successfully Complete") + + return 0 + diff --git a/Templates/GlobalParam.cfg b/Templates/GlobalParam.cfg new file mode 100755 index 0000000..9e74e6d --- /dev/null +++ b/Templates/GlobalParam.cfg @@ -0,0 +1,95 @@ +############################################################################# +## GlobalParameter File +## This File is used to specify the TestEnvironment/TestBed under Test. +############################################################################# + +############################################################################# +## Section: [Hosts] +## host = IP_Address of the Machine +## Example: +## host1 = 192.168.0.2 +## host2 = 192.168.0.3 +############################################################################# +[Hosts] +host1 = + +############################################################################# +## Section: [Users] +## user = Name of the User involved +## Example: +## user1 = root +## user2 = qa +############################################################################# +[Users] +user1 = + +############################################################################# +## Section: [Servers] +## server = user@host combination. +## List of Servers in the TestEnvironment. +## Every SSH Connection is recognized by user@host. +## +## Example: +## server1 = user1@host1 +############################################################################# +[Servers] +server1 = + +############################################################################# +## Section: [Clients] +## server = user@host combination. +## List of Clients in the TestEnvironment. +## Every SSH Connection is recognized by user@host. +## +## Example: +## client1 = user2@host1 +############################################################################# +[Clients] +client1 = + +############################################################################# +## Section: [ExportDirs] +## exportdir = Absolute Path of the exportdirectories +## +## Example: +## export1 = /home/export1 +## export2 = /home/export2 +############################################################################# +[ExportDirs] +export1 = + +############################################################################# +## Section: [MountPoints] +## mount = Absolute Path of the Mount Points +## +## Example: +## mount1 = /mnt/client1 +## mount2 = /mnt/client2 +############################################################################# +[MountPoints] +mount1 = + +############################################################################# +## Section: [Volumes] +## volume = name of the volume +## +## Example: +## volume1 = replicate_volume +## volume2 = distribute_volume +## volume3 = stripe_volume +############################################################################# +[Volumes] +volume1 = + +############################################################################# +## Section: [GlusterfsVersion] +## version = GlusterFSVersion under test +## Example: +## version = 3.2 +############################################################################# +[GlusterfsVersion] +version = + + + + diff --git a/Templates/config.cfg b/Templates/config.cfg new file mode 100755 index 0000000..e498115 --- /dev/null +++ b/Templates/config.cfg @@ -0,0 +1,99 @@ +############################################################################# +## ATF Configuration File. This is input for the atf.py python script. +## This File contains various sections. +## The information under each section will be used for Selecting/Running Tests +############################################################################# + +############################################################################# +## Section: [Keywords] +## Used to select the testcases tagged with keystring for test execution. +## keystring: sanity +## Selects all testcases tagged with sanity keyword under given TestUnit +## (This is used for Sanity Runs) +## keystring: art +## Selects all testcases tagged with art keyword under given TestUnit +## (This is used for Regression Runs) +## Example: +## keystring = art +## keystring = sanity +############################################################################# +[Keywords] +keystring = + +############################################################################# +## Section: [WorkUnits] +## unit specifies glusterfs features (testuntis) under test. +## Each TestUnit is directory under Glusterfs/TestUnits directory +## Example: +## unit1 = Replication +## unit2 = Replication/Self-heal +## unit3 = Distribution +## unit4 = Stripe +############################################################################# +[WorkUnits] +unit1 = + +############################################################################# +## Section: [ATFRoot] +## rootdir = absolute path of the directory where Automation Framework +## is Installed +## Example: +## rootdir = /ATF +## rootdir = /home/qa/ATF +############################################################################# +[ATFRoot] +rootdir = + +############################################################################# +## Section: [SummaryLog] +## filename = FileName to Log SummaryLogs +## loglevel = LogLevel could be debug| info | warning | error +## Example: +## filename = SummaryLog.out +## loglevel = info +############################################################################# +[SummaryLog] +filename = +loglevel = + +############################################################################# +## Section: [DetailLog] +## filename = FileName to Log DetailLogs of test case execution +## loglevel = LogLevel could be debug| info | warning | error +## Example: +## filename = DetailLog.out +## loglevel = info +############################################################################# +[DetailLog] +filename = +loglevel = + +############################################################################# +## Section: [StdoutLog] +## do_log = true | false. +## If do_log = true, Log to STDOUT. Else, do not log to STDOUT. +## loglevel = LogLevel could be debug| info | warning | error +## Example: +## do_log = true +## loglevel = info +############################################################################# +[StdoutLog] +do_log = +loglevel = + +############################################################################# +## Section: [GlobalParam] +## filename = Absolute path of the global Parameter File. +## GlobalParam file contains information about the TestEnvironment. +## Example: +## filename = /ATF/GlobalParam.cfg +## filename = /home/qa/ATF/GlobalParam.cfg +############################################################################# +[GlobalParam] +filename = + + + + + + @@ -0,0 +1,319 @@ +#!/usr/bin/env python + +import sys +import argparse +import ConfigParser +import ATFInit +import ATFSetup +import ATFExecute +import ATFCleanup +import ATFUtils + +########################################################################## +## commandline : command executed to start the TestRun. +########################################################################## +commandline = '' + +########################################################################## +## Configuration File Parser Object +########################################################################## +Config = ConfigParser.SafeConfigParser() + +def ConfigSectionMap(section): + """ + Description: + Get the key=value pair for the Section 'section' in the Config File + + Parameters: + section: Section Name in the Config File + + Returns: + Success: Dictionary: List of key=value pairs from section 'section' + Failure: 1 + """ + + dict1 = {} + + try: + options = Config.options(section) + + except ConfigParser.NoSectionError: + return 1 + + else: + for option in options: + dict1[option] = Config.get(section, option) + + return dict1 + +def parse_configfile(filename): + """ + Description: + Function to Parse the Configuration file + + Parameters: + filename: Name of the configuration file + + Returns: + Success: 0 + Failure: 1 + """ + + keyword = '' + workunit = '' + + status = Config.read(filename) + + if status == []: + print "Configuration File: " + filename + "Not Found" + return 1 + else: + ### Parse Section: [Keywords] ### + Map = ConfigSectionMap('Keywords') + + if Map == 1: + print "Section: [Keywords] Not Found" + return 1 + else: + keyword = Map['keystring'] + ATFUtils.TestsObj.add_keywords(keyword) + + ### Parse Section: [WorkUnits] ### + Map = ConfigSectionMap('WorkUnits') + + if Map == 1: + print "Section: [WorkUnits] Not Found" + return 1 + else: + for key in Map.keys(): + workunit = Map[key] + ATFUtils.TestsObj.add_testunits(workunit) + ATFUtils.TestsObj.sort_testunits() + + ### Parse Section: [ATFRoot] ### + Map = ConfigSectionMap('ATFRoot') + + if Map == 1: + print "Section: [ATFRoot] Not Found" + return 1 + else: + atfroot = Map['rootdir'] + + if atfroot == None: + print "ATF_ROOT Not defined. " + return 1 + else: + if ATFUtils.set_environ(ATF_ROOT = atfroot): + return 1 + + ### Parse Section: [SummaryLog] ### + Map = ConfigSectionMap('SummaryLog') + + if Map == 1: + print "Section: [SummaryLog] Not Found" + return 1 + else: + summarylog_filename = Map['filename'] + summarylog_level = Map['loglevel'] + + if summarylog_filename == None: + summarylog_filename = 'SummaryLog.out' + + if summarylog_level == None: + summarylog_level = 'INFO' + + ATFUtils.LogObj.set_summarylog(filename=summarylog_filename, + loglevel=summarylog_level) + abspath = atfroot + "/" + summarylog_filename + + if ATFUtils.set_environ(ATF_SUMMARYLOG = abspath): + return 1 + + ### Parse Detail Log Section ### + Map = ConfigSectionMap('DetailLog') + + if Map == 1: + print "Section: [DetailLog] Not Found" + return 1 + else: + detaillog_filename = Map['filename'] + detaillog_level = Map['loglevel'] + + if detaillog_filename == None: + detaillog_filename = 'DetailLog.out' + + if detaillog_level == None: + detaillog_level = 'DEBUG' + + ATFUtils.LogObj.set_detaillog(filename=detaillog_filename, + loglevel=detaillog_level) + + ### Parse Stdout Log Section ### + Map = ConfigSectionMap('StdoutLog') + + if Map == 1: + print "Section: [StdoutLog] Not Found" + else: + stdoutlog_log = Map['do_log'] + stdoutlog_level = Map['loglevel'] + + if stdoutlog_log == 'true': + if stdoutlog_level == None: + stdoutlog_level = 'INFO' + ATFUtils.LogObj.set_stdoutlog(loglevel=stdoutlog_level) + + ### Parse GlobalParam Section ### + Map = ConfigSectionMap('GlobalParam') + + if Map == 1: + print "Section: [GlobalParam] Not Found" + return 1 + else: + globalparamfile = Map['filename'] + + if globalparamfile == None: + print "Global Param File Not defined." + return 1 + else : + ATFUtils.TestEnvObj.set_globalparamfile(globalparamfile) + + #### Log the contents of Config File to SummaryLog and Stdout #### + abspath = atfroot + "/" + summarylog_filename + + try: + fhr = open(filename, "r") + + except IOError: + print "IOError: Cannot Open Config FIle for Reading" + abspath + return 1 + + else: + try: + fhw = open(abspath, "w") + + except IOError: + print "IOError: Cannot Open Summary Log FIle " + abspath + fhr.close() + return 1 + + else: + lines = fhr.readlines() + fhw.write("Starting the Glusterfs Regression Tests") + fhw.write("\n\nCommandLine: " + commandline + "\n\n") + fhw.write(("-" * 50) + "\nConfiguration File Contents: \n" + + ("-" * 50) + "\n") + fhw.writelines(lines) + + fhw.close() + fhr.close() + + return 0 + +def main(args): + """ + Description: + 1) Parse the Configuration File + 2) Initialize the Loggers, TestEnvironment + 3) Set-up TestBed for TestRun Execution + 4) Execute the Tests for the WorkUnits Specified + 5) Cleanup the TestEnvironment after the Test Execution is complete + + Parameters: + args: Command Line Arguments passed to 'atf' + + Returns: + Success: 0 + Failure: 1 + """ + + configfilename = args.file[0] + if parse_configfile(configfilename): + exit(1) + + if ATFInit.initialize(): + exit(1) + + if ATFSetup.setup(): + exit(1) + + if ATFExecute.execute(): + exit(1) + + if ATFCleanup.cleanup(): + exit(1) + + else: + exit(0) + +if __name__ == "__main__": + + for arg in sys.argv: + commandline = commandline + arg + " " + + parser = argparse.ArgumentParser( + description="Runs GlusterFS Regression Test Suite", + epilog="Report Bugs to dl-qa@gluster.com") + + parser.add_argument('-f', '--file', nargs=1, required=True, type=str, + help="Configuration FIleName") + + args = parser.parse_args() + + main(args) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + |