def _get_source_file(source_folder, device): """ Makes an attempt to find specific file within the given folder. KVM deployment requires source file with 'kvm' within the name KVM deployment for NTD requires 'virtual-edition' string within the name :param source_folder: :param device: :return: """ file_extension = ".zip" try: folder_contents = [ content for content in os.listdir(source_folder) if file_extension in content ] folder_contents = filter(lambda x: 'kvm' in x, folder_contents) PrintMessage("All files available: {0}".format(folder_contents)) if device.device_type == DeviceType.ntd: folder_contents = filter(lambda x: 'virtual-edition' in x, folder_contents) PrintMessage("For device {0}, selected file: {1}".format( device.device_type, folder_contents)) except TypeError: return None if len(folder_contents): return folder_contents[0] return None
def _turn_on_config_mode(self): """ This is only applicable to CMS connection. :return: """ # previously executed test might have been stuck in conf mode # code belows attempts to fix the situation try: self.send_cmd(command_line=' ', expected_value=None) self.send_cmd(CONF_MODE) except: command_history_count = 15 show_history = SHOW_HISTORY.format(command_history_count) PrintMessage( 'Uncommitted changes found, quiting configuration mode.') PrintMessage( 'Print history of last {0}-commands in configuration mode'. format(command_history_count)) self.send_cmd(show_history, expected_value=show_history) self.send_cmd(EXIT_CONF) if PExpectWrapper.expect(self.cli, 'There are uncommitted changes.'): self.send_cmd(UsersChoice.yes) self.send_cmd(CONF_MODE) PrintMessage( 'Print history of last {0}-commands out of configuration mode'. format(command_history_count)) self.send_cmd(show_history, expected_value=show_history)
def send_cmd(self, command_line='', expected_value="[ok]", delay=None): """ Wrapper around PExpect sendline command :param command_line: :param expected_value: by default it expects an [ok] string, this is tuned towards CMS communication However, this can be used by any ssh type connection :param delay: wait after sending command :return: """ PrintMessage("cmd({0}): {1}".format(self.user.name, command_line)) self.cli.sendline(command_line) if delay is not None: time.sleep(delay) if expected_value is not None: try: if '[error]' in self.cli.before: PrintMessage('ERROR noted in cli', LoggingLevel.warning) PExpectWrapper.display_before_n_after(self.cli) index = self.cli.expect(expected_value) if '[error]' in self.cli.before: PrintMessage('ERROR noted in cli', LoggingLevel.warning) PExpectWrapper.display_before_n_after(self.cli) return index except: PExpectWrapper.display_before_n_after(self.cli) raise return self.cli.before
def get_suite_from_test_class(self, classes_to_run): all_classes = self.get_test_classes('Suite') def match(class_x, class_bunch): return [x for x in class_bunch if class_x.lower() in x[0].lower()] all_found = [] for class_to_run in classes_to_run: found = match(class_to_run, all_classes) if not found: PrintMessage("Not found class name: {0}".format(class_to_run)) continue all_found += found suite = unittest.TestSuite() loader = unittest.TestLoader() if len(all_found) == 0: PrintMessage( 'Failed to find test class with class(s) name: {0}'.format( classes_to_run)) return suite all_found = list( set(all_found )) # casting to set and back to list removes any duplicates for class_found in all_found: PrintMessage("Executing tests from test class: {0}".format( class_found[0])) suite.addTests(loader.loadTestsFromTestCase(class_found[1])) return suite
def prep_source_files(self, device_to_deploy): device_folder = ConfigLoader.get_test_run_config( "Source_Values")["Device_Folder"] source_folder = FileTools.get_device_source_folder( device_to_deploy, device_folder) if source_folder is None: exception_message = "Haven't found any source files that match build number: {0}." raise Exception( exception_message.format(device_to_deploy.version.build)) PrintMessage("Device found: {0}".format(source_folder)) source_file = self._get_source_file(source_folder, device_to_deploy) if source_file is None: exception_message = "Failed to retrieve source file from: {0} for device: {1}" raise Exception( exception_message.format(source_file, device_to_deploy.device_type)) build_number = Common.Utilities.DeploymentUtils.DeploymentHelper.get_build_version( source_file) PrintMessage("Extracted build number from zip file {0} > {1}".format( source_file, build_number)) device_temp_folder = self._unzip_to_temp_folder( source_file, source_folder) PrintMessage("Source files dropped to temp folder: {0}".format( device_temp_folder)) return build_number, device_temp_folder
def _modify_day_zero_file(self, device_temp_folder, device): os.chdir(device_temp_folder) day0cfg = device_temp_folder + "day0cfg" if not os.path.isfile(day0cfg + ".iso"): PrintMessage("No Day0.iso file found, skipping") return PrintMessage("Modifying Day0 file with with values from {0}".format( self._test_run_config.sourceFile)) with open(day0cfg, "w") as my_file: my_file.write("---\n") my_file.write( DeploymentConstants.Day0_NEW_SETTING_IP_ADDRESS.format( device.ip_address)) my_file.write( DeploymentConstants.Day0_NEW_SETTING_HOSTNAME.format( device.device_type)) for key in DeploymentConstants.Day0_NEW_SETTINGS.keys(): day_zero_option = self._get_formatted_day_zero_option_string( key, DeploymentConstants.Day0_NEW_SETTINGS[key]) my_file.write(day_zero_option) self._update_iso_file()
def setup_time(self, time_zone, enable_ntp='N', ntp_server=None): PrintMessage('Changing time zone to {0}, ntp server to {1} '.format( time_zone, ntp_server)) self.send_cmd('setup time') self.send_cmd(enable_ntp) if enable_ntp.lower() == 'y': self.send_cmd(ntp_server) self.send_cmd( 'none') # secondary server, none to finish server insertion self.send_cmd(time_zone) # expects [A]ccept, [C]hange if self.expect(['Enter \[A\]ccept', 'Enter \[C\]hange']) == 0: # save changes self.send_cmd('a', delay=60, expected_value='Applying changes...') else: # exit without saving as no modification was made self.send_cmd('e') # Added check to fish out any warnings SWALL-5007 index = self.expect([self.cli_prompt, 'WARNING']) if index == 0: return elif index == 1: self.expect(self.cli_prompt) PrintMessage(PExpectWrapper.display_before_n_after(self.cli)) assert False, "WARNING message is displayed: SWALL-5738"
def deploy(self, device_to_deploy): assert type(device_to_deploy) == Device # stored support password becomes obsolete with new device deployed ActionsProvisionalCLI.pop_password(device_to_deploy.ip_address) PrintMessage( "Deploying device: {0}, with ip address: {1}, build number: {2}". format( device_to_deploy.name, device_to_deploy.ip_address, 'latest' if device_to_deploy.version.build is None else device_to_deploy.version.build)) done = False attempt_count = 0 while not done: try: device_to_deploy.version.build = self._execute_deploy( device_to_deploy) done = True except subprocess.CalledProcessError, e: PrintMessage('DeployDevices error details: {0}'.format( e.output)) PrintMessage('Attempting to re-try the deployment') time.sleep(10) attempt_count += 1 if attempt_count > 5: raise Exception( 'Failed to deploy device {0} at address {1}'.format( device_to_deploy.name, device_to_deploy.ip_address))
def switch_off_vm(vm_ip): """ Static method used to turn of VM Machine :param vm_ip: address of the Virtual Machine (VM) :return: None """ vm = TalkWithESX._find_vm_by_ip(vm_ip, check_once=True) if vm is None: return PrintMessage("TalkWithEsxServer >> Found: {0}".format(vm.name)) PrintMessage( "TalkWithEsxServer >> The current powerState is: {0}".format( vm.runtime.powerState)) if format(vm.runtime.powerState) == "poweredOn": PrintMessage( "TalkWithEsxServer >> Attempting to power off {0}".format( vm.name)) vm_task = vm.PowerOffVM_Task() TalkWithESX._wait_for_task(vm_task, 'switch vm off') return vm
def _get_source_file(source_folder, device): file_extension = ".zip" try: folder_contents = [ content for content in os.listdir(source_folder) if file_extension in content ] folder_contents = filter(lambda x: 'kvm' not in x, folder_contents) PrintMessage("All files available: {0}".format(folder_contents)) if device.device_type == DeviceType.ntd: core_count = str(device.deployment_config['Core_Count']) folder_contents = filter(lambda x: core_count + '-core' in x, folder_contents) PrintMessage("For device {0}, selected file: {1}".format( device.device_type, folder_contents)) except TypeError: return None if len(folder_contents): return folder_contents[0] return None
def save_all_profile(self, destination_file): save_dump = SAVE_PROFILE.format('', destination_file) status_code = PExpectWrapper.execute_shell_command(self.cli, save_dump) if status_code == 0: PrintMessage('Defense profile saved') else: PrintMessage( 'Failed to save Defense profile, status code: {0}'.format( status_code))
def get_suite_from_test_ids(self, test_ids): """ :param test_ids: :return: """ all_test_classes = self.get_test_classes('Suite') found_test_with_class = {} found_test_count = 0 for test_class in all_test_classes: test_pair = test_class[1].__dict__ test_methods = [ test_method for test_method in test_pair.keys() if 'test_C' in test_method ] matched_tests = [ matched for matched in test_methods if self._get_test_id(matched) in test_ids ] for test in matched_tests: found_test_with_class.update({test: test_class[1]}) found_test_count += len(matched_tests) # breaking out when found all expected tests if found_test_count == len(test_ids): break suite = unittest.TestSuite() if len(found_test_with_class) == 0: PrintMessage('Failed to find test with id: {0}'.format(test_ids)) return suite # to preserve order in which tests were specified, adding tests as they were initially put in for test_id in test_ids: indices = [ i for i, s in enumerate(found_test_with_class.keys()) if str(test_id) in s ] if len(indices) > 0: index = indices[0] else: PrintMessage( "Failed to find test with test id: {0}".format(test_id)) continue test_name = found_test_with_class.keys()[index] class_name = found_test_with_class[test_name] suite.addTest(class_name(test_name)) return suite
def get_text_after_value(cli, key, strip_value=None): message = "Get text after key {0} : {1}" index = cli.expect([key, '% No entries found.', pexpect.TIMEOUT]) if index == 0: value = get_line_from_buffer(cli) PrintMessage(message.format(key, value)) return value.strip(strip_value) elif index == 1: return None else: PrintMessage(message.format(key, '?? not found...')) raise CLINoResults(display_before_n_after(cli))
def upload_results(test_results, all_tests, build_number, test_run_id): try: if build_number: result_uploader = TestRailUploader.TestRailResultUploader( test_run_id, build_number) result_uploader.process_and_upload(test_results, all_tests) except Exception as e: tb = traceback.format_exc() PrintMessage( '_upload_results > Encountered exception {0}, with args {1}'. format(type(e), e.args)) PrintMessage(str(e)) PrintMessage("_upload_results > traceback: {0}".format(tb)) pass
def _deploy_device(self, device): PrintMessage("Attempt to deploy the device to ESX server.") vmware_config_values = self._test_run_config.load("VMWare_Values") if self._ovf_file_path_to_temp is None: ova_file_name = "*.ovf" else: ova_file_name = self._ovf_file_path_to_temp management_network = '--net:Management="{0}"'.format( device.deployment_config["NET_Management"]) if device.device_type == DeviceType.ntd: ovf_tool_command = DeploymentConstants.OVF_COMMAND.format( device.deployment_config["VM_Name"], vmware_config_values["Datastore"], management_network, '--net:External="{0}"'.format( device.deployment_config["NET_External"]), '--net:Internal="{0}"'.format( device.deployment_config["NET_Internal"]), ova_file_name, vmware_config_values["ESX_User"], vmware_config_values["ESX_Password"], vmware_config_values["Host"]) elif device.device_type == DeviceType.sms: ovf_tool_command = DeploymentConstants.OVF_COMMAND.format( device.deployment_config["VM_Name"], vmware_config_values["Datastore"], management_network, '--net:Secondary="{0}"'.format( device.deployment_config["NET_Secondary"]), '', ova_file_name, vmware_config_values["ESX_User"], vmware_config_values["ESX_Password"], vmware_config_values["Host"]) elif device.device_type == DeviceType.swa: ovf_tool_command = DeploymentConstants.OVF_COMMAND.format( device.deployment_config["VM_Name"], vmware_config_values["Datastore"], management_network, '--net:Secondary="{0}"'.format( device.deployment_config["NET_Secondary"]), '', ova_file_name, vmware_config_values["ESX_User"], vmware_config_values["ESX_Password"], vmware_config_values["Host"]) else: raise BaseException( "_deploy_device(): unexpected deviceType found: {0}".format( device.device_type)) PrintMessage("OVF Command: {0}".format(ovf_tool_command)) output = subprocess.check_output(ovf_tool_command, shell=True) PrintMessage('DeployDevices print output: {0}'.format(output))
def wait_for_ntd( self, device_name, max_try=50, sync_expected=True, expected_connection_state=DeviceStatus.ConnectionState.connected, expected_deployment_state=DeviceStatus.DeploymentState.in_sync): PrintMessage(WAIT_FOR_NTD) re_try = 0 while re_try < max_try: time.sleep(4) re_try += 1 try: device_status = self.api_client.get_v1( RestAPIConstants.URL_DEVICE_STATUS.format(device_name)) except (APIError, URLError) as e: tb = traceback.format_exc() PrintMessage('Encountered exception {0}, with args {1}'.format( type(e), e.args)) PrintMessage(str(e)) PrintMessage("Traceback: {0}".format(tb)) continue if not sync_expected: if expected_connection_state == device_status['connectionState'] \ and DeviceStatus.DeploymentAction.none == device_status['deploymentAction']: PrintMessage( WAIT_FOR_NTD_DEPLOYED.format( device_name, device_status['deploymentState'], device_status['connectionState'], device_status['deploymentAction'])) return True if DeviceStatus.DeploymentState.sync_required in device_status[ 'deploymentState']: PrintMessage('Attempt to sync device') self.send_cmd(REQUEST_DEVICE_SYNC.format(device_name)) if expected_deployment_state == device_status['deploymentState'] \ and expected_connection_state == device_status['connectionState'] \ and DeviceStatus.DeploymentAction.none == device_status['deploymentAction']: PrintMessage( WAIT_FOR_NTD_IN_SYNC.format( device_name, device_status['deploymentState'], device_status['connectionState'], device_status['deploymentAction'])) return True PrintMessage( WAIT_FOR_NTD_RE_TRY.format(device_name, device_status['deploymentState'], device_status['connectionState'], device_status['deploymentAction'], re_try)) if re_try == max_try: raise DeploymentException('Device is not yet in sync!')
def open_iptables_port(self, command, expected): PrintMessage('Attempt to modify ip tables on {0}'.format(self.host)) self.send_cmd('iptables -S') if self.cli.expect([expected, pexpect.TIMEOUT]) == 0: PrintMessage('IPTables already enabled - skipping') return if PExpectWrapper.execute_shell_command(self.cli, command) != 0: raise Exception('Failed opening ip tables!') if PExpectWrapper.execute_shell_command( self.cli, 'service iptables save', expected_value='[ OK ]') != 0: raise Exception('Failed opening ip tables!')
def toggle_network_connection_on_vm(vm_ip, device_name, state): """ Static method used to find VM Machine and toggle state of its network device :param vm_ip: ip address of targeted VM machine :param device_name: the interface name NIC is associated with (also used as id) :param state: False / True to indicate desired state :return: None """ managed_object_reference = TalkWithESX._find_vm_by_ip(vm_ip) # name = 'rderinger-internal-vSwitch' found_device = TalkWithESX.find_network_device( managed_object_reference.config.hardware.device, device_name) if found_device is None: message = "Device '{0}' not found on the VM machine with ip address {1}" raise Exception(message.format(device_name, vm_ip)) found_device.connectable.connected = state message = 'TalkWithEsxServer > connection state device {0}:{1} and state: {2}'.format( device_name, vm_ip, state) PrintMessage(message) TalkWithESX._edit_configuration(managed_object_reference, found_device)
def get_json_from_cli(cli): """ preferably get smaller sets of json data as for some reason it chokes on json outputs with more than 30 lines for method to work correctly it is expected the display json part of command to be the last e.g. 'show me the money | nomore | display json' :param cli: :return: """ total_lines = '' try: while True: read_line = cli.readline().strip() if len(read_line) == 0 or read_line == '\x08': # x08 character was found with print repr(string) # this is an odd case, no idea how this got itself into CLI # show configuration analytics message-controls continue if '*** ALARM' in read_line: # Another odd case, CMS might throw an alarm at CLI while json scrubbing is taking place raise CLINoResults('CMS alarm invalidated json scrubbing') total_lines += read_line if total_lines.count('{') == total_lines.count('}') != 0: break cli_json = json.loads(total_lines, cls=Decoder) return cli_json except: PrintMessage('get_json_from_cli> failed to decode string: ' + total_lines) display_before_n_after(cli)
def close_connection(self): """ This sends exit to the remote shell. If there are stopped jobs then this automatically sends exit twice. :return: """ try: self.sendline(Common.Utilities.Enums.ControlKeys.ctr_c) self.sendline("exit") index = self.expect( [pexpect.EOF, "(?i)there are stopped jobs", pexpect.TIMEOUT]) if index == 1: self.sendline("exit") self.expect(pexpect.EOF) elif index == 2: PExpectWrapper.display_before_n_after(self) except OSError: pass self.close() PrintMessage('Connection closed: {0}@{1}:{2}'.format( self.username, self.host, self.port))
def is_text_present(self, notification_text, element_type=ElementType.specific_element_type, element_index=0, by_type=By.CSS_SELECTOR, value=".error"): if element_type == ElementType.specific_element_type: notification_field = text_to_be_present_in_element((by_type, value), notification_text, element_index) try: PrintMessage('Making an attempt to check for notification: {0}'.format(notification_text)) WebDriverWait(self.webdriver, 20).until(notification_field) except TimeoutException: return False elif element_type == ElementType.any_element_type: text_to_be_present_in_element((by_type, value), notification_text) PrintMessage('Making an attempt to check for notification: {0}'.format(notification_text)) return True
def process_arguments_group_test_run(): """ RunAll, RunSmoke, RunRegression type of runs :return: """ parser = argparse.ArgumentParser(prefix_chars='-') CommandLineArgumentsParser.add_argument_build_number(parser) CommandLineArgumentsParser.add_argument_do_not_disable_all_rules( parser) CommandLineArgumentsParser.add_argument_def_mode(parser) CommandLineArgumentsParser.add_argument_configuration_file(parser) CommandLineArgumentsParser.add_argument_list_of_report_recipients( parser) CommandLineArgumentsParser.add_argument_post_deploy_wait_time(parser) CommandLineArgumentsParser.add_argument_deploy_devices(parser) CommandLineArgumentsParser.add_argument_re_run_failed(parser) CommandLineArgumentsParser.add_argument_log_file_path(parser) parsed_args = parser.parse_args() Test_Context.do_not_disable_all_rules = parsed_args.do_not_disable_all_rules Test_Context.log_drop_folder = parsed_args.log_drop_folder PrintMessage(TEST_CONTEST_INFO.format(vars(Test_Context))) update_test_context_with_device_details(parsed_args.config_file) return parsed_args
def edit_entry(self, name, species=None, product=None, cut=None, whole=None, headless=None, on_on=None, on_off=None, off_on=None, off_off=None, j_cut_on=None, j_cut_off=None, butterfly=None, off_v=None): self.wait() self.edit_button.click() edit_dialog = CategoriesEditDialog(self.webdriver) edit_dialog.wait() edit_dialog.edit_and_confirm(name, species, product, cut, whole, headless, on_on, on_off, off_on, off_off, j_cut_on, j_cut_off, butterfly, off_v) confirmation_dialog = ConfirmationMessageDialog(self.webdriver) confirmation_dialog.ok_button.click() PrintMessage('Category edited.')
def _format_time_taken(time_taken): hours = int(time_taken / 3600) minutes = int((time_taken - (hours * 3600)) / 60) formatted_message = Const.TIME_TAKEN.format(hours, minutes) PrintMessage('TimeTaken: {0}'.format(formatted_message)) return formatted_message
def process_arguments_single_test_run(): """ Command line test run with specified set of tests either by class or test ids :return: """ parser = argparse.ArgumentParser(prefix_chars='-') CommandLineArgumentsParser.add_argument_do_not_disable_all_rules( parser) CommandLineArgumentsParser.add_argument_def_mode(parser) CommandLineArgumentsParser.add_argument_configuration_file(parser) CommandLineArgumentsParser.add_argument_list_of_test_ids(parser) CommandLineArgumentsParser.add_argument_list_of_class_names(parser) CommandLineArgumentsParser.add_argument_execute_in_loop(parser) CommandLineArgumentsParser.add_argument_execute_in_loop_until_failure( parser) # test CommandLineArgumentsParser.add_argument_build_number(parser) CommandLineArgumentsParser.add_argument_list_of_report_recipients( parser) parsed_args = parser.parse_args() Test_Context.do_not_disable_all_rules = parsed_args.do_not_disable_all_rules Test_Context.def_mode = parsed_args.def_mode PrintMessage(TEST_CONTEST_INFO.format(vars(Test_Context))) if len(parsed_args.test_ids) == 0 and len( parsed_args.test_class_names) == 0: parser.error(TestClassNameOrTestCaseID) update_test_context_with_device_details(parsed_args.config_file) return parsed_args
def print_attributes(self): attrs = self.web_driver_find.webdriver.execute_script( 'var items = {}; for (index = 0; index < arguments[0].' 'attributes.length; ++index) { items[arguments[0].' 'attributes[index].name] = arguments[0].' 'attributes[index].value }; return items;', self.element) PrintMessage('elem_attrib:' + str(attrs), include_time_stamp=False)
def setup_dns(self, dns_to_set='none', search_domain_to_set='none'): PrintMessage('Changing dns to {0}, search domain to {1} '.format( dns_to_set, search_domain_to_set)) self.send_cmd('show dns') # # SWALL-1642, otherwise this if is not necessary # if PExpectWrapper.get_text_after_matched_value(self.cli, 'Error') is None: # current_dns = PExpectWrapper.get_text_after_matched_value(self.cli, 'DNS Servers') # current_search_domain = PExpectWrapper.get_text_after_matched_value(self.cli, 'DNS Search Domains') # # if dns_to_set in current_dns and search_domain_to_set in current_search_domain: # return self.send_cmd('setup dns') self.send_cmd() # enter hostname self.send_cmd(dns_to_set) # primary dns if dns_to_set != 'none': self.send_cmd('none') # secondary dns self.send_cmd('none') # dns domain self.send_cmd(search_domain_to_set) # dns search domains if self.expect(['Enter \[A\]ccept', 'Enter \[C\]hange']) == 0: # save changes self.send_cmd('a', delay=10) self.expect('Applying changes...') else: # if no changes are introduced, exit without save self.send_cmd('e') self.send_cmd(delay=10) self.expect(self.cli_prompt)
def edit_entry(self, row, name, weight=None, shipping=CheckOneBox.no): self.wait() row.edit_row_item.click() edit_dialog = TransportsEditDialog(self.webdriver) edit_dialog.edit_and_confirm(name, weight, shipping) confirmation_dialog = ConfirmationMessageDialog(self.webdriver) confirmation_dialog.ok_button.click() PrintMessage('Transport edited.')
def add_entry(self, name, weight=None, shipping=CheckOneBox.no): self.wait() self.add_button.click() add_dialog = TransportsAddDialog(self.webdriver) add_dialog.add_entry_and_save(name, weight, shipping) confirmation_dialog = ConfirmationMessageDialog(self.webdriver) confirmation_dialog.ok_button.click() PrintMessage('Transport created.')
def delete_row(self, row): self.wait() row.delete_row_item.click() delete_dialog = ConfirmDeleteDialog(self.webdriver) delete_dialog.confirm_delete.click() confirmation_dialog = ConfirmationMessageDialog(self.webdriver) confirmation_dialog.ok_button.click() PrintMessage('Transport deleted.')