diff --git a/acktools/tests/acktools_tests.py b/acktools/tests/acktools_tests.py index 2bcb324e..8a9523dc 100644 --- a/acktools/tests/acktools_tests.py +++ b/acktools/tests/acktools_tests.py @@ -10,9 +10,8 @@ class MockProcess: def __init__(self, output, err=None): self.output = output - if err: - self.returncode = 1 if err else 0 - self.__stderr = err + self.returncode = 1 if err else 0 + self.__stderr = err def stderr(self): return self.__stderr diff --git a/autocertkit/ssh.py b/autocertkit/ssh.py index 2706f7de..eb6015db 100644 --- a/autocertkit/ssh.py +++ b/autocertkit/ssh.py @@ -41,22 +41,6 @@ SSHPORT = 22 -# Symbols we want to export from the package. -__all__ = ["SSHSession", - "SFTPSession", - "SSHCommand", - "SSH", - "SSHread", - "getPublicKey"] - - -def getPublicKey(): - filename = ".ssh/id_dsa.pub" - f = file(filename, "r") - data = f.read() - f.close() - return string.strip(data) - class SSHSession: @@ -169,230 +153,6 @@ def __del__(self): self.close() -class SFTPSession(SSHSession): - """An SFTP session guarded for target lockups.""" - - def __init__(self, - ip, - log, - username="root", - timeout=300, - password=None, - nowarn=False): - self.log = log - self.log.debug("SFTP session to %s@%s" % (username, ip)) - self.ip = ip - self.username = username - self.timeout = timeout - self.password = password - self.nowarn = nowarn - SSHSession.__init__(self, - ip, - log, - username=username, - timeout=timeout, - password=password, - nowarn=nowarn) - try: - # We do this rather than the simple trans.open_sftp_client() because - # if we don't then we don't get a timeout set so we can hang - # forever - c = self.trans.open_channel("session") - c.settimeout(timeout) - c.invoke_subsystem("sftp") - self.client = paramiko.SFTPClient(c) - except: - self.reply = "SFTP connection failed" - self.toreply = 1 - self.close() - - def getClient(self): - # This is UNSAFE - the client object may change if we auto reconnect! - return self.client - - def check(self): - # Check if the connection is still active, if not, try and re-open the - # connection (this handles the case where the connection has dropped - # due to a transient network error)... - - alive = True - - # First see if the transport is alive - if not self.trans.is_active(): - alive = False - else: - try: - d = self.client.listdir() - except: - alive = False - - if not alive: - log.warn( - "SFTP session appears to have gone away, attempting to reconnect...") - self.__init__(self.ip, - self.log, - username=self.username, - timeout=self.timeout, - password=self.password, - nowarn=self.nowarn) - - def close(self): - if self.client: - try: - self.client.close() - except Exception, e: - log.debug("SFTP close exception %s" % (str(e))) - if self.trans: - try: - self.trans.close() - except Exception, e: - log.debug("SFTP trans close exception %s" % (str(e))) - - def copyTo(self, source, dest, preserve=True): - log.debug("SFTP local:%s to remote:%s" % (source, dest)) - self.client.put(source, dest) - if preserve: - st = os.lstat(source) - if preserve == True: - self.client.chmod(dest, st.st_mode) - self.client.utime(dest, (st.st_atime, st.st_mtime)) - - def copyFrom(self, source, dest, preserve=True, threshold=None, - sizethresh=None): - log.debug("SFTP remote:%s to local:%s" % (source, dest)) - self.check() - st = self.client.stat(source) - if threshold and st.st_mtime < threshold: - log.debug("Skipping %s, too old" % (source)) - return - elif sizethresh and st.st_size > long(sizethresh): - log.debug("Skipping %s, too big (%u)" % - (source, st.st_size)) - return - self.client.get(source, dest) - if preserve: - if preserve == True: - os.chmod(dest, st.st_mode) - os.utime(dest, (st.st_atime, st.st_mtime)) - - def copyTreeTo(self, source, dest, preserve=True): - """Recursive copy to the remote host - - source: local directory being root of the tree - dest: remote directory to be the new root of the tree - """ - log.debug("SFTP recursive local:%s to remote:%s" % - (source, dest)) - self.check() - source = os.path.normpath(source) - dirs = os.walk(source) - for dir in dirs: - (dirname, dirnames, filenames) = dir - # Create the remote directory - dirname = os.path.normpath(dirname) - relpath = dirname[len(source):] - if len(relpath) > 0 and relpath[0] == "/": - relpath = relpath[1:] - targetpath = os.path.normpath(os.path.join(dest, relpath)) - try: - self.client.lstat(targetpath) - # Already exists - if preserve == True: - self.client.chmod(targetpath, os.lstat(dirname).st_mode) - except IOError, e: - self.client.mkdir(targetpath, os.lstat(dirname).st_mode) - # Copy all the files in - for file in filenames: - srcfile = os.path.join(dirname, file) - dstfile = os.path.join(targetpath, file) - st = os.lstat(srcfile) - self.client.put(srcfile, dstfile) - if preserve: - if preserve == True: - self.client.chmod(dstfile, st.st_mode) - self.client.utime(dstfile, (st.st_atime, st.st_mtime)) - - def copyTreeFromRecurse(self, source, dest, preserve=True, threshold=None, - sizethresh=None): - # make sure local destination exists - if not os.path.exists(dest): - os.makedirs(dest) - if preserve: - os.chmod(dest, self.client.lstat(source).st_mode) - d = self.client.listdir(source) - for i in d: - try: - dummy = self.client.listdir("%s/%s" % (source, i)) - isdir = True - except: - isdir = False - if isdir: - self.copyTreeFromRecurse("%s/%s" % (source, i), - "%s/%s" % (dest, i), - preserve=preserve, - threshold=threshold, - sizethresh=sizethresh) - else: - log.debug("About to copy %s/%s" % (source, i)) - st = self.client.stat("%s/%s" % (source, i)) - if threshold and st.st_mtime < threshold: - log.debug("Skipping %s/%s, too old" % - (source, i)) - elif sizethresh and st.st_size > long(sizethresh): - log.debug("Skipping %s/%s, too big (%u)" % - (source, i, st.st_size)) - else: - self.client.get("%s/%s" % (source, i), - "%s/%s" % (dest, i)) - if preserve: - if preserve == True: - os.chmod("%s/%s" % (dest, i), st.st_mode) - os.utime("%s/%s" % (dest, i), - (st.st_atime, st.st_mtime)) - - def copyTreeFrom(self, source, dest, preserve=True, threshold=None, - sizethresh=None): - """Recursive copy from the remote host - - source: remote directory being root of the tree - dest: local directory to be the new root of the tree - """ - log.debug("SFTP recursive remote:%s to local:%s" % - (source, dest)) - self.check() - self.copyTreeFromRecurse(source, - dest, - preserve=preserve, - threshold=threshold, - sizethresh=sizethresh) - - def copyLogsFrom(self, pathlist, dest, threshold=None, sizethresh=None): - """Copy any files or directory trees from pathlist remotely to - dest locally""" - log.debug("SFTP log fetch of %s to local:%s" % - (`pathlist`, dest)) - for p in pathlist: - # Directory? - log.debug("Trying to fetch %s." % (p)) - try: - d = self.client.listdir(p) - self.copyTreeFrom(p, "%s/%s" % (dest, os.path.basename(p)), - preserve="utime", threshold=threshold, - sizethresh=sizethresh) - except: - # File? - try: - s = self.client.lstat(p) - self.copyFrom(p, "%s/%s" % (dest, os.path.basename(p)), - preserve="utime", threshold=threshold, - sizethresh=sizethresh) - except: - pass - - def __del__(self): - SSHSession.__del__(self) - - class SSHCommand(SSHSession): """An SSH session guarded for target lockups.""" @@ -486,89 +246,3 @@ def read(self, retval="code", fh=None): def __del__(self): SSHSession.__del__(self) - - -def SSH(ip, - command, - username="root", - timeout=300, - retval="code", - password=None, - idempotent=False, - nowarn=False, - newlineok=False, - getreply=True, - nolog=False, - outfile=None): - tries = 0 - while True: - tries = tries + 1 - log.debug("SSH %s@%s %s (attempt %u)" % - (username, ip, command, tries)) - try: - s = SSHCommand(ip, - command, - log, - username=username, - timeout=timeout, - password=password, - nowarn=nowarn, - newlineok=newlineok, - nolog=nolog) - if outfile: - try: - f = file(outfile, 'w') - reply = s.read(retval="code", fh=f) - finally: - f.close() - return reply - elif getreply: - reply = s.read(retval=retval) - return reply - else: - return None - except Exception, e: - if tries >= 3 or not idempotent: - raise e - if string.find(str(e), "SSH command exited with error") > -1: - raise e - if not nowarn: - log.debug("Retrying ssh connection %s@%s %s after %s" - % (username, ip, command, str(e))) - time.sleep(5) - - -def SSHread(ip, - command, - log, - username="root", - timeout=300, - password=None, - idempotent=False, - nowarn=False, - newlineok=False): - tries = 0 - while True: - tries = tries + 1 - log.debug("SSH %s@%s %s (attempt %u)" % - (username, ip, command, tries)) - try: - s = SSHCommand(ip, - command, - log, - username=username, - timeout=timeout, - password=password, - nowarn=nowarn, - newlineok=newlineok) - reply = s.read(retval="string") - return reply - except Exception, e: - if tries >= 3 or not idempotent: - raise e - if string.find(str(e), "SSH command exited with error") > -1: - raise e - if not nowarn: - log.debug("Retrying ssh connection %s@%s %s after %s" - % (username, ip, command, str(e))) - time.sleep(5) diff --git a/autocertkit/test_report.py b/autocertkit/test_report.py index e481f383..920e3c31 100644 --- a/autocertkit/test_report.py +++ b/autocertkit/test_report.py @@ -57,7 +57,8 @@ def wrap_text(string, width): def print_system_info(stream): """ Retrieve system information from SMBIOS and write to given stream. """ - sys_info = search_dmidecode("System Information") + session = get_local_xapi_session() + sys_info = search_dmidecode(session, "System Information") stream.write("#########################\n") stream.write("System Information from SMBIOS\n") stream.write('\n'.join(sys_info)) diff --git a/autocertkit/utils.py b/autocertkit/utils.py index 13a89537..73fe82af 100644 --- a/autocertkit/utils.py +++ b/autocertkit/utils.py @@ -57,8 +57,6 @@ DROID_VM = 'droid_vm' DEFAULT_PASSWORD = 'citrix' FOR_CLEANUP = "for_cleanup" -DROID_VM_LOC = '/opt/xensource/packages/files/auto-cert-kit/vpx-dlvm.xva' -XE = '/opt/xensource/bin/xe' DROID_TEMPLATE_TAG = "droid_vm_template" REBOOT_ERROR_CODE = 3 REBOOT_FLAG_FILE = "/opt/xensource/packages/files/auto-cert-kit/reboot" @@ -568,12 +566,6 @@ def validate_rec(self, rec): if key not in rec.keys(): raise Exception("Error: invalid input rec '%s'" % rec) - def to_rec(self): - rec = {} - for key in self.required_keys: - rec[key] = getattr(self, key) - return rec - def get_local_xapi_session(): """Login to Xapi locally. This will only work if this script is being run @@ -583,13 +575,6 @@ def get_local_xapi_session(): return session -def get_remote_xapi_session(creds): - """Return a remote xapi session based on creds""" - session = XenAPI.Session("http://%s" % creds['host']) - session.login_with_password(creds['user'], creds['pass']) - return session - - def get_pool_master(session): """Returns the reference to host which is currently master over the pool which can be seen with the given session""" @@ -702,19 +687,6 @@ def host_crash(session, do_cleanup=False): raise Exception("Failed to crash host.") -def retrieve_latest_crashdump(session, host=None, fromxapi=False): - """Retrieve latest one from crashdump list""" - cds = retrieve_crashdumps(session, host, fromxapi) - if not cds: - return None - - latest = sorted(cds, key=lambda cd: cd['timestamp'], reverse=True)[0] - - log.debug("Latest crashdump: %s" % latest) - - return latest - - def retrieve_crashdumps(session, host=None, fromxapi=False): """Retrive all list of crashdump of master.""" if not host: @@ -742,25 +714,6 @@ def retrieve_crashdumps(session, host=None, fromxapi=False): return cds -def print_test_results(tracker): - """Method for pretty printing results""" - for mlist in tracker: - for testclass in mlist: - for test in testclass: - print "****Test Name:", test['test_name'], "****" - print "Test Result:", test['result'] - if test.has_key('info'): - print "Additional Info:", test['info'] - if test.has_key('data'): - print "Data:", test['data'] - if test.has_key('config'): - print "Config:", test['config'] - if test.has_key('exception'): - print "Exceptions:", test['exception'], "\n" - else: - print - - def get_pool_slaves(session): """Returns a list of references for each host in a pool which is not a pool master""" @@ -821,65 +774,6 @@ def eval_expr(expr, val): condition) -def append_result_node(dom, parent_node, result): - """parent_node is an xml node to be appended to, result - is a dictionary item""" - element = dom.createElement("test") - parent_node.appendChild(element) - for key in result.keys(): - k = dom.createElement(key) - element.appendChild(k) - k.appendChild(dom.createTextNode(result[key])) - - -def make_local_call(call): - """Function wrapper for making a simple call to shell""" - log.debug(' '.join(call)) - process = subprocess.Popen(call, stdout=subprocess.PIPE) - stdout, stderr = process.communicate() - if process.returncode == 0: - return str(stdout).strip() - else: - log.debug("ERR: %s, %s" % (stdout, stderr)) - sys.exit() - - -def save_bugtool(): - """Saves a bugtool and returns the name""" - print "Collecting a bugtool report:" - call = ["xen-bugtool", "--yestoall"] - info = make_local_call(call) - where = info.find('/var/opt/xen/bug-report') - return ((info[where:]).split())[0] - - -def compress_output_files(mylist): - """Compress all output files to bz2 and return the name""" - print "Compressing output files...""" - tar = tarfile.open("auto-cert-kit-logs.tar.bz2", "w:bz2") - for myfile in mylist: - tar.add(myfile) - tar.close() - - -def output_test_results(tracker): - """Outputs an xml results doc and creates a xen-bugtool, - then bzip2 them together""" - xml_file_name = ('cert_log_%s.xml' % datetime.datetime.now()) - myfile = open(xml_file_name, 'w') - doc = xml.dom.minidom.Document() - top_element = doc.createElement("results") - doc.appendChild(top_element) - for all_results in tracker: - for test_class in all_results: - for test_result in test_class: - append_result_node(doc, top_element, test_result) - myfile.write(doc.toprettyxml()) - myfile.close() - bugtool = save_bugtool() - compress_output_files([xml_file_name, bugtool]) - - def create_network(session, name_label, description, other_config): """Method for creating a XAPI network""" net_ref = session.xenapi.network.create({'name_label': name_label, @@ -926,17 +820,6 @@ def get_pifs_by_device(session, device, hosts=[]): (device, hosts)) -def get_network_by_device(session, device): - pifs = get_pifs_by_device(session, device) - network_refs = [] - for pif in pifs: - ref = session.xenapi.PIF.get_network(pif) - if ref not in network_refs: - network_refs.append(ref) - assert(len(network_refs) == 1) - return network_refs.pop() - - def get_physical_devices_by_network(session, network): """Taking a network, enumerate the list of physical devices attached to each component PIF. This may require some unwrapping (e.g. bonds) @@ -1034,18 +917,6 @@ def create_vlan(session, pif_ref, network_ref, vlan_id): return session.xenapi.VLAN.create(pif_ref, str(vlan_id), network_ref) -def get_droid_templates(session, brand=DROID_TEMPLATE_TAG): - """Return the reference to the template for the - demo linux VM. This is obtained by searching for - a template with the other_config key 'droid_template_vm'.""" - vms = session.xenapi.VM.get_all() - droid_vms = [] - for vm in vms: - if brand in session.xenapi.VM.get_other_config(vm): - droid_vms.append(vm) - return droid_vms - - def brand_vm(session, vm_ref, brand=DROID_VM): """Take a VM, or template and brand it with a key in other_config""" oc = session.xenapi.VM.get_other_config(vm_ref) @@ -1107,17 +978,6 @@ def make_vm_noninteractive(session, vm_ref): session.xenapi.VM.set_PV_args(vm_ref, 'noninteractive') -def xenstore_read(path): - """Uses the local xenstore utility to read a specified path""" - process = subprocess.Popen(['/usr/bin/xenstore-read', path], - stdout=subprocess.PIPE) - stdout, stderr = process.communicate() - if process.returncode == 0: - return stdout - else: - raise TestCaseError(stderr) - - def should_timeout(start, timeout): """Method for evaluating whether a time limit has been met""" return time.time() - start > float(timeout) @@ -1292,20 +1152,6 @@ def ssh_command(ip, username, password, cmd_str, dbg_str=None, attempts=10): raise Exception("An unkown error has occured!") -def add_network_interface(vm_ip, interface_name, interface_ip, - interface_netmask, username="root", - password=DEFAULT_PASSWORD, dhcp=False): - """Configures a network interface inside a linux VM""" - log.debug("add_network_interface for %s" % vm_ip) - if dhcp: - cmd = "ifconfig %s up" % interface_name - else: - cmd = "ifconfig %s %s netmask %s up" % \ - (interface_name, interface_ip, interface_netmask) - - ssh_command(vm_ip, username, password, cmd, cmd, attempts=10) - - def plug_pif(session, pif): """ Plug given pif""" log.debug("Plugging PIF: %s" % pif) @@ -1527,24 +1373,6 @@ def get_module_names(name_filter): return modules -def change_vm_power_state(session, vm_ref): - """Toggles VM powerstate between halted and running""" - vm_power_state = session.xenapi.VM.get_power_state(vm_ref) - print "Current VM power state: %s" % vm_power_state - if vm_power_state == 'Running': - log.debug("%s is shutting down" % vm_ref) - session.xenapi.VM.clean_shutdown(vm_ref) - log.debug("%s shutdown complete" % vm_ref) - elif vm_power_state == 'Halted': - log.debug("%s is booting" % vm_ref) - session.xenapi.VM.start(vm_ref, False, False) - - -def arg_encode(string): - """Encode a string for sending over XML-RPC to plugin""" - return string.replace('/', '/').replace('.', '.') - - def droid_template_import(session, host_ref, sr_uuid): """Import the droid template into the specified SR""" # Note, the filename should be fully specified. @@ -1552,21 +1380,6 @@ def droid_template_import(session, host_ref, sr_uuid): return call_ack_plugin(session, 'droid_template_import', args, host=host_ref) -def get_default_sr(session): - """Returns the SR reference marked as default in the pool""" - pool_ref = session.xenapi.pool.get_all()[0] - sr_ref = session.xenapi.pool.get_default_SR(pool_ref) - try: - # A call to check 'freshness' of default SR reference - log.debug("Default SR: %s" % session.xenapi.SR.get_name_label(sr_ref)) - return sr_ref - except XenAPI.Failure, exn: - if exn.details[0] == 'HANDLE_INVALID': - raise Exception("Pool is not configured to have shared storage!") - else: - raise exn - - def get_local_sr(session, host): """Returns the ref object the local SR on the master host""" all_pbds = session.xenapi.PBD.get_all_records() @@ -1608,7 +1421,7 @@ def find_storage_for_host(session, host_ref, exclude_types=['iso', 'udev']): return rel_srs -def import_droid_vm(session, host_ref, creds=None, loc=DROID_VM_LOC): +def import_droid_vm(session, host_ref, creds=None): """Import VM template from Dom0 for use in tests""" sr_refs = find_storage_for_host(session, host_ref) @@ -1985,20 +1798,6 @@ def droid_set_static(session, vm_ref, protocol, iface, ip, netmask, gw): return call_ack_plugin(session, 'droid_set_static_conf', args) -def get_non_management_pifs(session): - """Return a list of pif refs for non management devices""" - pifs = session.xenapi.PIF.get_all_records() - results = [] - for pif_ref, rec in pifs.iteritems(): - if not rec['management']: - results.append(pif_ref) - - if not results: - raise Exception("No management PIFs were found!") - - return results - - class TimeoutFunction: """Wrapper class for providing a timemout for the execution of a function""" @@ -2008,7 +1807,7 @@ def __init__(self, function, timeout, exception=''): self.function = function self.exception = exception - def handle_timeout(self, signum, frame): + def handle_timeout(self, *args, **kwargs): raise TimeoutFunctionException(self.exception) def __call__(self, *args): @@ -2121,14 +1920,6 @@ def set_hw_offload(session, device, offload, state): 'state': state}) -def parse_csv_list(string): - arr = string.split(',') - res = [] - for item in arr: - res.append(item.strip()) - return res - - def set_nic_device_status(session, interface, status): """Function to set an ifconfig ethX interface up or down""" log.debug("Bringing %s network interface %s" % (status, interface)) @@ -2253,14 +2044,6 @@ def get_system_info(session): return rec -def get_master_ifaces(session): - devices = get_master_network_devices(session) - ifaces = [] - for device in devices: - ifaces.append(device['Kernel_name']) - return ifaces - - def set_dict_attributes(node, config): """Take a dict object, and set xmlnode attributes accordingly""" for k, v in config.iteritems(): @@ -2275,14 +2058,6 @@ def get_xml_attributes(node): return attr -def get_text_from_node_list(nlist, tag): - for node in nlist: - if node.nodeType == node.ELEMENT_NODE and node.tagName == tag: - for subnode in node.childNodes: - if subnode.nodeType == node.TEXT_NODE: - return subnode.data.strip() - - def to_bool(string): """Convert string value of true/false to bool""" return string.upper() == "TRUE"