From 77c7f324610224e808d8940aec7e6dbf19b790a5 Mon Sep 17 00:00:00 2001 From: Shwetha-H-Panduranga Date: Tue, 6 Dec 2011 14:26:59 +0530 Subject: Adding New/Updated Automation Files --- SharedModules/Connect/ssh.py | 114 +++++ SharedModules/Globals/atfglobals.py | 85 ++++ SharedModules/Globals/logger.py | 211 +++++++++ SharedModules/Globals/manager.py | 64 +++ SharedModules/Globals/testenv.py | 462 ++++++++++++++++++++ SharedModules/Globals/testruninfo.py | 144 +++++++ SharedModules/Parser/parser.py | 315 ++++++++++++++ SharedModules/Utils/atfutils.py | 58 +++ SharedModules/Utils/clientutils.py | 282 ++++++++++++ SharedModules/Utils/glusterutils.py | 644 ++++++++++++++++++++++++++++ SharedModules/Utils/hostutils.py | 193 +++++++++ SharedModules/Utils/managerutils.py | 55 +++ SharedModules/Utils/serverutils.py | 33 ++ TestUnits/replicate/self_heal/Main.py | 69 +++ TestUnits/replicate/self_heal/testcases.py | 96 +++++ TestUnits/replicate/self_heal/testcaseslist | 9 + TestUnits/replicate/self_heal/testenv.cfg | 98 +++++ atf.py | 51 +++ atfexecute.py | 63 +++ atfinit.py | 27 ++ atfsetup.py | 37 ++ export.py | 13 + testruninfo.cfg | 99 +++++ 23 files changed, 3222 insertions(+) create mode 100755 SharedModules/Connect/ssh.py create mode 100644 SharedModules/Globals/atfglobals.py create mode 100644 SharedModules/Globals/logger.py create mode 100755 SharedModules/Globals/manager.py create mode 100755 SharedModules/Globals/testenv.py create mode 100644 SharedModules/Globals/testruninfo.py create mode 100644 SharedModules/Parser/parser.py create mode 100644 SharedModules/Utils/atfutils.py create mode 100644 SharedModules/Utils/clientutils.py create mode 100644 SharedModules/Utils/glusterutils.py create mode 100644 SharedModules/Utils/hostutils.py create mode 100644 SharedModules/Utils/managerutils.py create mode 100644 SharedModules/Utils/serverutils.py create mode 100644 TestUnits/replicate/self_heal/Main.py create mode 100644 TestUnits/replicate/self_heal/testcases.py create mode 100644 TestUnits/replicate/self_heal/testcaseslist create mode 100644 TestUnits/replicate/self_heal/testenv.cfg create mode 100755 atf.py create mode 100644 atfexecute.py create mode 100644 atfinit.py create mode 100644 atfsetup.py create mode 100755 export.py create mode 100755 testruninfo.cfg diff --git a/SharedModules/Connect/ssh.py b/SharedModules/Connect/ssh.py new file mode 100755 index 0000000..a9952bb --- /dev/null +++ b/SharedModules/Connect/ssh.py @@ -0,0 +1,114 @@ +""" + sshConnection Class for connecting and performing operation on + remote server using SSH Protocol. +""" +import paramiko +import pdb +import time + +class SshConnection(): + + def __init__(self): + self._connection = None + self._connection = paramiko.SSHClient() + + def connect(self, host, user=None, password=None): + """ + Objective: + SSH to Server "host" as User "user" + + Parameter: + host: Server IP Address + user: Login Username + password: Login password + + Return: + Success: 0 + Failure: 1 + """ + self._connection.set_missing_host_key_policy(paramiko.AutoAddPolicy()) + + if user == None: + user = "root" + + if password == None: + password = "syst3m" + + try: + self._connection.connect(host, username=user, password=password) + + except paramiko.BadHostKeyException as result: + print( + "BadHostKeyException: Unable to Connect to Server: '" + host + + "' as User: '" + user + "'") + return 1 + + except paramiko.AuthenticationException: + print("AuthenticationException: Unable to Authenticate " + + user + "@" + host) + return 1 + + except paramiko.SSHException: + print("SSHException: Unknown server " + host) + return 1 + + return 0 + + def close(self): + """ + Objective: + Close SSH Connections + """ + self._connection.close() + return + + def executecommand(self, command, commandInput=None): + """ + Objective: + Execute Command "comamnd" + + Parameters: + command: command to execute + + Return: + Success: 0 + Failure: 1 + """ + output = {} + output["exitstatus"] = None + output["stdoutdata"] = None + output["stderrdata"] = None + exit_status_ready_flag = True + + try: + transport = self._connection.get_transport() + channel = transport.open_session() + channel.exec_command(command) + # Adding sleep to get the correct exit_status. + time.sleep(5) + exit_status_ready_flag = channel.exit_status_ready() + if not exit_status_ready_flag: + stdin = channel.makefile("wb") + + if commandInput: + stdin.write(commandInput) + else: + print "This command requirs Command Input \ + after executing comamnd for command completion" + stdin.write("\n") + return output + + stdout = channel.makefile("rb") + stderr = channel.makefile_stderr("rb") + exit_status = channel.recv_exit_status() + + output["exitstatus"] = exit_status + output["stdoutdata"] = stdout.readlines() + output["stderrdata"] = stderr.readlines() + + except paramiko.SSHException: + print("Unable to Execute Command: " + command) + + return output + + diff --git a/SharedModules/Globals/atfglobals.py b/SharedModules/Globals/atfglobals.py new file mode 100644 index 0000000..ff1faad --- /dev/null +++ b/SharedModules/Globals/atfglobals.py @@ -0,0 +1,85 @@ +"""atfglobals module contain AtfGlobal class and GlobalObj + +AtfGlobals class wrapps all global objects used in the framework +*) TestrunInfo +*) Logger +*) Testenv +*) ConnectionsManager + +GlobalObj is 'The Instance' of AtfGlobals which will be referred throughout +the framework utilities. +""" + +import testruninfo +import logger +import testenv +import manager + +class AtfGlobals: + + + def __init__(self): + self._testruninfo = None + self._logger = logger.Log() + self._env = None + self._connectionsmanager = manager.ConnectionsManager() + + def getTestrunInfoObj(self): + """Returns TestrunInfo Object + """ + return self._testruninfo + + def getLoggerObj(self): + """Returns Logger Object + """ + return self._logger + + def getTestenvObj(self): + """Returns Current TestEnvironment Object. + """ + return self._env + + def getConnectionsManagerObj(self): + """Returns ConnectionsManager Object + """ + return self._connectionsmanager + + def initTestrunInfoObj(self): + """Instantiation of TestrunInfo Object + """ + self._testruninfo = testruninfo.TestRunInfo() + + def initLoggerObj(self): + """Instantiation of Logger Object + """ + self._logger = logger.Log() + + def initTestenvObj(self): + """Instantiation of Testenv Object + """ + self._env = testenv.TestEnv() + + def initConnectionsManagerObj(self): + """Instantiation of ConnectionsManager Object + """ + self._connectionsmanager = manager.ConnectionsManager() + +GlobalObj = AtfGlobals() +__all__ = ['GlobalObj'] + + + + + + + + + + + + + + + + + diff --git a/SharedModules/Globals/logger.py b/SharedModules/Globals/logger.py new file mode 100644 index 0000000..9d11bd7 --- /dev/null +++ b/SharedModules/Globals/logger.py @@ -0,0 +1,211 @@ +""" + logger 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] + +""" +import logging + +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 getLogLevel(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 setSummaryLog(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.getLogLevel(loglevel) + + def setDetailLog(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.getLogLevel(loglevel) + + def setStdoutLog(self, do_log=True, loglevel='INFO'): + """ + Description: + Set Log Level for logging to STDOUT + + Parameters: + loglevel: Log level for logging to STDOUT + """ + self._stdoutlog['do_log'] = do_log + self._stdoutlog['loglevel'] = self.getLogLevel(loglevel) + + def createLogger(self, atfdir, logname='ATFLOG'): + """ + 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 + summarylog_abspath = atfdir + "/" + self._summarylog['filename'] + try: + summary_handler = logging.FileHandler(summarylog_abspath, mode='w') + + except IOError as (errno, errstr): + print "I/0 error({0}): {1}".format(errno, errstr) + return 1 + + else: + summary_formatter = logging.Formatter(self._summarylog['format']) + summary_handler.setFormatter(summary_formatter) + summary_handler.setLevel(self._summarylog['loglevel']) + 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['do_log'] == '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 + return 0 + + def addDetaillogHandler(self, abspath, 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 + abspath = abspath + 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") + + return 0 + + def removeDetaillogHandler(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/SharedModules/Globals/manager.py b/SharedModules/Globals/manager.py new file mode 100755 index 0000000..d73cf15 --- /dev/null +++ b/SharedModules/Globals/manager.py @@ -0,0 +1,64 @@ +""" manager module contains: + +*) ConnectionsManager Class +""" +class ConnectionsManager(): + """ + *) Manages Client SSH Connections in the current TestEnvironment + *) Manages Server SSH Connections in the current TestEnvironment + *) Manages allhosts SSH Connection in the current TestEnvironment + """ + def __init__(self): + + self._serverpool = {} + self._clientpool = {} + self._all = {} + + def addServer(self, key, server): + """ + Add a server to _serverpool + """ + + self._serverpool[key] = server + self._all[key] = server + return + + def addClient(self, key, client): + """ + Add a client to clientpool + """ + + self._clientpool[key] = client + self._all[key] = client + return + + def getServers(self): + """ + Return the server object + """ + + return self._serverpool + + def getClients(self): + """ + Return the client object + """ + + return self._clientpool + + def getConnection(self, key): + """ + """ + value = None + if self._all.has_key(key): + value = self._all[key] + return value + + def getConnections(self): + """ + """ + return self._all + + + + diff --git a/SharedModules/Globals/testenv.py b/SharedModules/Globals/testenv.py new file mode 100755 index 0000000..9aa8ec8 --- /dev/null +++ b/SharedModules/Globals/testenv.py @@ -0,0 +1,462 @@ +"""testenv module. + +TestEnv Class has attributes which holds information of the current +testenvironment. It includes information about Servers, Clients, Volume, +Bricks, MountPoints etc. +TestEnv Class provides methods to access the testenvironment info +""" + +from collections import namedtuple +import re + +class TestEnv(): + + def __init__(self): + self._exportdirs = {} + self._servers = {} + self._bricks = {} + self._volumes = {} + self._clients = {} + self._mountdevices = {} + self._mounts = {} + self._gluster_download_paths = [] + self._active_volume = None + + self._exportdir_tuple = namedtuple('ExportDir', + ['dir', 'fstype', 'device']) + + self._server_tuple = namedtuple('Server', + ['hostname', 'user', 'password', + 'glusterversion', 'installpath']) + + self._brick_tuple = namedtuple('Brick', + ['hostname', 'path']) + + self._volume_tuple = namedtuple('Volume', + ['volumename', 'volumetype', 'count', + 'transporttype', 'bricks']) + + self._client_tuple = namedtuple('Client', + ['hostname', 'user', 'password', + 'glusterversion', 'installpath']) + + self._mountdevice_tuple = namedtuple('MountDevice', + ['hostname', 'volumename']) + + self._mount_tuple = namedtuple('Mount', + ['client', 'dir', 'device', + 'type', 'logfile', 'options']) + + def addExportdir(self, key, dir_, **arguments): + """ + """ + fstype = device = None + if (arguments.has_key('fstype') and arguments['fstype']): + fstype = arguments['fstype'] + + if (arguments.has_key('device') and arguments['device']): + device = arguments['device'] + + exportdir_obj = self._exportdir_tuple(dir_, fstype, device) + self._exportdirs[key] = exportdir_obj + + def getExportdir(self, exportdirkey): + """ + """ + exportdir_obj = None + if self._exportdirs.has_key(exportdirkey): + exportdir_obj = self._exportdirs[exportdirkey] + + return exportdir_obj + + def getExportdirs(self): + """Returns self._exportdirs dictionary. + 'key' in dict is exportdirkey + 'value' is exportdir namedtuple object + """ + + return self._exportdirs + + def addServer(self, key, hostname, user, password, + glusterversion, **arguments): + """ + """ + installpath = None + if (arguments.has_key('installpath') and arguments['installpath']): + installpath = arguments['installpath'] + + server_obj = self._server_tuple(hostname, user, password, + glusterversion, installpath) + + self._servers[key] = server_obj + + def getServer(self, serverkey): + """ + """ + server_obj = None + if self._servers.has_key(serverkey): + server_obj = self._servers[serverkey] + + return server_obj + + def getServers(self): + """ + """ + servers = {} + + for serverkey in self._servers.keys(): + servers[serverkey] = self.getServer(serverkey) + + return servers + + def addClient(self, key, hostname, user, password, + glusterversion, **arguments): + """ + """ + installpath = None + if arguments.has_key('installpath') and arguments['installpath']: + installpath = arguments['installpath'] + + client_obj = self._client_tuple(hostname, user, password, + glusterversion, installpath) + self._clients[key] = client_obj + + def getClient(self, clientkey): + """ + """ + client_obj = None + if self._clients.has_key(clientkey): + client_obj = self._clients[clientkey] + + return client_obj + + def getClients(self): + """ + """ + clients = {} + + for clientkey in self._clients.keys(): + clients[clientkey] = self.getClient(clientkey) + + return clients + + def addBrick(self, key, hostname, path, **arguments): + """ + """ + brick_obj = self._brick_tuple(hostname, path) + self._bricks[key] = brick_obj + + def getBrick(self, brickkey): + """ + """ + return_brick_obj = None + newhostname = newpath = '' + + if self._bricks.has_key(brickkey): + brick_obj = self._bricks[brickkey] + else: + return return_brick_obj + + hostname_value = brick_obj.hostname + serverkey = re.split("\.", hostname_value, maxsplit=1)[0] + server_obj = self.getServer(serverkey) + if server_obj: + newhostname = server_obj.hostname + else: + return return_brick_obj + + path_value = brick_obj.path + if re.match("^\/", path_value): + path = path_value + else: + exportdir_obj = self.getExportdir(path_value) + if exportdir_obj: + newpath = exportdir_obj.dir + else: + brick_obj = None + return return_brick_obj + + return_brick_obj = brick_obj._replace(hostname=newhostname, + path=newpath) + + return return_brick_obj + + def getBricks(self): + """ + """ + return_bricks = {} + + for brickkey in self._bricks.keys(): + return_bricks[brickkey] = self.getBrick(brickkey) + + return return_bricks + + def getRawBrick(self, brickkey): + brick_obj = None + if self._bricks.has_key(brickkey): + brick_obj = self._bricks[brickkey] + return brick_obj + + def getBrickKeys(self): + """ + """ + brick_keys = [] + brick_keys.extend(self._bricks.keys()) + return brick_keys + + def addBricksToVolume(self, volumekey="ActiveVolume", *bricks): + """ + """ + volume_obj = None + if volumekey == "ActiveVolume": + volumekey = self._active_volume + + if not (volumekey and self._volumes.has_key(volumekey)): + return 1 + + volume_obj = self._volumes[volumekey] + + for brick in bricks: + volume_obj.bricks.append(brick) + + return 0 + + def replaceBrickInVolume(self, replace_brick, to_brick, + volumekey="ActiveVolume"): + """ + """ + volume_obj = None + replaced_status = False + if volumekey == "ActiveVolume": + volumekey = self._active_volume + + if not (volumekey and self._volumes.has_key(volumekey)): + return 1 + + volume_obj = self._volumes[volumekey] + for index, brick in enumerate(volume_obj.bricks): + if brick == replace_brick: + volume_obj.bricks[index] = to_brick + replaced_status = True + break + else: + continue + + if replaced_status: + return 0 + else: + return 1 + + def addVolume(self, key, volumename, volumetype, count, + transporttype, bricks): + """ + """ + brickskeylist = [x.strip() for x in bricks.split(",")] + volume_obj = self._volume_tuple(volumename, volumetype, + count, transporttype, brickskeylist) + self._volumes[key] = volume_obj + + def getVolume(self, volumekey): + """ + """ + return_volume_obj = None + + if not self._volumes.has_key(volumekey): + return return_volume_obj + + volume_obj = self._volumes[volumekey] + brickslist = [] + for brickkey in volume_obj.bricks: + brick_obj = self.getBrick(brickkey) + if not brick_obj: + return return_volume_obj + else: + brickslist.append(brick_obj) + + return_volume_obj = volume_obj._replace(bricks=brickslist) + + return return_volume_obj + + def getVolumes(self): + """ + """ + return_volumes = {} + for volumekey in self._volumes.keys(): + return_volumes[volumekey] = self.getVolume(volumekey) + + return return_volumes + + def addMountDevice(self, key, hostname, volumename): + """ + """ + mountdevice_obj = self._mountdevice_tuple(hostname, volumename) + self._mountdevices[key] = mountdevice_obj + + def getMountDevice(self, mountdevicekey): + """ + *) Check the hostname = IPAddress + *) Check hostname refers to any server + *) Check the volume is defined. + *) Substitute all values + """ + returndevice_obj = None + ip_pattern = re.compile('(?:[\d]{1,3})\.(?:[\d]{1,3})\.(?:[\d]{1,3})\.(?:[\d]{1,3})') + + if not self._mountdevices.has_key(mountdevicekey): + return returndevice_obj + + else: + mountdevice_obj = self._mountdevices[mountdevicekey] + + hostname_value = mountdevice_obj.hostname + if ip_pattern.match(hostname_value): + newhostname = hostname_value + elif re.match('(([a-z]|[A-Z])+[0-9]+)\.hostname', hostname_value): + serverkey = re.split("\.", hostname_value, maxsplit=1)[0] + server_obj = self.getServer(serverkey) + if server_obj: + newhostname = server_obj.hostname + else: + return returndevice_obj + else: + newhostname = hostname_value + volumekey = re.split("\.", mountdevice_obj.volumename, maxsplit=1)[0] + volume_obj = self.getVolume(volumekey) + if volume_obj: + newvolumename = volume_obj.volumename + else: + return returndevice_obj + + + returndevice_obj = mountdevice_obj._replace(hostname=newhostname, + volumename=newvolumename) + return returndevice_obj + + def getMountDevices(self): + """ + """ + return_mount_devices = {} + + for mountdevicekey in self._mountdevices.keys(): + return_mount_devices[mountdevicekey] = self.getMountDevice(mountdevicekey) + + return return_mount_devices + + def addMount(self, key, client, dir_, device, **arguments): + """ + """ + logfile = options = None + type_ = "glusterfs" + + if (arguments.has_key("type") and arguments['type']): + type_ = arguments['type'] + + if (arguments.has_key("logfile") and arguments['logfile']): + logfile = arguments['logfile'] + + if (arguments.has_key("options") and arguments['options']): + options = arguments['options'] + + mount_obj = self._mount_tuple(client, dir_, device, + type_, logfile, options) + self._mounts[key] = mount_obj + + def getMount(self, mountkey): + """ + """ + return_mount_obj = None + if not self._mounts.has_key(mountkey): + return return_mount_obj + + mount_obj = self._mounts[mountkey] + devicekey = mount_obj.device + device_obj = self.getMountDevice(devicekey) + if not device_obj: + return return_mount_obj + else: + return_mount_obj = mount_obj._replace(device=device_obj) + + return return_mount_obj + + def getMounts(self): + """ + """ + return_mounts = {} + + for mountkey in self._mounts.keys(): + return_mounts[mountkey] = self.getMount(mountkey) + + return return_mounts + + def getMountsKeys(self): + """ + """ + mounts_keys = [] + mounts_keys.extend(self._mounts.keys()) + return mounts_keys + + def addDefaults(self, **arguments): + """ + """ + downloadpaths = [] + + if (arguments.has_key('downloadpath') and arguments['downloadpath']): + paths = arguments['downloadpath'] + downloadpaths = [x.strip() for x in paths.split(",")] + + self._gluster_download_paths = downloadpaths + + def setActiveVolume(self, volumekey): + """ + """ + if self._volumes.has_key(volumekey): + self._active_volume = volumekey + return 0 + else: + return 1 + + def getActiveVolume(self): + """ + """ + active_volume_key = self._active_volume + active_volume = self.getVolume(active_volume_key) + return active_volume + + def getGlusterDownloadPaths(self): + """ + """ + return self._gluster_download_paths + + def getHosts(self): + """ + """ + all_hosts = {} + all_hosts.update(self.getServers) + all_hosts.update(self.getClients) + return all_hosts + + def getHostsKeys(self): + """ + """ + hosts_keys = [] + hosts_keys.extend(self._servers.keys()) + hosts_keys.extend(self._clients.keys()) + return hosts_keys + + def getHost(self, hostkey): + """ + """ + host_obj = None + host_obj = self.getServer(hostkey) + if host_obj: + return host_obj + else: + host_obj = self.getClient(hostkey) + return host_obj + + + + + + + diff --git a/SharedModules/Globals/testruninfo.py b/SharedModules/Globals/testruninfo.py new file mode 100644 index 0000000..9b012e8 --- /dev/null +++ b/SharedModules/Globals/testruninfo.py @@ -0,0 +1,144 @@ +"""testruninfo module + +TestRunInfo Class contains variables and methods for storing and retrieving +information about current "TestRun". +""" +import re + +class TestRunInfo(): + def __init__(self): + self._testunits = [] + self._keywords = '' + self._glusterversion = '' + self._atfdir = '' + self._summaryloginfo = {} + self._detailloginfo = {} + self._stdoutloginfo = {} + + def addGlusterVersion(self, version): + """ + """ + self._glusterversion = version + + def getGlusterVersion(self): + """ + """ + return self._glusterversion + + def addSummaryLogInfo(self, filename, loglevel): + """ + """ + if not filename: + filename = "SummaryLog.out" + + if not loglevel: + loglevel = "info" + + self._summaryloginfo['filename'] = filename + self._summaryloginfo['loglevel'] = loglevel + + def getSummaryLogInfo(self): + """ + """ + return self._summaryloginfo + + def addDetailLogInfo(self, filename, loglevel): + """ + """ + if not filename: + filename = "DetailLog.out" + + if not loglevel: + loglevel = "info" + + self._detailloginfo['filename'] = filename + self._detailloginfo['loglevel'] = loglevel + + def getDetailLogInfo(self): + """ + """ + return self._detailloginfo + + def addStdoutLogInfo(self, do_log, loglevel): + """ + """ + true_pattern = re.compile('True|Yes', re.IGNORECASE) + false_pattern = re.compile('False|No', re.IGNORECASE) + + if not loglevel: + loglevel = "info" + + if true_pattern.match(do_log): + do_log = True + + elif false_pattern.match(do_log): + do_log = False + + else: + do_log = True + + self._stdoutloginfo['do_log'] = do_log + self._stdoutloginfo['loglevel'] = loglevel + + def getStdoutLogInfo(self): + """ + """ + return self._stdoutloginfo + + def addAtfDir(self, atfdir): + """ + """ + self._atfdir = atfdir + + def getAtfDir(self): + """ + """ + return self._atfdir + + def addTestUnits(self, testunit): + """ + Description: + Add a testunit to TestUnits List + + Parameter: + testunit: Name of the Testing Unit + + Returns: + """ + + self._testunits.append(testunit) + return + + def getTestUnits(self): + """ + Description: + Return TestUnits List + + Parameters: + + Returns: + Success: Testunit Name + Failure: '' + """ + + return self._testunits + + def addKeywords(self, keywords): + """ + Description: + Add Keywords to KeyWords List + + Parameters: + keyname: Keyword + + Returns: + """ + self._keywords = keywords + + def getKeywords(self): + """ + """ + return self._keywords + + + diff --git a/SharedModules/Parser/parser.py b/SharedModules/Parser/parser.py new file mode 100644 index 0000000..ee3a2d1 --- /dev/null +++ b/SharedModules/Parser/parser.py @@ -0,0 +1,315 @@ +""" Parser module contains parsers for parsing: +*) TestrunInfo file +*) TestEnvironment file +*) Testcaselist file. +""" + +import ConfigParser +import re +from collections import OrderedDict +import os +from atfglobals import GlobalObj + + +def verify_necessary_options(cp, section, necessary_options): + """Helper function for all parsers to verify necessary options + in a section of the config file. + + Parameters: + cp : Config Parser Object + section: name of the section in ConfigFile + necessary_options: Options necessary under Section 'section' + + Returns: + Success: True (if all necessary_options are found in 'section') + Failure: False ( if any of the necessaty_options not found in 'section') + """ + all_options_found = True + items = dict(cp.items(section)) + for option in necessary_options: + if not (items.has_key(option) and items[option]): + print "' %s ' Should be defined in Section: %s" % (option, section) + all_options_found = False + return all_options_found + + +def parse_testrun_info_file(filename): + """ + Parse TestrunInfo File + """ + GlobalObj.initTestrunInfoObj() + testruninfo_obj = GlobalObj.getTestrunInfoObj() + cp = ConfigParser.SafeConfigParser() + necessary_sections = ["keywords", "testunits", "atfdir", + "summarylog","detaillog", "stdoutlog", + "glusterversion"] + matched_sections = [] + unmatched_sections = [] + + if not cp.read(filename): + print "Error reading file ' %s '.File Not found " % filename + return 1 + else: + available_sections = cp.sections() + found_all_sections = True + for section in necessary_sections: + matched_obj = re.search(section, str(available_sections), + re.IGNORECASE) + if not matched_obj: + found_all_sections = False + unmatched_sections.append(section) + else: + matched_sections.append(matched_obj.group(0)) + + if not found_all_sections: + for section in unmatched_sections: + print "Section %s Not Found" % section + print "Please define the above sections in TestRunInfo File" + return 1 + + else: + for section in matched_sections: + Map = {} + if re.match("keywords", section, re.IGNORECASE): + Map = dict(cp.items(section)) + testruninfo_obj.addKeywords(Map['keywords']) + + elif re.match("testunits", section, re.IGNORECASE): + Map = dict(cp.items(section)) + testunits = Map.values() + for testunit in testunits: + if testunit: + testruninfo_obj.addTestUnits(testunit) + + elif re.match("atfdir", section, re.IGNORECASE): + Map = dict(cp.items(section)) + atfdir = Map['dir'] + if not atfdir: + print "dir option not defined in ATFDir. " + \ + "The 'dir'option should be defined" + return 1 + else: + testruninfo_obj.addAtfDir(atfdir) + + elif re.match("summarylog", section, re.IGNORECASE): + Map = dict(cp.items(section)) + testruninfo_obj.addSummaryLogInfo(Map['filename'], + Map['loglevel']) + + elif re.match("detaillog", section, re.IGNORECASE): + Map = dict(cp.items(section)) + testruninfo_obj.addDetailLogInfo(Map['filename'], + Map['loglevel']) + + elif re.match("stdoutlog", section, re.IGNORECASE): + Map = dict(cp.items(section)) + testruninfo_obj.addStdoutLogInfo(Map['do_log'], + Map['loglevel']) + + elif re.match("glusterversion", section, re.IGNORECASE): + Map = dict(cp.items(section)) + glusterversion = Map['version'] + if not glusterversion: + print "version option not defined in GlusterVersion. " + \ + "The 'version' option should be defined" + return 1 + else: + testruninfo_obj.addGlusterVersion(glusterversion) + + return 0 + +def parse_testcaseslist_file(filename): + """ + Parse TestCasesList file + """ + return_status = 1 + testcaseslist = [] + if not os.path.exists(filename): + print "%s file not found." % filename + return return_status + + testruninfo_obj = GlobalObj.getTestrunInfoObj() + glusterversion = testruninfo_obj.getGlusterVersion() + + testcaseslistfile = open(filename, "r") + filedata = testcaseslistfile.readlines() + + testcaseslist = [] + for data in filedata: + if (not data.strip() or re.match("^#", data)): + continue + + else: + testcaseid, version, keyword = (value.strip() for value in + data.split(':')) + testcaseslist.append({'testcaseid':testcaseid, 'version':version, + 'keyword':keyword}) + + selected_testcases = [] + if glusterversion == "master": + for testcase in testcaseslist: + selected_testcases.append(testcase['testcaseid']) + return selected_testcases + else: + for testcase in testcaseslist: + if re.match("^(<|>|=|<=|>=)", testcase['version']): + condition, version = (x.strip() for x in + testcase['version'].split()) + + if ((condition == "<=" and glusterversion <= version) or + (condition == ">=" and glusterversion >= version) or + (condition == "<" and glusterversion < version) or + (condition == ">" and glusterversion > version) or + (condition == "=" and glusterversion == version)): + selected_testcases.append(testcase['testcaseid']) + + elif re.search("-", testcaseid['version']): + fromversion, toversion = (x.strip() for x in + testcaseid['version'].split("-")) + if (glusterversion >= fromversion and + glusterversion <= toversion): + selected_testcases.append(testcase['testcaseid']) + + return selected_testcases + + +def parse_testenv_configfile(filename): + """ + parse testenv.cfg file + """ + GlobalObj.initTestenvObj() + env = GlobalObj.getTestenvObj() + cp = ConfigParser.SafeConfigParser(dict_type=OrderedDict) + sections_to_functions_mapping = { + "export" : "addExportdir", + "server" : "addServer", + "brick" : "addBrick", + "volume" : "addVolume", + "client" : "addClient", + "mountdevice" : "addMountDevice", + "mount" : "addMount", + "defaults" : "addDefaults"} + section_pattern = re.compile('(export|server|brick|volume|client|mountdevice|mount)*') + if not cp.read(filename): + print "Error reading file ' %s '.File Not found " % filename + return 1 + else: + defaults = dict(cp.defaults()) + function = getattr(env, "addDefaults") + function(**defaults) + sections = cp.sections() + for section in sections: + items = dict(cp.items(section)) + matched_obj = section_pattern.match((section.lower())) + result = matched_obj.group(0) + if result is '': + continue + else: + funcname = sections_to_functions_mapping[result] + function = getattr(env, funcname) + necessary_options = [] + + if re.match('export', result): + necessary_options = ["dir"] + if verify_necessary_options(cp, section, necessary_options): + dir_ = items.pop('dir') + function(section, dir_, **items) + else: + return 1 + + elif re.match('server', result): + necessary_options = ["hostname", "user", "password", + "glusterversion"] + if verify_necessary_options(cp, section, necessary_options): + hostname = items.pop('hostname') + user = items.pop('user') + password = items.pop('password') + glusterversion = items.pop('glusterversion') + function(section, hostname, user, password, + glusterversion, **items) + else: + return 1 + + elif re.match('client', result): + necessary_options = ["hostname", "user", "password", + "glusterversion"] + if verify_necessary_options(cp, section, necessary_options): + hostname = items.pop('hostname') + user = items.pop('user') + password = items.pop('password') + glusterversion = items.pop('glusterversion') + function(section, hostname, user, password, + glusterversion, **items) + else: + return 1 + + elif re.match('brick', result): + necessary_options = ["hostname", "path"] + if verify_necessary_options(cp, section, necessary_options): + hostname = items.pop('hostname') + path = items.pop('path') + function(section, hostname, path, **items) + else: + return 1 + + elif re.match('volume', result): + necessary_options = ["volumename", "volumetype", + "count", "transporttype", + "bricks"] + if verify_necessary_options(cp, section, necessary_options): + volumename = items.pop('volumename') + volumetype = items.pop('volumetype') + count = items.pop('count') + transporttype = items.pop('transporttype') + bricks = items.pop('bricks') + function(section, volumename, volumetype, + count, transporttype, bricks) + else: + return 1 + + elif re.match('mountdevice', result): + necessary_options = ["hostname", "volumename"] + if verify_necessary_options(cp, section, necessary_options): + hostname = items.pop('hostname') + volumename = items.pop('volumename') + function(section, hostname, volumename) + + elif re.match('mount', result): + necessary_options = ["client", "dir", "device"] + if verify_necessary_options(cp, section, necessary_options): + client = items.pop('client') + dir_ = items.pop('dir') + device = items.pop('device') + function(section, client, dir_, device, **items) + + else: + return 1 + return 0 + + +__all__ = ['parse_testrun_info_file', + 'parse_testcaseslist_file', + 'parse_testenv_configfile'] + + + + + + + + + + + + + + + + + + + + + + + diff --git a/SharedModules/Utils/atfutils.py b/SharedModules/Utils/atfutils.py new file mode 100644 index 0000000..980c286 --- /dev/null +++ b/SharedModules/Utils/atfutils.py @@ -0,0 +1,58 @@ +"""atfutils module contains general purpose wrappers + +*) assert_success +*) assert_failure +*) print-stdout +*) print_stderr +*) set_active_volume +""" + +import re +import ssh +from atfglobals import GlobalObj + +def assert_success(**arguments): + """ + """ + if not arguments["exitstatus"]: + return 0 + else: + return 1 + +def assert_failure(**arguments): + """ + """ + if arguments["exitstatus"]: + return 0 + else: + return 1 + +def print_stdout(stdoutdata): + """ + """ + if not stdoutdata == None: + for data in stdoutdata: + print data + +def print_stderr(stderrdata): + if not stderrdata == None: + for data in stderrdata: + print data + +def set_active_volume(volumekey): + """ + """ + env = GlobalObj.getTestenvObj() + return_status = env.setActiveVolume(volumekey) + if return_status: + print "Unable to set Active Volume. '%s' Not defined in TestEnvironment"\ + % volumekey + return return_status + + + +__all__ = ['assert_success', + 'assert_failure', + 'print-stdout', + 'print_stderr', + 'set_active_volume'] diff --git a/SharedModules/Utils/clientutils.py b/SharedModules/Utils/clientutils.py new file mode 100644 index 0000000..ad5d593 --- /dev/null +++ b/SharedModules/Utils/clientutils.py @@ -0,0 +1,282 @@ +"""clientutils module contains functions required for performing +certain operations on client + +Supported Wrappers :- +----------- +*) umount +*) umountall +*) mount +*) mountall +""" + +import atfutils +import hostutils +from atfglobals import GlobalObj + +def umount(mountkey): + """unmounts a mountpoint + + Parameters: + mountkey : name given to a mount as specified in testenv.cfg file. + Ex:-"mount1" + + Returns: + Success : 0 + Failure : 1` + """ + base_command = "umount " + env = GlobalObj.getTestenvObj() + cm = GlobalObj.getConnectionsManagerObj() + + mount_obj = env.getMount(mountkey) + if not mount_obj: + print "InValid Mount. %s not defined in TestEnvironment" % mountkey + return 1 + + clientkey = mount_obj.client + client_connection = cm.getConnection(clientkey) + if not client_connection: + print "SSH connection to host '%s' has not been established" % clientkey + return 1 + + command = base_command + mount_obj.dir + print "%s : %s" % (clientkey, command) + output = client_connection.executecommand(command) + return_status = atfutils.assert_success(**output) + atfutils.print_stdout(output['stdoutdata']) + atfutils.print_stderr(output['stderrdata']) + if return_status: + stdoutdata = str(output["stdoutdata"]) + if ((stdoutdata.rfind("not found")) or (stdoutdata.rfind("not mount"))): + return_status = 0 + + else: + print "Unable to umount %s" % mountkey + + return return_status + +def umountall(): + """unmounts all mount specified in testenv.cfg file. + Ex:- mount1, mount2 etc + + Parameters: + None + + Returns: + Success : 0 + Failure : 1` + """ + env = GlobalObj.getTestenvObj() + failure_flag = False + + mounts_keys = env.getMountsKeys() + for mountkey in mounts_keys: + return_status = umount(mountkey) + if return_status: + failure_flag = True + + if failure_flag: + return 1 + else: + return 0 + +def mount(mountkey): + """mounts a filesystem + + Parameters: + mountkey : name given to a mount as specified in testenv.cfg file. + Ex:-"mount1" + + Returns: + Success : 0 + Failure : 1` + """ + + base_command = command = "mount " + env = GlobalObj.getTestenvObj() + cm = GlobalObj.getConnectionsManagerObj() + + mount_obj = env.getMount(mountkey) + if not mount_obj: + print "InValid Mount. %s not defined in TestEnvironment" % mountkey + return 1 + + clientkey = mount_obj.client + client_connection = cm.getConnection(clientkey) + if not client_connection: + print "SSH connection to host '%s' has not been established" % clientkey + return 1 + + mountdevice_obj = mount_obj.device + device = mountdevice_obj.hostname + ":/" + mountdevice_obj.volumename + options = ["-t", mount_obj.type] + if mount_obj.logfile: + options.extend(["-o", ("log-file="+mount_obj.logfile), + "log-level=INFO"]) + + if mount_obj.options: + options.extend([mount_obj.option]) + + options.extend([device, mount_obj.dir]) + for index, option in enumerate(options): + command = command + option + " " + + return_status = hostutils.mkdir(clientkey, mount_obj.dir) + if return_status: + return return_status + + print "%s : %s" % (clientkey, command) + output = client_connection.executecommand(command) + return_status = atfutils.assert_success(**output) + atfutils.print_stdout(output['stdoutdata']) + atfutils.print_stderr(output['stderrdata']) + return return_status + +def mountall(): + """mounts a filesystem for all mounts specified in testenv.cfg file. + + Parameters: + None + + Returns: + Success : 0 + Failure : 1` + """ + env = GlobalObj.getTestenvObj() + + mounts_keys = env.getMountsKeys() + for mountkey in mounts_keys: + return_status = mount(mountkey) + if return_status: + return return_status + + return 0 + + +def execute_on_mount(mountkey, command, commandInput=None): + """ + """ + env = GlobalObj.getTestenvObj() + mount_obj = env.getMount(mountkey) + if not mount_obj: + print "InValid Mount. %s not defined in TestEnvironment" % mountkey + return 1 + + clientkey = mount_obj.client + mountdir = mount_obj.dir + command = "cd " + mountdir + " ;" + command + return_status = hostutils.execute_command(clientkey, command, commandInput) + return return_status + +__all__ = ['execute_on_mount', + 'umount', + 'umountall', + 'mount', + 'mountall'] + +##def umountall(clientkey): +## """ +## """ +## base_command = "umount " +## env = GlobalObj.get_testenv_obj() +## cm = GlobalObj.get_connectionsmanager_obj() +## client_obj = env.getclient(clientkey) +## mountdir = client_obj.mountdir +## volume = client_obj.device +## client = cm.getconnection(clientkey) +## +## mountpoints = [] +## success_flag = False +## failure_flag = False +## command = "mount | grep " + mountdir +## output = client.executecommand(command) +## if not output["exitstatus"]: +## for data in output["stdoutdata"]: +## mountpoints.append(data.split(" ")[2]) +## +## for mountpoint in mountpoints: +## command = base_command + mountpoint +## output = client.executecommand(command) +## return_code = utils.assert_success(**output) +## if return_code: +## failure_flag = True +## else: +## success_flag = True +## continue +## +## if failure_flag: +## return 1 +## +## mountpoints = [] +## success_flag = False +## failure_flag = False +## command = "mount | grep " + volume +## output = client.executecommand(command) +## if not output["exitstatus"]: +## for data in output["stdoutdata"]: +## mountpoints.append(data.split(" ")[2]) +## +## for mountpoint in mountpoints: +## command = base_command + mountpoint +## output = client.executecommand(command) +## return_code = utils.assert_success(**output) +## if return_code: +## failure_flag = True +## else: +## success_flag = True +## continue +## +## if failure_flag: +## return 1 +## +## return 0 + +##def cd_mount(mountkey): +## """ +## """ +## env = GlobalObj.getTestenvObj() +## mount_obj = env.getMount(mountkey) +## if not mount_obj: +## print "InValid Mount. %s not defined in TestEnvironment" % mountkey +## return 1 +## +## clientkey = mount_obj.client +## dirpath = mount_obj.dir +## return_status = hostutils.cd(clientkey, dirpath) +## return return_status +## +##def cd_allmounts(): +## """ +## """ +## env = GlobalObj.getTestenvObj() +## mounts_keys = env.getMountsKeys() +## for mountkey in mounts_keys: +## return_status = cd_mount(mountkey) +## if return_status: +## return return_status +## +## return 0 + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/SharedModules/Utils/glusterutils.py b/SharedModules/Utils/glusterutils.py new file mode 100644 index 0000000..0c15af1 --- /dev/null +++ b/SharedModules/Utils/glusterutils.py @@ -0,0 +1,644 @@ +"""glusterutils module contains wrappers for gluster commands. + +*) glusterd_start +*) glusterd_start_allservers +*) glusterd_stop +*) glusterd_stop_allservers +*) glusterd_restart +*) glusterd_remove_dir +*) glusterd_remove_dir_allservers +*) glusterd_remove_logs_allservers +*) volume_delete +*) volume_create +*) volume_start +*) volume_stop +*) volume_addbrick +*) volume_replacebrick +*) volume_set +*) volume_reset +*) peer_probe +*) create_brick +*) mount_exportdir +*) umount_exportdir +""" + +import re +import atfutils +import hostutils +from atfglobals import GlobalObj + + +def glusterd_start(serverkey, force=False): + """ + """ + env = GlobalObj.getTestenvObj() + cm = GlobalObj.getConnectionsManagerObj() + commands_to_execute = ["which glusterd", "ps -e | grep glusterd"] + gluster_version = env.getServer(serverkey).glusterversion + host_connection = cm.getConnection(serverkey) + if not host_connection: + print "SSH connection to host '%s' has not been established" % serverkey + return 1 + + """ Check if gluster is already running. If already Running and force=True, + restart glusterd process""" + command = commands_to_execute.pop() + output = host_connection.executecommand(command) + return_status = atfutils.assert_success(**output) + if not return_status: + if force: + return_status = glusterd_restart(serverkey) + return return_status + else: + return return_status + + command = commands_to_execute.pop() + output = host_connection.executecommand(command) + if output["exitstatus"]: + print "Unable to start glusterd" + return_status = atfutils.assert_success(**output) + return return_status + else: + if output["stdoutdata"]: + gluster_path = None + gluster_path = output["stdoutdata"][0].strip("\n") + else: + print "Unable to find gluster path" + return_status = atfutils.assert_success(**output) + return return_status + + if gluster_path: + command = gluster_path + " --version" + output = host_connection.executecommand(command) + if not output["stdoutdata"] == None: + if re.search(gluster_version, str(output["stdoutdata"])): + print "%s : %s" % (serverkey, gluster_path) + output = host_connection.executecommand(gluster_path) + return_status = atfutils.assert_success(**output) + atfutils.print_stdout(output['stdoutdata']) + atfutils.print_stderr(output['stderrdata']) + return return_status + else: + print "Unable to start glusterd" + return 1 + else: + print "Unable to start glusterd" + return 1 + +def glusterd_start_allservers(force=False): + """ + """ + env = GlobalObj.getTestenvObj() + all_servers = env.getServers() + for serverkey in all_servers.keys(): + return_status = glusterd_start(serverkey) + if return_status: + return return_status + + return 0 + +def glusterd_stop(serverkey): + """ + """ + base_command = "kill -KILL " + env = GlobalObj.getTestenvObj() + cm = GlobalObj.getConnectionsManagerObj() + host_connection = cm.getConnection(serverkey) + if not host_connection: + print "SSH connection to host '%s' has not been established" % serverkey + return 1 + + gluster_pid_list = [] + output = host_connection.executecommand("pidof glusterd") + return_status = atfutils.assert_failure(**output) + if not return_status: + return return_status + + else: + if output["stdoutdata"]: + for output in output["stdoutdata"]: + gluster_pid_list.append(output) + + for pid in gluster_pid_list: + command = base_command + pid + print "%s : %s" % (serverkey, command) + output = host_connection.executecommand(command) + return_status = atfutils.assert_success(**output) + atfutils.print_stdout(output['stdoutdata']) + atfutils.print_stderr(output['stderrdata']) + if return_status: + break + + return return_status + +def glusterd_stop_allservers(): + """ + """ + env = GlobalObj.getTestenvObj() + all_servers = env.getServers() + for serverkey in all_servers.keys(): + return_status = glusterd_stop(serverkey) + if return_status: + return return_status + + return 0 + +def glusterd_restart(serverkey): + """ + """ + return_status = glusterd_stop(serverkey) + if return_status: + return return_status + else: + return_status = glusterd_start(serverkey) + return return_status + +def glusterd_remove_dir(serverkey): + """ + """ + command = "rm -rf /etc/glusterd/*" + env = GlobalObj.getTestenvObj() + cm = GlobalObj.getConnectionsManagerObj() + + server_obj = env.getServer(serverkey) + if not server_obj: + print "Invalid Host. %s not defined in TestEnvironment" % serverkey + return 1 + + server_connection = cm.getConnection(serverkey) + if not server_connection: + print "SSH connection to host '%s' has not been established" % serverkey + return 1 + + print "%s : %s" % (serverkey, command) + output = server_connection.executecommand(command) + return_status = atfutils.assert_success(**output) + atfutils.print_stdout(output['stdoutdata']) + atfutils.print_stderr(output['stderrdata']) + return 0 + +def glusterd_remove_dir_allservers(): + """ + """ + env = GlobalObj.getTestenvObj() + all_servers = env.getServers() + for serverkey in all_servers.keys(): + return_status = glusterd_remove_dir(serverkey) + + return 0 + + +def glusterd_remove_logs(serverkey): + """ + """ + base_command = "rm -rf " + log_paths = ["/var/log/glusterfs/*.log", "/var/log/glusterfs/bricks/*"] + absolute_path_list = [] + prefix_path = '' + env = GlobalObj.getTestenvObj() + cm = GlobalObj.getConnectionsManagerObj() + + server_obj = env.getServer(serverkey) + if not server_obj: + print "Invalid Host. %s not defined in TestEnvironment" % serverkey + return 1 + + server_connection = cm.getConnection(serverkey) + if not server_connection: + print "SSH connection to host '%s' has not been established" % serverkey + return 1 + + if server_obj.installpath: + prefix_path = server_obj.installpath + + for path in log_paths: + absolute_path_list.append(prefix_path + path) + + for path in absolute_path_list: + command = base_command + path + print "%s : %s" % (serverkey, command) + output = server_connection.executecommand(command) + return_status = atfutils.assert_success(**output) + atfutils.print_stdout(output['stdoutdata']) + atfutils.print_stderr(output['stderrdata']) + + return 0 + +def glusterd_remove_logs_allservers(): + """ + """ + env = GlobalObj.getTestenvObj() + all_servers = env.getServers() + for serverkey in all_servers.keys(): + return_status = glusterd_remove_logs(serverkey) + + return 0 + +def volume_delete(serverkey): + """ + """ + base_command = "gluster volume delete " + env = GlobalObj.getTestenvObj() + cm = GlobalObj.getConnectionsManagerObj() + active_volume = env.getActiveVolume() + if not active_volume: + print "Invalid Volume.ActiveVolume not defined for the TestEnvironment" + return 1 + volumename = active_volume.volumename + command = base_command + volumename + host_connection = cm.getConnection(serverkey) + if not host_connection: + print "SSH connection to host '%s' has not been established" % serverkey + return 1 + + print "%s : %s" % (serverkey, command) + output = host_connection.executecommand(command, commandInput="y\n") + return_status = atfutils.assert_success(**output) + atfutils.print_stdout(output['stdoutdata']) + atfutils.print_stderr(output['stderrdata']) + return return_status + +def volume_create(serverkey): + """ + """ + base_command = "gluster volume create " + env = GlobalObj.getTestenvObj() + cm = GlobalObj.getConnectionsManagerObj() + active_volume = env.getActiveVolume() + if not active_volume: + print "ActiveVolume not defined for the TestEnvironment" + return 1 + + command = base_command + \ + active_volume.volumename + " " + \ + active_volume.volumetype + " " + \ + active_volume.count + " " + \ + "transport " + active_volume.transporttype + " " + + for brick_obj in active_volume.bricks: + brick_value = brick_obj.hostname + ":" + brick_obj.path + command = command + brick_value + " " + + host_connection = cm.getConnection(serverkey) + if not host_connection: + print "SSH connection to host '%s' has not been established" % serverkey + return 1 + + print "%s : %s" % (serverkey, command) + output = host_connection.executecommand(command, commandInput="y\n") + return_status = atfutils.assert_success(**output) + if return_status: + if str(output["stdoutdata"]).rfind("already exists"): + return_status = 0 + atfutils.print_stdout(output['stdoutdata']) + atfutils.print_stderr(output['stderrdata']) + return return_status + +def volume_start(serverkey, force=False): + """ + """ + base_command = "gluster volume start " + env = GlobalObj.getTestenvObj() + cm = GlobalObj.getConnectionsManagerObj() + active_volume = env.getActiveVolume() + if not active_volume: + print "ActiveVolume not defined for the TestEnvironment" + return 1 + volumename = active_volume.volumename + command = base_command + volumename + if force: + command = command + " force" + + host_connection = cm.getConnection(serverkey) + if not host_connection: + print "SSH connection to host '%s' has not been established" % serverkey + return 1 + + print "%s : %s" % (serverkey, command) + output = host_connection.executecommand(command, commandInput="y\n") + return_status = atfutils.assert_success(**output) + if return_status: + if str(output["stdoutdata"]).rfind("already started"): + return_status = 0 + atfutils.print_stdout(output['stdoutdata']) + atfutils.print_stderr(output['stderrdata']) + return return_status + +def volume_stop(serverkey, force=False): + """ + """ + base_command = "gluster volume stop " + env = GlobalObj.getTestenvObj() + cm = GlobalObj.getConnectionsManagerObj() + active_volume = env.getActiveVolume() + if not active_volume: + print "ActiveVolume not defined for the TestEnvironment" + return 1 + volumename = active_volume.volumename + command = base_command + volumename + if force: + command = command + " force" + + host_connection = cm.getConnection(serverkey) + if not host_connection: + print "SSH connection to host '%s' has not been established" % serverkey + return 1 + + print "%s : %s" % (serverkey, command) + output = host_connection.executecommand(command, commandInput="y\n") + return_status = atfutils.assert_success(**output) + atfutils.print_stdout(output['stdoutdata']) + atfutils.print_stderr(output['stderrdata']) + return return_status + +def volume_addbrick(serverkey, *bricks): + """ + """ + base_command = "gluster volume add-brick " + env = GlobalObj.getTestenvObj() + cm = GlobalObj.getConnectionsManagerObj() + active_volume = env.getActiveVolume() + if not active_volume: + print "ActiveVolume not defined for the TestEnvironment" + return 1 + volumename = active_volume.volumenameGlobalObj.getConnectionsManagerObj() + command = base_command + volumename + " " + for brick in bricks: + brick_obj = env.getBrick(brick) + if not brick_obj: + print "Invalid Brick. Brick Not defined in TestEnvironment" + return 1 + brick_value = brick_obj.hostname + ":" + brick_obj.path + command = command + brick_value + + host_connection = cm.getConnection(serverkey) + if not host_connection: + print "SSH connection to host '%s' has not been established" % serverkey + return 1 + + print "%s : %s" % (serverkey, command) + output = host_connection.executecommand(command, commandInput="y\n") + return_status = atfutils.assert_success(**output) + if not return_status: + if env.addBricksToVolume(*bricks): + return 1 + atfutils.print_stdout(output['stdoutdata']) + atfutils.print_stderr(output['stderrdata']) + return return_status + +def volume_replacebrick(serverkey, replacebrick_key, tobrick_key): + """ + """ + base_command = "gluster volume replace-brick " + env = GlobalObj.getTestenvObj() + cm = GlobalObj.getConnectionsManagerObj() + active_volume = env.getActiveVolume() + if not active_volume: + print "ActiveVolume not defined for the TestEnvironment" + return 1 + volumename = active_volume.volumename + command = base_command + volumename + " " + replace_brick = env.getbrick(replacebrick_key) + to_brick = env.getbrick(tobrick_key) + command = command + replace_brick + " " + to_brick + + host_connection = cm.getConnection(serverkey) + if not host_connection: + print "SSH connection to host '%s' has not been established" % serverkey + return 1 + + print "%s : %s" % (serverkey, command) + output = host_connection.executecommand(command, commandInput="y\n") + return_status = atfutils.assert_success(**output) + if not return_status: + if env.replaceBrickInVolume(replacebrick_key, tobrick_key): + return 1 + atfutils.print_stdout(output['stdoutdata']) + atfutils.print_stderr(output['stderrdata']) + return return_status + +def volume_set(serverkey, key, value): + """ + """ + base_command = "gluster volume set " + env = GlobalObj.getTestenvObj() + cm = GlobalObj.getConnectionsManagerObj() + active_volume = env.getActiveVolume() + if not active_volume: + print "ActiveVolume not defined for the TestEnvironment" + return 1 + volumename = active_volume.volumename + command = base_command + volumename + " " + key + " " + value + host_connection = cm.getConnection(serverkey) + if not host_connection: + print "SSH connection to host '%s' has not been established" % serverkey + return 1 + + print "%s : %s" % (serverkey, command) + output = host_connection.executecommand(command, commandInput="y\n") + return_status = atfutils.assert_success(**output) + atfutils.print_stdout(output['stdoutdata']) + atfutils.print_stderr(output['stderrdata']) + return return_status + +def volume_reset(serverkey): + """ + """ + base_command = "gluster volume reset " + env = GlobalObj.getTestenvObj() + cm = GlobalObj.getConnectionsManagerObj() + active_volume = env.getActiveVolume() + if not active_volume: + print "ActiveVolume not defined for the TestEnvironment" + return 1 + volumename = active_volume.volumename + command = base_command + volumename + host_connection = cm.getConnection(serverkey) + if not host_connection: + print "SSH connection to host '%s' has not been established" % serverkey + return 1 + + print "%s : %s" % (serverkey, command) + output = host_connection.executecommand(command, commandInput="y\n") + return_status = atfutils.assert_success(**output) + atfutils.print_stdout(output['stdoutdata']) + atfutils.print_stderr(output['stderrdata']) + return return_status + +def peer_probe(fromserverkey): + """ + """ + base_command = "gluster peer probe " + command = base_command + all_servers = {} + env = GlobalObj.getTestenvObj() + cm = GlobalObj.getConnectionsManagerObj() + all_servers = env.getServers() + all_servers.pop(fromserverkey) + + for key in all_servers.keys(): + if key is fromserverkey: + continue + else: + server_obj = all_servers[key] + command = command + server_obj.hostname + " " + + host_connection = cm.getConnection(fromserverkey) + if not host_connection: + print "SSH connection to host '%s' has not been established" % serverkey + return 1 + + print "%s : %s" % (fromserverkey, command) + output = host_connection.executecommand(command) + return_status = atfutils.assert_success(**output) + atfutils.print_stdout(output['stdoutdata']) + atfutils.print_stderr(output['stderrdata']) + return return_status + +def create_brick(brickkey): + """ + """ + return_status = 1 + env = GlobalObj.getTestenvObj() + brick_obj = env.getRawBrick(brickkey) + + hostname_value = brick_obj.hostname + serverkey = re.split("\.", hostname_value, maxsplit=1)[0] + + exportdir = brick_obj.path + device = fstype = None + """If the exportdir is not a mount point of a device: + 1) Remove the existing exportdir + 2) Create new exportdir""" + + if re.match("^\/", exportdir): + dirpath = exportdir + command = base_command + dirpath + else: + export_obj = env.getExportdir(exportdir) + dirpath = export_obj.dir + device = export_obj.device + fstype = export_obj.fstype + + print "%s : %s" % (serverkey, 'create_brick') + if device: + if umount_device(serverkey, device): + return return_status + if hostutils.mkfs(serverkey, device, fstype): + return return_status + if mount_exportdir(serverkey, device, fstype, dirpath): + return return_status + return 0 + + else: + if hostutils.rmdir(serverkey, dirpath): + return return_status + if hostutils.mkdir(serverkey, dirpath): + return return_status + + return 0 + +def umount_device(serverkey, device): + """ + """ + base_command = "umount " + cm = GlobalObj.getConnectionsManagerObj() + + server_connection = cm.getConnection(serverkey) + if not server_connection: + print "SSH connection to host '%s' has not been established" % serverkey + return 1 + + mountpoints = hostutils.find_mountpoints(serverkey, device) + + for mountpoint in mountpoints: + command = base_command + mountpoint + print "%s : %s" % (serverkey, command) + output = server_connection.executecommand(command) + return_status = atfutils.assert_success(**output) + atfutils.print_stdout(output['stdoutdata']) + atfutils.print_stderr(output['stderrdata']) + if return_status: + stdoutdata = str(output["stdoutdata"]) + if ((stdoutdata.rfind("not found")) or (stdoutdata.rfind("not mount"))): + return_status = 0 + + else: + return return_status + + return 0 + +def mount_exportdir(serverkey, device, fstype, dirpath): + """ + """ + base_command = "mount " + cm = GlobalObj.getConnectionsManagerObj() + + server_connection = cm.getConnection(serverkey) + if not server_connection: + print "SSH connection to host '%s' has not been established" % serverkey + return 1 + + if fstype is None: + fstype = "xfs" + + command = base_command + "-t " + fstype + " " + device + " " + dirpath + + print "%s : %s" % (serverkey, command) + output = server_connection.executecommand(command) + return_status = atfutils.assert_success(**output) + atfutils.print_stdout(output['stdoutdata']) + atfutils.print_stderr(output['stderrdata']) + return return_status + +def create_brick_allservers(): + """ + """ + env = GlobalObj.getTestenvObj() + brick_keys = env.getBrickKeys() + for brickkey in brick_keys: + return_status = create_brick(brickkey) + if return_status: + return return_status + + return 0 + + +__all__ = ['glusterd_start', + 'glusterd_start_allservers', + 'glusterd_stop', + 'glusterd_stop_allservers', + 'glusterd_restart', + 'glusterd_remove_dir', + 'glusterd_remove_dir_allservers', + 'glusterd_remove_logs_allservers', + 'volume_delete', + 'volume_create', + 'volume_start', + 'volume_stop', + 'volume_addbrick', + 'volume_replacebrick', + 'volume_set', + 'volume_reset', + 'peer_probe', + 'create_brick', + 'create_brick_allservers', + 'mount_exportdir', + 'umount_device'] + + + + + + + + + + + + + + + + + diff --git a/SharedModules/Utils/hostutils.py b/SharedModules/Utils/hostutils.py new file mode 100644 index 0000000..68bb1bf --- /dev/null +++ b/SharedModules/Utils/hostutils.py @@ -0,0 +1,193 @@ +"""hostutils module contains wrappers for commands that can be executed on any +host in the test environment + +Supported Wrappers: +------------------- +*) rmdir +*) mkdir +*) mkfs +*) execute_command +""" + +import re +import atfutils +from atfglobals import GlobalObj + +def cd(hostkey, dirpath): + """ + """ + base_command = "cd " + cm = GlobalObj.getConnectionsManagerObj() + host_connection = cm.getConnection(hostkey) + if not host_connection: + print "SSH Connection Not established to host '%s' " % hostkey + return 1 + command = base_command + dirpath + print "%s : %s" % (hostkey, command) + output = host_connection.executecommand(command) + return_status = atfutils.assert_success(**output) + atfutils.print_stdout(output['stdoutdata']) + atfutils.print_stderr(output['stderrdata']) + return return_status + +def rmdir(hostkey, dirpath): + """ + """ + base_command = "rm -rf " + cm = GlobalObj.getConnectionsManagerObj() + system_dirs = re.compile('(/bin|/boot|/dev|/etc|/lib|/mnt|/net|/opt|/root|/sbin|/usr|/var|/sys)\/?$') + if system_dirs.match(dirpath): + print "System Directiories cannot be deleted" + return 1 + + else: + host_connection = cm.getConnection(hostkey) + if not host_connection: + print "SSH Connection Not established to host '%s' " % hostkey + return 1 + command = base_command + dirpath + print "%s : %s" % (hostkey, command) + output = host_connection.executecommand(command) + return_status = atfutils.assert_success(**output) + atfutils.print_stdout(output['stdoutdata']) + atfutils.print_stderr(output['stderrdata']) + return return_status + +def mkdir(hostkey, dirpath): + """ + """ + base_command = "mkdir -p " + cm = GlobalObj.getConnectionsManagerObj() + system_dirs = re.compile('(/bin|/boot|/dev|/etc|/lib|/mnt|/net|/opt|/root|/sbin|/usr|/var|/sys)\/?$') + if system_dirs.match(dirpath): + print "System Directiories cannot be created" + return 1 + + else: + host_connection = cm.getConnection(hostkey) + if not host_connection: + print "SSH Connection Not established to host '%s' " % hostkey + return 1 + command = base_command + dirpath + print "%s : %s" % (hostkey, command) + output = host_connection.executecommand(command) + return_status = atfutils.assert_success(**output) + atfutils.print_stdout(output['stdoutdata']) + atfutils.print_stderr(output['stderrdata']) + return return_status + +def mkfs(hostkey, device, fstype=None): + """ + """ + base_command = "mkfs " + cm = GlobalObj.getConnectionsManagerObj() + host_connection = cm.getConnection(hostkey) + if not host_connection: + print "SSH Connection Not established to host '%s' " % hostkey + return 1 + + if fstype is None: + fstype = "xfs" + + command = base_command + " -t " + fstype + " -f " + device + print "%s : %s" % (hostkey, command) + output = host_connection.executecommand(command) + return_status = atfutils.assert_success(**output) + atfutils.print_stdout(output['stdoutdata']) + atfutils.print_stderr(output['stderrdata']) + return return_status + +def find_mountpoints(hostkey, device): + """ + """ + base_command = "mount | grep " + cm = GlobalObj.getConnectionsManagerObj() + + host_connection = cm.getConnection(hostkey) + if not host_connection: + print "SSH connection to host '%s' has not been established" % hostkey + return 1 + + mountpoints = [] + command = base_command + device + print "%s : %s" % (hostkey, command) + output = host_connection.executecommand(command) + if not output["exitstatus"]: + for data in output["stdoutdata"]: + mountpoints.append(data.split(" ")[2]) + + return mountpoints + +def execute_command(hostkey, command, commandInput=None): + """ + """ + cm = GlobalObj.getConnectionsManagerObj() + host_connection = cm.getConnection(hostkey) + if not host_connection: + print "SSH Connection Not established to host '%s' " % hostkey + return 1 + new_command = _substitute_value_for_variables(hostkey, command) + + print "%s : %s" % (hostkey, command) + output = host_connection.executecommand(new_command, commandInput) + return_status = atfutils.assert_success(**output) + atfutils.print_stdout(output['stdoutdata']) + atfutils.print_stderr(output['stderrdata']) + return return_status + + +def _substitute_value_for_variables(hostkey, command): + """ + """ + pattern_for_variables = re.compile("<[a-z]+\d*>") + pattern_for_hosts = re.compile('(server|client|master)*') + variables_to_replace = [] + replace_values = {} + new_command = command + Functions_Map = { + "server" : "getserver", + "client" : "getclient", + "master" : "getmaster" + } + variables = pattern_for_variables.findall(command) + host = None + + if not variables: + return new_command + + else: + result = pattern_for_hosts.match(hostkey.lower()).group(0) + if result: + funcname = Functions_Map[result] + function = getattr(env, funcname) + if re.match("master", result): + host = function() + else: + host = function(hostkey) + + if not host: + print "No Host to execute the command\n" + return 1 + + for variable in variables: + if variable not in variables_to_replace: + variables_to_replace.append(variable.strip("<>")) + + for variable in variables_to_replace: + value = host.__getattribute__(variable) + replace_values[variable] = value + + for key in replace_values.keys(): + value = replace_values[key] + key = "<" + key + ">" + pattern = re.compile(key) + new_command = pattern.sub(value, new_command) + + return new_command + +__all__ = ['cd', + 'rmdir', + 'mkdir', + 'mkfs', + 'find_mountpoints', + 'execute_command'] diff --git a/SharedModules/Utils/managerutils.py b/SharedModules/Utils/managerutils.py new file mode 100644 index 0000000..ca38b3f --- /dev/null +++ b/SharedModules/Utils/managerutils.py @@ -0,0 +1,55 @@ +"""managerutils module. + +Supported Wrappers:- +--------------- +*) ssh_connect +*) ssh_connect_allhosts +""" + +import re +import ssh +from atfglobals import GlobalObj + +def ssh_connect(hostkey): + """ + """ + env = GlobalObj.getTestenvObj() + cm = GlobalObj.getConnectionsManagerObj() + host_connection = cm.getConnection(hostkey) + if not host_connection: + host_obj = env.getHost(hostkey) + if not host_obj: + print "Invalid Host. %s is not defined in TestEnvironment" % hostkey + return 1 + else: + host_connection = ssh.SshConnection() + if host_connection.connect(host_obj.hostname, host_obj.user, + host_obj.password): + return 1 + else: + if re.match("server", hostkey, re.IGNORECASE): + cm.addServer(hostkey, host_connection) + else: + cm.addClient(hostkey, host_connection) + return 0 + else: + print "Connection to %s already exist" % hostkey + + return 0 + +def ssh_connect_allhosts(): + """ + """ + env = GlobalObj.getTestenvObj() + cm = GlobalObj.getConnectionsManagerObj() + hosts_keys = env.getHostsKeys() + for hostkey in hosts_keys: + return_status = ssh_connect(hostkey) + if return_status: + return return_status + + return 0 + +__all__ = ['ssh_connect', + 'ssh_connect_allhosts'] + diff --git a/SharedModules/Utils/serverutils.py b/SharedModules/Utils/serverutils.py new file mode 100644 index 0000000..618ee23 --- /dev/null +++ b/SharedModules/Utils/serverutils.py @@ -0,0 +1,33 @@ +"""serverutils module +""" +import re +import hostutils +from atfglobals import GlobalObj + +def execute_on_brick(brickkey, command, commandInput=None): + """ + """ + env = GlobalObj.getTestenvObj() + + raw_brick_obj = env.getRawBrick(brickkey) + if not raw_brick_obj: + print "InValid Brick. %s not defined in TestEnvironment" % brickkey + return 1 + serverkey = re.split("\.", raw_brick_obj.hostname, maxsplit=1)[0] + + brick_obj = env.getBrick(brickkey) + if not brick_obj: + print "InValid Brick. %s not defined in TestEnvironment" % brickkey + return 1 + exportdirpath = brick_obj.path + + command = "cd " + exportdirpath + ";" + command + return_status = hostutils.execute_command(serverkey, command, commandInput) + return return_status + +__all__ = ['execute_on_brick'] + + + + + diff --git a/TestUnits/replicate/self_heal/Main.py b/TestUnits/replicate/self_heal/Main.py new file mode 100644 index 0000000..4e37265 --- /dev/null +++ b/TestUnits/replicate/self_heal/Main.py @@ -0,0 +1,69 @@ +"""Main module for the testunit. + +This module "main" function is called from atfexecute to execute the testunit. +""" +import parser +import atfutils +import glusterutils +import managerutils +import testcases + +def initialize(filename): + """ + """ + return_status = 1 + if parser.parse_testenv_configfile(filename): + return return_status + if managerutils.ssh_connect_allhosts(): + return return_status + + return 0 + +def setup(): + """ + """ + return_status = 1 + if atfutils.set_active_volume("volume1"): + return return_status + return 0 + +def execute(*testcaselist): + """ + """ + passedtestcases = 0 + failedtestcases = 0 + selectedtestcases = len(testcaselist) + + for testcase in testcaselist: + function_obj = getattr(testcases, testcase) + if function_obj: + print "Starting Test: ' %s '" % testcase + return_status = function_obj() + if return_status: + print "TestCase ' %s ' Failed" % testcase + failedtestcases += 1 + else: + print "TestCase ' %s ' Passed" % testcase + passedtestcases += 1 + print "Ending Test: ' %s '" % testcase + else: + print "TestCase %s not defined in 'testcases' module" % testcase + continue + + print "Selected %d : Passed %d, Failed %d" % (selectedtestcases, + passedtestcases, + failedtestcases) + +def cleanup(): + """ + """ + pass + +def main(testenvfile, *testcaselist): + """ + """ + initialize(testenvfile) + setup() + execute(*testcaselist) + cleanup() + return diff --git a/TestUnits/replicate/self_heal/testcases.py b/TestUnits/replicate/self_heal/testcases.py new file mode 100644 index 0000000..0015e5f --- /dev/null +++ b/TestUnits/replicate/self_heal/testcases.py @@ -0,0 +1,96 @@ +"""testcases for replicate/self-heal +""" + +import sys +import time +import hostutils +import managerutils +import glusterutils +import atfutils +import clientutils +import serverutils +import parser + +def reset_testenv(): + return_status = 1 + if clientutils.umountall(): + return return_status + glusterutils.volume_stop("server1", force=True) + glusterutils.volume_delete("server1") + glusterutils.glusterd_stop_allservers() + glusterutils.glusterd_remove_dir_allservers() + glusterutils.glusterd_remove_logs_allservers() + return 0 + +def setup_testenv(): + """ + """ + return_status = 1 + if glusterutils.glusterd_start_allservers(force=True): + return return_status + if glusterutils.peer_probe("server1"): + return return_status + if glusterutils.create_brick_allservers(): + return return_status + if glusterutils.volume_create("server1"): + return 1 + glusterutils.volume_set("server1", key="diagnostics.client-log-level", value="DEBUG") + if glusterutils.volume_start("server1"): + return 1 + if clientutils.mountall(): + return 1 + return 0 + +def test001(): + """ + Description: Test for failure when the entry does not exist + """ + return_status = 1 + if reset_testenv(): + return return_status + if setup_testenv(): + return return_status + return_status = clientutils.execute_on_mount("mount1", "ls abcd") + + if return_status: + test_status = 0 + else: + test_status = 1 + + return test_status + +def test002(): + """ + Description: Test for estale when the fs is stale + """ + return_status = 1 + if reset_testenv(): + return return_status + if setup_testenv(): + return return_status + + clientutils.execute_on_mount("mount1", "touch file") + serverutils.execute_on_brick("brick1", + "setfattr -n trusted.gfid -v 0sBfz5vAdHTEK1GZ99qjqTIg== file") + return_status = clientutils.execute_on_mount("mount1", "find file | xargs stat") + + if return_status: + test_status = 0 + else: + test_status = 1 + + return test_status + + + + + + + + + + + + + + diff --git a/TestUnits/replicate/self_heal/testcaseslist b/TestUnits/replicate/self_heal/testcaseslist new file mode 100644 index 0000000..ba90492 --- /dev/null +++ b/TestUnits/replicate/self_heal/testcaseslist @@ -0,0 +1,9 @@ +################################################################# +# List of testcases for the self-heal feature of afr. +# TestCaseId : Version : Keyword +################################################################## +test001 : >= 3.2 : art +test002 : >= 3.2 : art + + + diff --git a/TestUnits/replicate/self_heal/testenv.cfg b/TestUnits/replicate/self_heal/testenv.cfg new file mode 100644 index 0000000..a8b15c8 --- /dev/null +++ b/TestUnits/replicate/self_heal/testenv.cfg @@ -0,0 +1,98 @@ +[DEFAULT] +user = root +password = syst3m +glusterversion = 3.2.5 +installpath = +downloadpath = + +# ExportDir Section. +# Necessary Options: dir +# Optional: fstype, device +[export1] +dir = /export +fstype = xfs +device = /dev/sdb1 + +[export2] +dir = /export +fstype = xfs +device = /dev/sda1 + +# Server Section +# Necessary Options: hostname, username, password, glusterversion. +# The username, password, glusterversion defaults from DEFAULTS Section and +# can be overridden +# Optional: installpath +[server1] +hostname = 10.1.11.110 + +[server2] +hostname = 10.1.11.111 + +# Brick Section +# Necessary Options: hostname, path +[brick1] +hostname = server1.hostname +path = export1 + +[brick2] +hostname = server2.hostname +path = export2 + + +# Volume Section +# Necessary Options: volumename, volumetype, count, transporttype, bricks +[volume1] +volumename = replicate +volumetype = replica +count = 2 +transporttype = tcp +bricks = brick1, brick2 + +# Client Section +# Necessary Options: hostname, username, password, glusterversion. +# The username, password, glusterversion defaults from DEFAULTS Section and +# can be overridden +# Optional: installpath +[client1] +hostname = 10.1.11.109 + +# MountDevice Section +# Necessary Options: hostname, volume +# The Server1.hostname could be a VIP also. Need not be a server hostname +# IN a general case,(without NFS) we keep the 1st server from serverpool +# The volume specified in this section is the "active_volume" onto which all +# clients will be mounting to. This active volume and hostname can be changed +# during testrun. +[mountdevice1] +hostname = server1.hostname +volumename = volume1.volumename + +# Mount Section +# addMount(dir, type, client, device=master.volume, logfile=None) +[mount1] +dir = /mnt/replicate1 +client = client1 +device = mountdevice1 +type = glusterfs +logfile = +options = + +[mount2] +dir = /mnt/replicate2 +client = client1 +device = mountdevice1 +type = glusterfs + +[mount3] +dir = /mnt/replicate3 +client = client1 +device = mountdevice1 +type = glusterfs + + + + + + + diff --git a/atf.py b/atf.py new file mode 100755 index 0000000..63b0f9d --- /dev/null +++ b/atf.py @@ -0,0 +1,51 @@ +"""atf module is the entry point of the regression suite. + +CommandLine Usage: python atf.py -f testruninfo.cfg +""" +import argparse +import atfinit +import atfexecute + +def main(args): + """ + Description: + *) Initialize TestRun + *) Execute TestUnits + + Parameters: + args: Command Line Arguments passed to 'atf' + + Returns: + Success: 0 + Failure: 1 + """ + if atfinit.initialize(args): + exit(1) + + if atfexecute.execute(): + exit(1) + + else: + exit(0) + +if __name__ == "__main__": + + argparser = argparse.ArgumentParser( + description="Runs GlusterFS Functional/Regression Test Suite", + epilog="Report Bugs to dl-qa@gluster.com") + + argparser.add_argument('-f', '--file', required=True, type=str, + help="TestRunInfo FileName") + + args = argparser.parse_args() + + main(args) + + + + + + + + + diff --git a/atfexecute.py b/atfexecute.py new file mode 100644 index 0000000..a60402b --- /dev/null +++ b/atfexecute.py @@ -0,0 +1,63 @@ +"""atfexecute +""" + +import os.path +import sys +import parser +from atfglobals import GlobalObj + +def _execute_testunit(testunit): + """ + *) Parse the testcaseslist file in the 'testunit' and select test cases + specified for testing 'glusterversion' + *) Call Main.py of 'testunit' to execute the testcases. + """ + return_status = 1 + testruninfo_obj = GlobalObj.getTestrunInfoObj() + atfdir = testruninfo_obj.getAtfDir() + testunit_abspath = atfdir + "/TestUnits/" + testunit + + testenvfile = testunit_abspath + "/testenv.cfg" + testcaseslistfile = testunit_abspath + "/testcaseslist" + + if not os.path.exists(testenvfile): + default_testenvfile = atfdir + "testenv.cfg" + if not os.path.exists(testenvfile): + print "Skipping TestUnit %s . TestEnv File Not Found" % testenvfile + return return_status + else: + testenvfile = default_testenvfile + + if not os.path.exists(testcaseslistfile): + print "Skipping TestUnit %s" % testunit + return return_status + else: + testcaseslist = [] + testcasespassed = None + testcasesfailed = None + totaltestcases = None + + testcaseslist = parser.parse_testcaseslist_file(testcaseslistfile) + if not testcaseslist: + print "Skipping TestUnit %s. No testcases to execute" % testunit + return return_status + else: + sys.path.append(testunit_abspath) + import Main + print "Executing TestUnit: %s" % testunit + print "-" * 50 + return_status = Main.main(testenvfile, *testcaseslist) + return return_status + +def execute(): + """ + *) Execute the TestsCases form TestUnits specified in TestRunInfo File + """ + testruninfo_obj = GlobalObj.getTestrunInfoObj() + testunits = testruninfo_obj.getTestUnits() + for testunit in testunits: + _execute_testunit(testunit) + + return 0 + +__all__ = ['execute'] diff --git a/atfinit.py b/atfinit.py new file mode 100644 index 0000000..f50eefb --- /dev/null +++ b/atfinit.py @@ -0,0 +1,27 @@ +"""atfinit module + +""" +import os.path +import parser +from atfglobals import GlobalObj + +def _initialize_testrun_info(testrun_info_filename): + """ + """ + return_status = 1 + if not os.path.exists(testrun_info_filename): + print "Testrun Info File ' %s ' not found" % testrun_info_filename + return return_status + else: + return_status = parser.parse_testrun_info_file(testrun_info_filename) + return return_status + +def initialize(args): + """ + *) Initialize TestrunInfo File + """ + testrun_info_filename = args.file + return_status = _initialize_testrun_info(testrun_info_filename) + return return_status + +__all__ = ['initialize'] diff --git a/atfsetup.py b/atfsetup.py new file mode 100644 index 0000000..8631ab4 --- /dev/null +++ b/atfsetup.py @@ -0,0 +1,37 @@ +"""atf setup +""" + +from atfglobals import GlobalObj + +def _setup_loggers(): + """ + """ + testruninfo_obj = GlobalObj.getTestrunInfoObj() + logger_obj = GlobalObj.getLoggerObj() + + summaryloginfo = testruninfo_obj.getSummaryLogInfo() + detailloginfo = testruninfo_obj.getDetailLogInfo() + stdoutloginfo = testruninfo_obj.getStdoutLogInfo() + + logger_obj.setSummaryLog(summaryloginfo['filename'], + summaryloginfo['loglevel']) + loggerobj.setDetailLog(detailloginfo['filename'], + detailloginfo['loglevel']) + loggerobj.setStdoutLog(stdoutloginfo['do_log'], + stdoutloginfo['loglevel']) + + atfdir = testruninfo_obj.getAtfDir() + return_status = logger_obj.createLogger(atfdir) + if return_status: + print "Unable to create Loggers" + return return_status + +def setup(): + """ + *) Setup SummaryLogs , DetailLogs Handlers + """ + return_status = _setup_loggers() + return return_status + +__all__ = ['setup'] + diff --git a/export.py b/export.py new file mode 100755 index 0000000..e33812a --- /dev/null +++ b/export.py @@ -0,0 +1,13 @@ +#!/usr/bin/env python + +import os +import os + +exportstr = '' +libdir = os.getcwd() + "/SharedModules/" +for dirname, dirnames, filenames in os.walk(libdir): + for subdirname in dirnames: + exportstr = exportstr + os.path.join(dirname, subdirname) + ':' + +exportstr = os.getcwd() + ":" + libdir + ":" + exportstr +print exportstr diff --git a/testruninfo.cfg b/testruninfo.cfg new file mode 100755 index 0000000..ed65461 --- /dev/null +++ b/testruninfo.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. +## keywords: sanity +## Selects all testcases tagged with sanity keyword under given TestUnit +## (This is used for Sanity Runs) +## keywords: art +## Selects all testcases tagged with art keyword under given TestUnit +## (This is used for Regression Runs) +## Example: +## keywords = art +## keywords = sanity +############################################################################# +[Keywords] +keywords = + +############################################################################# +## 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 +############################################################################# +[TestUnits] +unit1 = replicate/self_heal + +############################################################################# +## Section: [ATFDir] +## atfdir = absolute path of the directory where Automation Framework +## is Installed +## Example: +## dir = /ATF +## dir = /home/qa/ATF +############################################################################# +[ATFDir] +dir = /home/shwetha/PythonCustomLibs/ATF + +############################################################################# +## 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: [GlusterVersion] +## filename = Version of the 'Gluster' for testing +## +## Example: +## version = '3.3.2' +## +############################################################################# +[GlusterVersion] +version = 3.2.5 + + + + + + -- cgit