def main(): parser = argparse.ArgumentParser( epilog=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter) parser.add_argument('address', help='hostname or ip address of target appliance') args = parser.parse_args() ssh_kwargs = { 'username': credentials['ssh']['username'], 'password': credentials['ssh']['password'], 'hostname': args.address } # Init SSH client client = SSHClient(**ssh_kwargs) # generate installed rpm list status, out = client.run_command( 'rpm -qa | sort > /tmp/installed_rpms.txt') client.get_file('/tmp/installed_rpms.txt', 'installed_rpms.txt') # compress logs dir status, out = client.run_command( 'cd /var/www/miq/vmdb; tar zcvf /tmp/appliance_logs.tgz log') client.get_file('/tmp/appliance_logs.tgz', 'appliance_logs.tgz')
def setup_external_auth_openldap(**data): """Sets up the appliance for an external authentication with OpenLdap. Keywords: get_groups: Get User Groups from External Authentication (httpd). ipaserver: IPA server address. iparealm: Realm. credentials: Key of the credential in credentials.yaml """ connect_kwargs = { 'username': credentials['host_default']['username'], 'password': credentials['host_default']['password'], 'hostname': data['ipaddress'], } appliance_obj = appliance.IPAppliance() appliance_name = 'cfmeappliance{}'.format(fauxfactory.gen_alpha(7).lower()) appliance_address = appliance_obj.address appliance_fqdn = '{}.{}'.format(appliance_name, data['domain_name']) ldapserver_ssh = SSHClient(**connect_kwargs) # updating the /etc/hosts is a workaround due to the # https://bugzilla.redhat.com/show_bug.cgi?id=1360928 command = 'echo "{}\t{}" >> /etc/hosts'.format(appliance_address, appliance_fqdn) ldapserver_ssh.run_command(command) ldapserver_ssh.get_file(remote_file=data['cert_filepath'], local_path=conf_path.strpath) ldapserver_ssh.close() ensure_browser_open() login_admin() auth = ExternalAuthSetting(get_groups=data.pop("get_groups", True)) auth.setup() appliance_obj.configure_appliance_for_openldap_ext_auth(appliance_fqdn) logout()
def main(): parser = argparse.ArgumentParser( epilog=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter) parser.add_argument('address', help='hostname or ip address of target appliance') parser.add_argument('-R', '--reverse', help='flag to indicate the patch should be undone', action='store_true', default=False, dest='reverse') args = parser.parse_args() # Find the patch file patch_file_name = data_path_for_filename('ajax_wait.diff', scripts_path.strpath) # Set up temp dir tmpdir = mkdtemp() atexit.register(shutil.rmtree, tmpdir) source = '/var/www/miq/vmdb/public/javascripts/application.js' target = os.path.join(tmpdir, 'application.js') # Init SSH client ssh_kwargs = { 'username': credentials['ssh']['username'], 'password': credentials['ssh']['password'], 'hostname': args.address } client = SSHClient(**ssh_kwargs) print 'retriving appliance.js from appliance' client.get_file(source, target) os.chdir(tmpdir) # patch, level 4, patch direction (default forward), ignore whitespace, don't output rejects direction = '-N -R' if args.reverse else '-N' exitcode = subprocess.call('patch -p4 %s -l -r- < %s' % (direction, patch_file_name), shell=True) if exitcode == 0: # Put it back after successful patching. print 'replacing appliance.js on appliance' client.put_file(target, source) else: print 'not changing appliance' return exitcode
def main(): parser = argparse.ArgumentParser(epilog=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter) parser.add_argument('address', help='hostname or ip address of target appliance') parser.add_argument('-R', '--reverse', help='flag to indicate the patch should be undone', action='store_true', default=False, dest='reverse') args = parser.parse_args() # Find the patch file patch_file_name = data_path_for_filename('ajax_wait.diff', scripts_path.strpath) # Set up temp dir tmpdir = mkdtemp() atexit.register(shutil.rmtree, tmpdir) source = '/var/www/miq/vmdb/public/javascripts/application.js' target = os.path.join(tmpdir, 'application.js') # Init SSH client ssh_kwargs = { 'username': credentials['ssh']['username'], 'password': credentials['ssh']['password'], 'hostname': args.address } client = SSHClient(**ssh_kwargs) print 'retriving appliance.js from appliance' client.get_file(source, target) os.chdir(tmpdir) # patch, level 4, patch direction (default forward), ignore whitespace, don't output rejects direction = '-N -R' if args.reverse else '-N' exitcode = subprocess.call('patch -p4 %s -l -r- < %s' % (direction, patch_file_name), shell=True) if exitcode == 0: # Put it back after successful patching. print 'replacing appliance.js on appliance' client.put_file(target, source) else: print 'not changing appliance' return exitcode
def main(): parser = argparse.ArgumentParser(epilog=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter) parser.add_argument('address', help='hostname or ip address of target appliance') args = parser.parse_args() ssh_kwargs = { 'username': credentials['ssh']['username'], 'password': credentials['ssh']['password'], 'hostname': args.address } # Init SSH client client = SSHClient(**ssh_kwargs) # generate installed rpm list status, out = client.run_command('rpm -qa | sort > /tmp/installed_rpms.txt') client.get_file('/tmp/installed_rpms.txt', 'installed_rpms.txt') # compress logs dir status, out = client.run_command('cd /var/www/miq/vmdb; tar zcvf /tmp/appliance_logs.tgz log') client.get_file('/tmp/appliance_logs.tgz', 'appliance_logs.tgz')
class UiCoveragePlugin(object): def __init__(self): self.ssh_client = SSHClient() # trylast so that terminalreporter's been configured before ui-coverage @pytest.mark.trylast def pytest_configure(self, config): # Eventually, the setup/teardown work for coverage should be handled by # utils.appliance.Appliance to make multi-appliance support easy self.reporter = config.pluginmanager.getplugin('terminalreporter') self.reporter.write_sep('-', 'Setting up UI coverage reporting') self.install_simplecov() self.install_coverage_hook() self.restart_evm() self.touch_all_the_things() check_appliance_ui(base_url()) def pytest_unconfigure(self, config): self.reporter.write_sep( '-', 'Waiting for coverage to finish and collecting reports') self.stop_touching_all_the_things() self.merge_reports() self.collect_reports() self.print_report() def install_simplecov(self): logger.info('Installing coverage gems on appliance') self.ssh_client.put_file(gemfile.strpath, rails_root.strpath) x, out = self.ssh_client.run_command( 'cd {}; bundle'.format(rails_root)) return x == 0 def install_coverage_hook(self): logger.info('Installing coverage hook on appliance') # Put the coverage hook in the miq lib path self.ssh_client.put_file( coverage_hook.strpath, rails_root.join('..', 'lib', coverage_hook.basename).strpath) replacements = { 'require': r"require 'coverage_hook'", 'config': rails_root.join('config').strpath } # grep/echo to try to add the require line only once # This goes in preinitializer after the miq lib path is set up, # which makes it so ruby can actually require the hook command_template = ( 'cd {config};' 'grep -q "{require}" preinitializer.rb || echo -e "\\n{require}" >> preinitializer.rb' ) x, out = self.ssh_client.run_command( command_template.format(**replacements)) return x == 0 def restart_evm(self, rude=True): logger.info('Restarting EVM to enable coverage reporting') # This is rude by default (issuing a kill -9 on ruby procs), since the most common use-case # will be to set up coverage on a freshly provisioned appliance in a jenkins run if rude: x, out = self.ssh_client.run_command( 'killall -9 ruby; service evmserverd start') else: x, out = self.ssh_client.run_comment('service evmserverd restart') return x == 0 def touch_all_the_things(self): logger.info( 'Establishing baseline overage by requiring ALL THE THINGS') # send over the thing toucher self.ssh_client.put_file( thing_toucher.strpath, rails_root.join(thing_toucher.basename).strpath) # start it in an async process so we can go one testing while this takes place self._thing_toucher_proc = Process(target=_thing_toucher_mp_handler, args=[self.ssh_client]) self._thing_toucher_proc.start() def stop_touching_all_the_things(self): logger.info('Waiting for baseline coverage generator to finish') # block while the thing toucher is still running self._thing_toucher_proc.join() return self._thing_toucher_proc.exitcode == 0 def merge_reports(self): logger.info("Merging coverage reports on appliance") # install the merger script self.ssh_client.put_file( coverage_merger.strpath, rails_root.join(coverage_merger.basename).strpath) # don't async this one since it's happening in unconfigure # merge/clean up the coverage reports x, out = self.ssh_client.run_rails_command('coverage_merger.rb') return x == 0 def collect_reports(self): coverage_dir = log_path.join('coverage') # clean out old coverage dir if it exists if coverage_dir.check(): coverage_dir.remove(rec=True, ignore_errors=True) # Then ensure the the empty dir exists coverage_dir.ensure(dir=True) # then copy the remote coverage dir into it logger.info("Collecting coverage reports to {}".format( coverage_dir.strpath)) logger.info("Report collection can take several minutes") self.ssh_client.get_file(rails_root.join('coverage').strpath, log_path.strpath, recursive=True) def print_report(self): try: last_run = json.load( log_path.join('coverage', '.last_run.json').open()) coverage = last_run['result']['covered_percent'] # TODO: Make the happy vs. sad coverage color configurable, and set it to something # good once we know what good is style = {'bold': True} if coverage > 40: style['green'] = True else: style['red'] = True self.reporter.line('UI Coverage Result: {}%'.format(coverage), **style) except KeyboardInterrupt: # don't block this, so users can cancel out raise except: logger.error( 'Error printing coverage report to terminal, traceback follows' ) logger.error(traceback.format_exc())
class UiCoveragePlugin(object): def __init__(self): self.ssh_client = SSHClient() # trylast so that terminalreporter's been configured before ui-coverage @pytest.mark.trylast def pytest_configure(self, config): # Eventually, the setup/teardown work for coverage should be handled by # utils.appliance.Appliance to make multi-appliance support easy self.reporter = config.pluginmanager.getplugin('terminalreporter') self.reporter.write_sep('-', 'Setting up UI coverage reporting') self.install_simplecov() self.install_coverage_hook() self.restart_evm() self.touch_all_the_things() check_appliance_ui(base_url()) def pytest_unconfigure(self, config): self.reporter.write_sep('-', 'Waiting for coverage to finish and collecting reports') self.stop_touching_all_the_things() self.merge_reports() self.collect_reports() self.print_report() def install_simplecov(self): logger.info('Installing coverage gems on appliance') self.ssh_client.put_file(gemfile.strpath, rails_root.strpath) x, out = self.ssh_client.run_command('cd {}; bundle'.format(rails_root)) return x == 0 def install_coverage_hook(self): logger.info('Installing coverage hook on appliance') # Put the coverage hook in the miq lib path self.ssh_client.put_file( coverage_hook.strpath, rails_root.join('..', 'lib', coverage_hook.basename).strpath ) replacements = { 'require': r"require 'coverage_hook'", 'config': rails_root.join('config').strpath } # grep/echo to try to add the require line only once # This goes in preinitializer after the miq lib path is set up, # which makes it so ruby can actually require the hook command_template = ( 'cd {config};' 'grep -q "{require}" preinitializer.rb || echo -e "\\n{require}" >> preinitializer.rb' ) x, out = self.ssh_client.run_command(command_template.format(**replacements)) return x == 0 def restart_evm(self, rude=True): logger.info('Restarting EVM to enable coverage reporting') # This is rude by default (issuing a kill -9 on ruby procs), since the most common use-case # will be to set up coverage on a freshly provisioned appliance in a jenkins run if rude: x, out = self.ssh_client.run_command('killall -9 ruby; service evmserverd start') else: x, out = self.ssh_client.run_comment('service evmserverd restart') return x == 0 def touch_all_the_things(self): logger.info('Establishing baseline overage by requiring ALL THE THINGS') # send over the thing toucher self.ssh_client.put_file( thing_toucher.strpath, rails_root.join(thing_toucher.basename).strpath ) # start it in an async process so we can go one testing while this takes place self._thing_toucher_proc = Process(target=_thing_toucher_mp_handler, args=[self.ssh_client]) self._thing_toucher_proc.start() def stop_touching_all_the_things(self): logger.info('Waiting for baseline coverage generator to finish') # block while the thing toucher is still running self._thing_toucher_proc.join() return self._thing_toucher_proc.exitcode == 0 def merge_reports(self): logger.info("Merging coverage reports on appliance") # install the merger script self.ssh_client.put_file( coverage_merger.strpath, rails_root.join(coverage_merger.basename).strpath ) # don't async this one since it's happening in unconfigure # merge/clean up the coverage reports x, out = self.ssh_client.run_rails_command('coverage_merger.rb') return x == 0 def collect_reports(self): coverage_dir = log_path.join('coverage') # clean out old coverage dir if it exists if coverage_dir.check(): coverage_dir.remove(rec=True, ignore_errors=True) # Then ensure the the empty dir exists coverage_dir.ensure(dir=True) # then copy the remote coverage dir into it logger.info("Collecting coverage reports to {}".format(coverage_dir.strpath)) logger.info("Report collection can take several minutes") self.ssh_client.get_file( rails_root.join('coverage').strpath, log_path.strpath, recursive=True ) def print_report(self): try: last_run = json.load(log_path.join('coverage', '.last_run.json').open()) coverage = last_run['result']['covered_percent'] # TODO: Make the happy vs. sad coverage color configurable, and set it to something # good once we know what good is style = {'bold': True} if coverage > 40: style['green'] = True else: style['red'] = True self.reporter.line('UI Coverage Result: {}%'.format(coverage), **style) except KeyboardInterrupt: # don't block this, so users can cancel out raise except: logger.error('Error printing coverage report to terminal, traceback follows') logger.error(traceback.format_exc())