def test_volume_attach_detach_instance(volume, new_instance, appliance): """ Polarion: assignee: mnadeem casecomponent: Cloud initialEstimate: 1/4h """ # TODO: Test Reset and Cancel initial_instance_count = volume.instance_count volume.attach_instance(new_instance.name) view = appliance.browser.create_view(navigator.get_class(volume, 'Details').VIEW) view.flash.assert_success_message( 'Attaching Cloud Volume "{name}" to {instance} finished'.format( name=volume.name, instance=new_instance.name)) @wait_for_decorator(delay=10, timeout=300, message="Waiting for volume to be attached to instance") def volume_attached_to_instance(): new_instance.refresh_relationships() return volume.instance_count == initial_instance_count + 1 volume.detach_instance(new_instance.name) view = appliance.browser.create_view(navigator.get_class(volume, 'Details').VIEW) view.flash.assert_success_message( 'Detaching Cloud Volume "{name}" from {instance} finished'.format( name=volume.name, instance=new_instance.name)) @wait_for_decorator(delay=10, timeout=300, message="Waiting for volume to be detached from instance") def volume_detached_from_instance(): new_instance.refresh_relationships() return volume.instance_count == initial_instance_count
def set_ownership(self, user=None, group=None, click_cancel=False, click_reset=False): """Set instance ownership Args: user (str): username for ownership group (str): groupname for ownership click_cancel (bool): Whether to cancel form submission click_reset (bool): Whether to reset form after filling """ view = navigate_to(self, 'SetOwnership') fill_result = view.form.fill({ 'user_name': user, 'group_name': group}) if not fill_result: view.form.cancel_button.click() view = self.create_view(navigator.get_class(self, 'Details').VIEW) view.flash.assert_success_message('Set Ownership was cancelled by the user') return # Only if the form changed if click_reset: view.form.reset_button.click() view.flash.assert_message('All changes have been reset', 'warning') # Cancel after reset assert view.form.is_displayed view.form.cancel_button.click() elif click_cancel: view.form.cancel_button.click() view.flash.assert_success_message('Set Ownership was cancelled by the user') else: # save the form view.form.save_button.click() view = self.create_view(navigator.get_class(self, 'Details').VIEW) view.flash.assert_success_message('Ownership saved for selected {}' .format(self.VM_TYPE))
def test_flavor_crud(appliance, provider, request): """ Polarion: assignee: mnadeem casecomponent: Cloud initialEstimate: 1/4h """ collection = appliance.collections.cloud_flavors flavor = collection.create(name=fauxfactory.gen_alpha(), provider=provider, ram=RAM, vcpus=VCPUS, disk=DISK_SIZE, swap=SWAP_SIZE, rxtx=RXTX) @request.addfinalizer def cleanup(): if flavor.exists: flavor.delete() view = appliance.browser.create_view(navigator.get_class(collection, 'All').VIEW) view.flash.assert_success_message( 'Add of Flavor "{}" was successfully initialized.'.format(flavor.name)) wait_for(lambda: flavor.exists, delay=5, timeout=600, fail_func=flavor.refresh, message='Wait for flavor to appear') flavor.delete() view = appliance.browser.create_view(navigator.get_class(collection, 'All').VIEW) view.flash.assert_success_message( 'Delete of Flavor "{}" was successfully initiated.'.format(flavor.name)) wait_for(lambda: not flavor.exists, delay=5, timeout=600, fail_func=flavor.refresh, message='Wait for flavor to appear')
def test_instance_attach_detach_volume_with_type(volume_with_type, new_instance, appliance): """ Polarion: assignee: mnadeem initialEstimate: 1/4h """ initial_volume_count = new_instance.volume_count new_instance.attach_volume(volume_with_type.name) view = appliance.browser.create_view(navigator.get_class(new_instance, 'Details').VIEW) view.flash.assert_success_message( 'Attaching Cloud Volume "{}" to {} finished' .format(volume_with_type.name, new_instance.name) ) @wait_for_decorator(delay=10, timeout=300, message="Waiting for volume to be attached to instance") def volume_attached_to_instance(): new_instance.refresh_relationships() return new_instance.volume_count > initial_volume_count new_instance.detach_volume(volume_with_type.name) view = appliance.browser.create_view(navigator.get_class(new_instance, 'Details').VIEW) view.flash.assert_success_message( 'Detaching Cloud Volume "{}" from {} finished' .format(volume_with_type.name, new_instance.name) ) @wait_for_decorator(delay=10, timeout=300, message="Waiting for volume to be detached from instance") def volume_detached_from_instance(): new_instance.refresh_relationships() return new_instance.volume_count == initial_volume_count
def test_chargeback_duplicate_disallowed( chargeback_rate, rate_resource, rate_type, rate_action, appliance ): """ Polarion: assignee: nachandr casecomponent: CandU caseimportance: low initialEstimate: 1/12h """ cb_rate = chargeback_rate # for brevity assert cb_rate.exists with pytest.raises((AssertionError, TimedOutError)): # create method might raise either if rate_resource == 'compute': appliance.collections.compute_rates.create( description=cb_rate.description, fields=cb_rate.fields ) elif rate_resource == 'storage': appliance.collections.storage_rates.create( description=cb_rate.description, fields=cb_rate.fields ) # view should still be on the add form view = cb_rate.create_view(navigator.get_class(cb_rate.parent, 'Add').VIEW, wait=10) view.flash.assert_message('Description has already been taken', t='error') # cancel form, check all redirect view.cancel_button.click() view = cb_rate.create_view(navigator.get_class(cb_rate.parent, 'All').VIEW, wait=10) view.flash.assert_success_message('Add of new Chargeback Rate was cancelled by the user')
def test_map_tagging_crud(appliance, category, soft_assert): """Test map tag crud with flash message assertion Polarion: assignee: anikifor initialEstimate: 1/4h casecomponent: Tagging """ label = fauxfactory.gen_alphanumeric(8) map_tags_collection = appliance.collections.map_tags map_tag_entity = map_tags_collection.create('Container Project', label, category.name) view = appliance.browser.create_view(navigator.get_class(map_tags_collection, 'All').VIEW) view.flash.assert_success_message('Container Label Tag Mapping "{}" was added' .format(label)) # use label var to validate create method with update(map_tag_entity): map_tag_entity.category = fauxfactory.gen_alphanumeric(8) view = appliance.browser.create_view(navigator.get_class(map_tags_collection, 'All').VIEW) view.flash.assert_success_message( 'Container Label Tag Mapping "{}" was saved' .format(map_tag_entity.label) # use entity label since it may get updated ) row = next(view.table.rows(resource_label=map_tag_entity.label)) soft_assert(row.tag_category.text == map_tag_entity.category) map_tag_entity.delete() view = appliance.browser.create_view(navigator.get_class(map_tags_collection, 'All').VIEW) view.flash.assert_success_message('Container Label Tag Mapping "{}": Delete successful' .format(map_tag_entity.label))
def _post_update_checks(self, edit_view): details_view = self.create_view(navigator.get_class(self, 'Details').VIEW) main_view = self.create_view(navigator.get_class(self, 'All').VIEW) main_view.flash.assert_no_error() success_text = '{} Manager "{}" was saved'.format(self.string_name, self.name) if main_view.is_displayed: main_view.flash.assert_message(success_text) elif details_view.is_displayed: details_view.flash.assert_message(success_text) else: edit_view.flash.assert_no_error() raise AssertionError("Provider wasn't updated. It seems form isn't accurately filled")
def test_vm_analysis_profile_crud(appliance, soft_assert, analysis_profile_collection): """CRUD for VM analysis profiles. Polarion: assignee: anikifor caseimportance: medium initialEstimate: 1/2h testtype: integration """ vm_profile = analysis_profile_collection.create( name=fauxfactory.gen_alphanumeric(), description=fauxfactory.gen_alphanumeric(), profile_type=analysis_profile_collection.VM_TYPE, files=files_list, categories=categories_list, registry=registry_list, events=events_check() ) view = appliance.browser.create_view( navigator.get_class(analysis_profile_collection, 'All').VIEW) vm_flash = vm_profile.name if appliance.version < '5.10' else vm_profile.description view.flash.assert_message('Analysis Profile "{}" was saved'.format(vm_flash)) assert vm_profile.exists files_updates = events_check(updates=True) with update(vm_profile): vm_profile.files = files_updates view = appliance.browser.create_view(navigator.get_class(vm_profile, 'Details').VIEW) view.flash.assert_success_message('Analysis Profile "{}" was saved'.format(vm_flash)) soft_assert(vm_profile.files == files_updates, 'Files update failed on profile: {}, {}'.format(vm_profile.name, vm_profile.files)) with update(vm_profile): vm_profile.categories = ['System'] soft_assert(vm_profile.categories == ['System'], 'Categories update failed on profile: {}'.format(vm_profile.name)) copied_profile = vm_profile.copy(new_name='copied-{}'.format(vm_profile.name)) view = appliance.browser.create_view( navigator.get_class(analysis_profile_collection, 'All').VIEW) # yep, not copy specific vm_copied_flash = ( copied_profile.name if appliance.version < '5.10' else copied_profile.description ) view.flash.assert_message('Analysis Profile "{}" was saved'.format(vm_copied_flash)) assert copied_profile.exists copied_profile.delete() assert not copied_profile.exists vm_profile.delete() view.flash.assert_success_message('Analysis Profile "{}": Delete successful'.format(vm_flash)) assert not vm_profile.exists
def test_migrations_different_os_templates(request, appliance, v2v_providers, host_creds, conversion_tags, form_data_multiple_vm_obj_single_datastore, soft_assert): """ Polarion: assignee: kkulkarn casecomponent: V2V initialEstimate: 1/4h subcomponent: RHV upstream: yes """ infrastructure_mapping_collection = appliance.collections.v2v_mappings mapping = infrastructure_mapping_collection.create( form_data_multiple_vm_obj_single_datastore.form_data) @request.addfinalizer def _cleanup(): infrastructure_mapping_collection.delete(mapping) migration_plan_collection = appliance.collections.v2v_plans migration_plan = migration_plan_collection.create( name="plan_{}".format(fauxfactory.gen_alphanumeric()), description="desc_{}" .format(fauxfactory.gen_alphanumeric()), infra_map=mapping.name, vm_list=form_data_multiple_vm_obj_single_datastore.vm_list, start_migration=True) # as migration is started, try to track progress using migration plan request details page view = appliance.browser.create_view( navigator.get_class(migration_plan_collection, 'All').VIEW.pick()) wait_for(func=view.progress_card.is_plan_started, func_args=[migration_plan.name], message="migration plan is starting, be patient please", delay=5, num_sec=150, handle_exception=True, fail_cond=False) view.progress_card.select_plan(migration_plan.name) view = appliance.browser.create_view(navigator.get_class(migration_plan_collection, 'Details').VIEW, wait='10s') request_details_list = view.migration_request_details_list view.items_on_page.item_select('15') vms = request_details_list.read() wait_for(func=view.plan_in_progress, message="migration plan is in progress, be patient please", delay=5, num_sec=4200) for vm in vms: soft_assert(request_details_list.is_successful(vm) and not request_details_list.is_errored(vm)) src_vms_list = form_data_multiple_vm_obj_single_datastore.vm_list # validate MAC address matches between source and target VMs for src_vm in src_vms_list: migrated_vm = get_migrated_vm_obj(src_vm, v2v_providers.rhv_provider) soft_assert(src_vm.mac_address == migrated_vm.mac_address)
def test_compute_chargeback_duplicate_disallowed(chargeback_compute_rate): chargeback_compute_rate.create() assert chargeback_compute_rate.exists with pytest.raises(AssertionError): chargeback_compute_rate.create() # view should still be on the add form view = chargeback_compute_rate.create_view( navigator.get_class(chargeback_compute_rate, 'Add').VIEW) view.flash.assert_message('Description has already been taken', t='error') # cancel form, check all redirect view.cancel_button.click() view = chargeback_compute_rate.create_view( navigator.get_class(chargeback_compute_rate, 'All').VIEW) assert view.is_displayed view.flash.assert_success_message('Add of new Chargeback Rate was cancelled by the user')
def create(self, entity_type, label, category, cancel=False): """ Map tags creation method Args: cancel: True - if you want to cancel map creation, by defaul map will be created """ view = navigate_to(self, 'Add') view.fill({ 'resource_entity': entity_type, 'resource_label': label, 'category': category }) if cancel: view.cancel_button.click() else: view.add_button.click() view = self.create_view(navigator.get_class(self, 'All').VIEW) assert view.is_displayed view.flash.assert_no_error() return self.instantiate( entity_type=entity_type, label=label, category=category )
def test_mandatory_entry_point_with_dynamic_element(appliance): """Tests Entry point should be mandatory if element is dynamic Bugzilla: 1488579 Polarion: assignee: nansari casecomponent: Services caseimportance: high initialEstimate: 1/8h tags: service """ element_1_data = { 'element_information': { 'ele_label': "ele_label_{}".format(fauxfactory.gen_alphanumeric()), 'ele_name': fauxfactory.gen_alphanumeric(), 'ele_desc': fauxfactory.gen_alphanumeric(), 'dynamic_chkbox': True, 'choose_type': "Text Box", } } service_dialog = appliance.collections.service_dialogs sd = service_dialog.create(label='label_{}'.format(fauxfactory.gen_alphanumeric(), description="my dialog")) tab = sd.tabs.create(tab_label='tab_{}'.format(fauxfactory.gen_alphanumeric(), tab_desc="my tab desc")) box = tab.boxes.create(box_label='box_{}'.format(fauxfactory.gen_alphanumeric(), box_desc="my box desc")) assert box.elements.create(element_data=[element_1_data]) is False view_cls = navigator.get_class(sd.parent, 'Add').VIEW view = appliance.browser.create_view(view_cls) assert view.save.disabled
def test_crud_service_dialog(appliance): """ Polarion: assignee: sshveta casecomponent: Services initialEstimate: 1/4h """ element_data = { 'element_information': { 'ele_label': "ele_" + fauxfactory.gen_alphanumeric(), 'ele_name': fauxfactory.gen_alphanumeric(), 'ele_desc': fauxfactory.gen_alphanumeric(), 'choose_type': "Text Box" }, 'options': { 'default_text_box': "Default text" } } dialog, element = create_dialog(appliance, element_data) view_cls = navigator.get_class(element.parent, 'Add').VIEW view = element.appliance.browser.create_view(view_cls) flash_message = '{} was saved'.format(dialog.label) view.flash.assert_message(flash_message) with update(dialog): dialog.description = "my edited description" dialog.delete()
def test_retirement_now_ec2_instance_backed(retire_ec2_s3_vm, tagged): """Tests on-demand retirement of an instance/vm S3 (instance-backed) EC2 instances that aren't lifecycle tagged won't get shut down """ # Tag the VM with lifecycle for full retirement based on parameter if tagged: retire_ec2_s3_vm.add_tag('LifeCycle', 'Fully retire VM and remove from Provider') expected_power_state = ['terminated'] else: # no tagging expected_power_state = ['on'] # For 5.7+ capture two times to assert the retire time is within a window. # Too finicky to get it down to minute precision, nor is it really needed here retire_times = dict() retire_times['start'] = generate_retirement_date_now() + timedelta(minutes=-5) retire_ec2_s3_vm.retire() view_cls = navigator.get_class(retire_ec2_s3_vm, 'Details').VIEW reload = retire_ec2_s3_vm.appliance.browser.create_view(view_cls).toolbar.reload assert wait_for(lambda: retire_ec2_s3_vm.is_retired, delay=5, num_sec=10 * 60, fail_func=reload.click, message="Wait for VM '{}' to enter retired state" .format(retire_ec2_s3_vm.name)) view = retire_ec2_s3_vm.load_details() assert view.entities.power_management.get_text_of('Power State') in expected_power_state retire_times['end'] = generate_retirement_date_now() + timedelta(minutes=5) verify_retirement_date(retire_ec2_s3_vm, expected_date=retire_times)
def update(self, updates, cancel=False): """ Update category method Args: updates: category data that should be changed cancel: """ view = navigate_to(self, 'Edit') change = view.fill({ 'name': updates.get('name'), 'display_name': updates.get('display_name'), 'long_description': updates.get('description'), 'show_in_console': updates.get('show_in_console'), 'single_value': updates.get('single_value'), 'capture_candu': updates.get('capture_candu'), }) if cancel or not change: view.cancel_button.click() else: view.save_button.click() view = self.create_view(navigator.get_class(self.parent, 'All').VIEW) assert view.is_displayed view.flash.assert_no_error()
def test_add_new_compute_chargeback(chargeback_compute_rate): chargeback_compute_rate.create() view = chargeback_compute_rate.create_view( navigator.get_class(chargeback_compute_rate, 'All').VIEW) view.flash.assert_success_message('Chargeback Rate "{}" was added' .format(chargeback_compute_rate.description)) assert chargeback_compute_rate.exists
def _assign_unassign_policy_profiles(self, assign, *policy_profile_names): """DRY function for managing policy profiles. See :py:func:`assign_policy_profiles` and :py:func:`assign_policy_profiles` Args: assign: Wheter to assign or unassign. policy_profile_names: :py:class:`str` with Policy Profile names. """ view = navigate_to(self, 'ManagePoliciesFromDetails') policy_changed = False for policy_profile in policy_profile_names: if assign: policy_changed = view.policy_profiles.fill( view.policy_profiles.CheckNode([policy_profile]) ) or policy_changed else: policy_changed = view.policy_profiles.fill( view.policy_profiles.UncheckNode([policy_profile]) ) or policy_changed if policy_changed: view.save.click() else: view.cancel.click() details_view = self.create_view(navigator.get_class(self, 'Details').VIEW) details_view.flash.assert_no_error()
def test_analysis_profile_duplicate_name(analysis_profile_collection): """ Test to validate duplicate profiles name. Polarion: assignee: anikifor casecomponent: Configuration caseimportance: low initialEstimate: 1/15h """ profile = analysis_profile_collection.create( name=fauxfactory.gen_alphanumeric(), description=fauxfactory.gen_alphanumeric(), profile_type=analysis_profile_collection.VM_TYPE, categories=categories_list ) with pytest.raises(AssertionError): analysis_profile_collection.create( name=profile.name, description=profile.description, profile_type=analysis_profile_collection.VM_TYPE, categories=profile.categories ) # Should still be on the form page after create method raises exception view = analysis_profile_collection.create_view( navigator.get_class(analysis_profile_collection, 'AddVmProfile').VIEW, wait='10s' ) view.flash.assert_message("Name has already been taken") view.cancel.click()
def create(self, description, currency=None, fields=None): """ Create a rate in the UI Args: description (str): name of the compute rate to create currency (str): - type of currency for the rate fields (dict): - nested dictionary listing the Rate Details Key => Rate Details Description Value => dict Key => Rate Details table column names Value => Value to input in the table """ storage_rate = self.instantiate(description, currency, fields) view = navigate_to(self, 'Add') view.fill_with({'description': storage_rate.description, 'currency': storage_rate.currency, 'fields': storage_rate.fields}, on_change=view.add_button, no_change=view.cancel_button) view = self.create_view(navigator.get_class(self, 'All').VIEW, wait=10) view.flash.assert_no_error() return storage_rate
def test_service_dialog_duplicate_name(appliance, request): element_data = { 'element_information': { 'ele_label': "ele_" + fauxfactory.gen_alphanumeric(), 'ele_name': fauxfactory.gen_alphanumeric(), 'ele_desc': fauxfactory.gen_alphanumeric(), 'choose_type': "Text Box" }, 'options': { 'default_text_box': "Default text" } } label = 'duplicate_' + fauxfactory.gen_alphanumeric() dialog, element = create_dialog(appliance, element_data, label=label) request.addfinalizer(dialog.delete_if_exists) region_number = appliance.server.zone.region.number error_message = version.pick({ '5.8': 'Validation failed: Label is not unique within region {}'.format(region_number), '5.9': 'There was an error editing this dialog: ' 'Failed to create a new dialog - Validation failed: ' 'Name is not unique within region {}'.format(region_number)}) with pytest.raises(AssertionError): create_dialog(appliance, element_data, label=label) view_cls = navigator.get_class(element.parent, 'Add').VIEW view = element.appliance.browser.create_view(view_cls) view.flash.assert_message(error_message)
def test_single_network_single_vm_migration(request, appliance, v2v_providers, host_creds, conversion_tags, form_data_vm_obj_single_network): """ Polarion: assignee: kkulkarn casecomponent: V2V initialEstimate: 1/4h subcomponent: RHV upstream: yes """ # This test will make use of migration request details page to track status of migration infrastructure_mapping_collection = appliance.collections.v2v_mappings mapping = infrastructure_mapping_collection.create(form_data_vm_obj_single_network.form_data) @request.addfinalizer def _cleanup(): infrastructure_mapping_collection.delete(mapping) migration_plan_collection = appliance.collections.v2v_plans migration_plan = migration_plan_collection.create( name="plan_{}".format(fauxfactory.gen_alphanumeric()), description="desc_{}" .format(fauxfactory.gen_alphanumeric()), infra_map=mapping.name, vm_list=form_data_vm_obj_single_network.vm_list, start_migration=True) # as migration is started, try to track progress using migration plan request details page view = appliance.browser.create_view( navigator.get_class(migration_plan_collection, 'All').VIEW.pick()) wait_for(func=view.progress_card.is_plan_started, func_args=[migration_plan.name], message="migration plan is starting, be patient please", delay=5, num_sec=150, handle_exception=True, fail_cond=False) view.progress_card.select_plan(migration_plan.name) view = appliance.browser.create_view(navigator.get_class(migration_plan_collection, 'Details').VIEW, wait='10s') request_details_list = view.migration_request_details_list vms = request_details_list.read() # ideally this will always pass as request details list shows VMs in migration plan # unless we have a bug assert len(vms) > 0, "No VMs displayed on Migration Plan Request Details list." wait_for(func=view.plan_in_progress, message="migration plan is in progress, be patient please", delay=5, num_sec=2700) assert (request_details_list.is_successful(vms[0]) and not request_details_list.is_errored(vms[0])) # validate MAC address matches between source and target VMs src_vm = form_data_vm_obj_single_network.vm_list.pop() migrated_vm = get_migrated_vm_obj(src_vm, v2v_providers.rhv_provider) assert src_vm.mac_address == migrated_vm.mac_address
def after_fill(self, was_change): # TODO: Remove this method once BZ1647695 has been fixed self.submit_button.click() if was_change and BZ(1647695, forced_streams=['5.10', 'upstream']).blocks: instance = self.context['object'] view = self.browser.create_view(navigator.get_class(instance, 'Details').VIEW) wait_for(lambda: view.entities.title.text == 'Instance "{}"'.format( self.context['object'].name), timeout=20, delay=2)
def test_migration_with_edited_mapping(request, appliance, v2v_providers, edited_form_data, form_data_vm_obj_single_datastore, host_creds, conversion_tags, soft_assert): """ Test migration with edited infrastructure mapping. Steps: * create mapping , edit mapping * Migrate vm Polarion: assignee: sshveta caseimportance: medium initialEstimate: 1/4h casecomponent: V2V """ _form_data, edited_form_data = edited_form_data infrastructure_mapping_collection = appliance.collections.v2v_mappings mapping = infrastructure_mapping_collection.create(form_data_vm_obj_single_datastore.form_data) @request.addfinalizer def _cleanup(): infrastructure_mapping_collection.delete(mapping) # vm_obj is a list, with only 1 VM object, hence [0] src_vm_obj = form_data_vm_obj_single_datastore.vm_list[0] mapping.update(edited_form_data) migration_plan_collection = appliance.collections.v2v_plans migration_plan = migration_plan_collection.create( name="plan_{}".format(fauxfactory.gen_alphanumeric()), description="desc_{}".format(fauxfactory.gen_alphanumeric()), infra_map=mapping.name, vm_list=form_data_vm_obj_single_datastore.vm_list, start_migration=True) # explicit wait for spinner of in-progress status card view = appliance.browser.create_view( navigator.get_class(migration_plan_collection, 'All').VIEW.pick()) wait_for(func=view.progress_card.is_plan_started, func_args=[migration_plan.name], message="migration plan is starting, be patient please", delay=5, num_sec=150, handle_exception=True, fail_cond=False) # wait until plan is in progress wait_for(func=view.plan_in_progress, func_args=[migration_plan.name], message="migration plan is in progress, be patient please", delay=5, num_sec=1800) view.switch_to("Completed Plans") view.wait_displayed() migration_plan_collection.find_completed_plan(migration_plan) logger.info("For plan %s, migration status after completion: %s, total time elapsed: %s", migration_plan.name, view.migration_plans_completed_list. get_vm_count_in_plan(migration_plan.name), view.migration_plans_completed_list.get_clock(migration_plan.name)) # validate MAC address matches between source and target VMs assert view.migration_plans_completed_list.is_plan_succeeded(migration_plan.name) migrated_vm = get_migrated_vm_obj(src_vm_obj, v2v_providers.rhv_provider) assert src_vm_obj.mac_address == migrated_vm.mac_address
def delete(self, cancel=False): """Delete a CB rate in the UI Args: cancel: boolean, whether to cancel the action on alert """ view = navigate_to(self, 'Details') view.toolbar.configuration.item_select('Remove from the VMDB', handle_alert=(not cancel)) view = self.create_view(navigator.get_class(self.parent, 'All').VIEW, wait=10) view.flash.assert_no_error()
def update(self, updates): # Update a rate in UI view = navigate_to(self, 'Edit') view.fill_with(updates, on_change=view.save_button, no_change=view.cancel_button) view = self.create_view(navigator.get_class(self, 'Details').VIEW) view.flash.assert_no_error()
def create(self, cancel=False, validate_credentials=True, validate_inventory=False, check_existing=False): if check_existing and self.exists: return False created = True logger.info('Setting up Network Provider: %s', self.key) add_view = navigate_to(self, 'Add') if not cancel or (cancel and any(self.view_value_mapping.values())): # filling main part of dialog add_view.fill(self.view_value_mapping) if not cancel or (cancel and self.endpoints): # filling endpoints for endpoint_name, endpoint in self.endpoints.items(): try: # every endpoint class has name like 'default', 'events', etc. # endpoints view can have multiple tabs, the code below tries # to find right tab by passing endpoint name to endpoints view endp_view = getattr(self.endpoints_form(parent=add_view), endpoint_name) except AttributeError: # tabs are absent in UI when there is only single (default) endpoint endp_view = self.endpoints_form(parent=add_view) endp_view.fill(endpoint.view_value_mapping) # filling credentials if hasattr(endpoint, 'credentials'): endp_view.fill(endpoint.credentials.view_value_mapping) if (validate_credentials and hasattr(endp_view, 'validate') and endp_view.validate.is_displayed): # there are some endpoints which don't demand validation like # RSA key pair endp_view.validate.click() # Flash message widget is in add_view, not in endpoints tab logger.info( 'Validating credentials flash message for endpoint %s', endpoint_name) self._post_validate_checks(add_view) main_view = self.create_view(navigator.get_class(self, 'All').VIEW) if cancel: created = False add_view.cancel.click() self._post_cancel_checks(main_view) else: add_view.add.click() self._post_create_checks(main_view, add_view) if validate_inventory: self.validate() return created
def test_host_analysis_profile_crud(appliance, soft_assert, analysis_profile_collection): """CRUD for Host analysis profiles. Polarion: assignee: anikifor casecomponent: Configuration caseimportance: low initialEstimate: 1/12h """ host_profile = analysis_profile_collection.create( name=fauxfactory.gen_alphanumeric(), description=fauxfactory.gen_alphanumeric(), profile_type=analysis_profile_collection.HOST_TYPE, files=files_list, events=events_check() ) view = appliance.browser.create_view( navigator.get_class(analysis_profile_collection, 'All').VIEW) host_flash = host_profile.name if appliance.version < '5.10' else host_profile.description view.flash.assert_message('Analysis Profile "{}" was saved'.format(host_flash)) assert host_profile.exists files_updates = events_check(updates=True) with update(host_profile): host_profile.files = files_updates soft_assert(host_profile.files == files_updates, 'Files update failed on profile: {}, {}' .format(host_profile.name, host_profile.files)) copied_profile = host_profile.copy(new_name='copied-{}'.format(host_profile.name)) view = appliance.browser.create_view( navigator.get_class(analysis_profile_collection, 'All').VIEW) host_copied_flash = ( copied_profile.name if appliance.version < '5.10' else copied_profile.description ) view.flash.assert_message('Analysis Profile "{}" was saved'.format(host_copied_flash)) assert copied_profile.exists copied_profile.delete() assert not copied_profile.exists host_profile.delete() view.flash.assert_success_message('Analysis Profile "{}": Delete successful'.format(host_flash)) assert not host_profile.exists
def test_delete_compute_chargeback(chargeback_compute_rate): chargeback_compute_rate.create() assert chargeback_compute_rate.exists chargeback_compute_rate.delete() view = chargeback_compute_rate.create_view( navigator.get_class(chargeback_compute_rate, 'Details').VIEW) view.flash.assert_success_message( 'Chargeback Rate "{}": Delete successful'.format(chargeback_compute_rate.description)) assert not chargeback_compute_rate.exists
def test_chargeback_rate(rate_resource, rate_type, rate_action, request): """ Polarion: assignee: nachandr casecomponent: CandU initialEstimate: 1/4h """ cb_rate = chargeback_rate(rate_resource, rate_type, rate_action, request) cb_rate.create() view = cb_rate.create_view( navigator.get_class(cb_rate, 'All').VIEW) view.flash.assert_success_message( 'Chargeback Rate "{}" was added'.format(cb_rate.description)) assert cb_rate.exists if 'delete' in rate_action: cb_rate.delete() view = cb_rate.create_view( navigator.get_class(cb_rate, 'Details').VIEW) view.flash.assert_success_message( 'Chargeback Rate "{}": Delete successful'.format(cb_rate.description)) assert not cb_rate.exists if 'update' in rate_action: with update(cb_rate): cb_rate.description = '{}_edited'.format(cb_rate.description) if 'compute' in rate_action: cb_rate.fields = { 'Fixed Compute Cost 1': with_random_per_time(fixed_rate='500'), 'Allocated CPU Count': with_random_per_time(fixed_rate='100'), } elif 'storage' in rate_action: cb_rate.fields = { 'Fixed Storage Cost 1': with_random_per_time(fixed_rate='100'), 'Fixed Storage Cost 2': with_random_per_time(fixed_rate='200'), } view = cb_rate.create_view( navigator.get_class(cb_rate, 'Details').VIEW) view.flash.assert_success_message( 'Chargeback Rate "{}" was saved'.format(cb_rate.description)) assert cb_rate.exists
def test_delete_storage_chargeback(): storage_rate = chargeback_storage_rate() # TODO parametrize on variable storage_rate.create() assert storage_rate.exists storage_rate.delete() view = storage_rate.create_view( navigator.get_class(storage_rate, 'Details').VIEW) view.flash.assert_success_message( 'Chargeback Rate "{}": Delete successful'.format(storage_rate.description)) assert not storage_rate.exists
def unset_ownership(self): """Remove user ownership and return group to EvmGroup-Administrator""" view = navigate_to(self, 'SetOwnership') fill_result = view.form.fill({ 'user_name': '<No Owner>', 'group_name': 'EvmGroup-administrator' }) if fill_result: view.form.save_button.click() msg = 'Ownership saved for selected {}'.format(self.VM_TYPE) else: view.form.cancel_button.click() logger.warning('No change during unset_ownership') msg = 'Set Ownership was cancelled by the user' view = self.create_view(navigator.get_class(self, 'Details').VIEW) view.flash.assert_success_message(msg)
def delete(self, cancel=False): """ Delete existing category Args: cancel: Default value 'False', category will be deleted 'True' - deletion of category will be canceled """ view = navigate_to(self.parent, 'All') row = view.table.row(description=self.display_name) row.actions.click() view.browser.handle_alert(cancel=cancel) if not cancel: view = self.create_view( navigator.get_class(self.parent, 'All').VIEW) assert view.is_displayed view.flash.assert_no_error()
def delete(self, cancel=False): """ Delete existing user Args: cancel: Default value 'False', map will be deleted 'True' - map will not be deleted """ view = navigate_to(self.parent, 'All') row = view.table.row(tag_category=self.category, resource_label=self.label) row.actions.click() view.browser.handle_alert(cancel=cancel) if not cancel: view = self.create_view(navigator.get_class(self.parent, 'All').VIEW) assert view.is_displayed view.flash.assert_no_error()
def _method_setup(vm_names, provider_crud=None): """ Reduces some redundant code shared between methods """ if isinstance(vm_names, basestring): vm_names = [vm_names] if provider_crud: provider_crud.load_all_provider_vms() from cfme.utils.appliance import get_or_create_current_appliance app = get_or_create_current_appliance() view = app.browser.create_view(navigator.get_class(Vm, 'VMsOnly').VIEW) else: view = navigate_to(Vm, 'VMsOnly') if view.entities.paginator.exists: view.entities.paginator.set_items_per_page(1000) for vm_name in vm_names: view.entities.get_entity(vm_name).check()
def test_migration_special_char_name(request, appliance, v2v_providers, host_creds, conversion_tags, form_data_vm_obj_single_datastore): """Tests migration where name of migration plan is comprised of special non-alphanumeric characters, such as '@#$(&#@('.""" infrastructure_mapping_collection = appliance.collections.v2v_mappings mapping = infrastructure_mapping_collection.create(form_data_vm_obj_single_datastore.form_data) @request.addfinalizer def _cleanup(): infrastructure_mapping_collection.delete(mapping) src_vm_obj = form_data_vm_obj_single_datastore.vm_obj[0] wait_for(lambda: src_vm_obj.ip_address is not None, message="Waiting for VM to display IP in CFME", fail_func=src_vm_obj.refresh_relationships, delay=5, timeout=300) migration_plan_collection = appliance.collections.v2v_plans # fauxfactory.gen_special() used here to create special character string e.g. #$@#@ migration_plan = migration_plan_collection.create( name="{}".format(fauxfactory.gen_special()), description="desc_{}" .format(fauxfactory.gen_alphanumeric()), infra_map=mapping.name, vm_list=form_data_vm_obj_single_datastore.vm_obj, start_migration=True) # explicit wait for spinner of in-progress status card view = appliance.browser.create_view(navigator.get_class(migration_plan_collection, 'All').VIEW) wait_for(func=view.progress_card.is_plan_started, func_args=[migration_plan.name], message="migration plan is starting, be patient please", delay=5, num_sec=150, handle_exception=True) # wait until plan is in progress wait_for(func=view.plan_in_progress, func_args=[migration_plan.name], message="migration plan is in progress, be patient please", delay=5, num_sec=1800) view.migr_dropdown.item_select("Completed Plans") view.wait_displayed() logger.info("For plan %s, migration status after completion: %s, total time elapsed: %s", migration_plan.name, view.migration_plans_completed_list.get_vm_count_in_plan( migration_plan.name), view.migration_plans_completed_list.get_clock( migration_plan.name)) # validate MAC address matches between source and target VMs assert view.migration_plans_completed_list.is_plan_succeeded(migration_plan.name) src_vm = form_data_vm_obj_single_datastore.vm_obj[0] migrated_vm = get_migrated_vm_obj(src_vm, v2v_providers.rhv_provider) assert src_vm.mac_address == migrated_vm.mac_address
def test_dual_disk_vm_migration(request, appliance, v2v_providers, host_creds, conversion_tags, form_data_vm_obj_single_datastore): """ Polarion: assignee: kkulkarn casecomponent: V2V initialEstimate: None subcomponent: RHV upstream: yes """ infrastructure_mapping_collection = appliance.collections.v2v_mappings mapping = infrastructure_mapping_collection.create(form_data_vm_obj_single_datastore.form_data) @request.addfinalizer def _cleanup(): infrastructure_mapping_collection.delete(mapping) migration_plan_collection = appliance.collections.v2v_plans migration_plan = migration_plan_collection.create( name="plan_{}".format(fauxfactory.gen_alphanumeric()), description="desc_{}" .format(fauxfactory.gen_alphanumeric()), infra_map=mapping.name, vm_list=form_data_vm_obj_single_datastore.vm_list, start_migration=True) # explicit wait for spinner of in-progress status card view = appliance.browser.create_view( navigator.get_class(migration_plan_collection, 'All').VIEW.pick()) wait_for(func=view.progress_card.is_plan_started, func_args=[migration_plan.name], message="migration plan is starting, be patient please", delay=5, num_sec=150, handle_exception=True) # wait until plan is in progress wait_for(func=view.plan_in_progress, func_args=[migration_plan.name], message="migration plan is in progress, be patient please", delay=5, num_sec=3600) view.switch_to("Completed Plans") view.wait_displayed() migration_plan_collection.find_completed_plan(migration_plan) logger.info("For plan %s, migration status after completion: %s, total time elapsed: %s", migration_plan.name, view.migration_plans_completed_list.get_vm_count_in_plan( migration_plan.name), view.migration_plans_completed_list.get_clock( migration_plan.name)) assert view.migration_plans_completed_list.is_plan_succeeded(migration_plan.name) # validate MAC address matches between source and target VMs src_vm = form_data_vm_obj_single_datastore.vm_list.pop() migrated_vm = get_migrated_vm_obj(src_vm, v2v_providers.rhv_provider) assert src_vm.mac_address == migrated_vm.mac_address
def test_analysis_profile_name_validation(analysis_profile_collection): """ Test to validate profile name.""" with pytest.raises(AssertionError): analysis_profile_collection.create( name="", description=fauxfactory.gen_alphanumeric(), profile_type=analysis_profile_collection.HOST_TYPE, files=files_list) # Should still be on the form page after create method raises exception view = analysis_profile_collection.create_view( navigator.get_class(analysis_profile_collection, 'AddHostProfile').VIEW) assert view.is_displayed view.flash.assert_message("Name can't be blank") view.cancel.click()
def test_vmanalysis_profile_description_validation(analysis_profile_collection): """ Test to validate description in vm profiles""" with pytest.raises(AssertionError): analysis_profile_collection.create( name=fauxfactory.gen_alphanumeric(), description=None, profile_type=analysis_profile_collection.VM_TYPE, categories=categories_list ) # Should still be on the form page after create method raises exception view = analysis_profile_collection.create_view( navigator.get_class(analysis_profile_collection, 'AddVmProfile').VIEW ) assert view.is_displayed view.flash.assert_message("Description can't be blank") view.cancel.click()
def test_end_to_end_migration(appliance, v2v_providers, form_data_single_datastore, vm_list): infrastructure_mapping_collection = appliance.collections.v2v_mappings mapping = infrastructure_mapping_collection.create( form_data_single_datastore) coll = appliance.collections.v2v_plans coll.create(name="plan_{}".format(fauxfactory.gen_alphanumeric()), description="desc_{}".format(fauxfactory.gen_alphanumeric()), infra_map=mapping.name, vm_list=vm_list, start_migration=True) view = appliance.browser.create_view(navigator.get_class(coll, 'All').VIEW) # explicit wait for spinner of in-progress status card wait_for(lambda: bool(view.progress_bar.is_plan_started(coll.name)), message="migration plan is starting, be patient please", delay=5, num_sec=120) assert view._get_status(coll.name) == "Completed Plans"
def test_analysis_profile_item_validation(analysis_profile_collection): """ Test to validate analysis profile items.""" profile_name = fauxfactory.gen_alphanumeric() with pytest.raises(AssertionError): analysis_profile_collection.create( name=profile_name, description=profile_name, profile_type=analysis_profile_collection.HOST_TYPE) # Should still be on the form page after create method raises exception view = analysis_profile_collection.create_view( navigator.get_class(analysis_profile_collection, 'AddHostProfile').VIEW) assert view.is_displayed view.flash.assert_message( "At least one item must be entered to create Analysis Profile") view.cancel.click()
def create(self, name, display_name, description, show_in_console=True, single_value=True, capture_candu=False, cancel=False): """ Create category method Args: name: Name of the category display_name: Category display name description: Category description show_in_console: Option to show category in console (True/False) single_value: Option if category is single value (True/False) capture_candu: True/False, capture c&u data by tag cancel: To cancel creation pass True, cancellation message will be verified By default user will be created """ view = navigate_to(self, 'Add') view.fill({ 'name': name, 'display_name': display_name, 'long_description': description, 'show_in_console': show_in_console, 'single_value': single_value, 'capture_candu': capture_candu, }) if cancel: view.cancel_button.click() else: view.add_button.click() view = self.create_view(navigator.get_class(self, 'All').VIEW) assert view.is_displayed view.flash.assert_no_error() return self.instantiate(display_name=display_name, name=name, description=description, show_in_console=show_in_console, single_value=single_value, capture_candu=capture_candu)
def _assign_unassign_policy_profiles(self, assign, *policy_profile_names): """DRY function for managing policy profiles. See :py:func:`assign_policy_profiles` and :py:func:`assign_policy_profiles` Args: assign: Wheter to assign or unassign. policy_profile_names: :py:class:`str` with Policy Profile names. """ view = navigate_to(self, 'ManagePoliciesFromDetails') for policy_profile in policy_profile_names: if assign: view.policy_profiles.check_node(policy_profile) else: view.policy_profiles.uncheck_node(policy_profile) view.save.click() details_view = self.create_view(navigator.get_class(self, 'Details').VIEW) details_view.flash.assert_no_error()
def verify_retirement_state(retire_vm): """Verify the vm/instance is in the 'retired' state in the UI and assert its power state Args: retire_vm: vm/instance object """ # wait for the info block showing a date as retired date # Use lambda for is_retired since its a property view_cls = navigator.get_class(retire_vm, 'Details').VIEW view = retire_vm.appliance.browser.create_view(view_cls) assert wait_for( lambda: retire_vm.is_retired, delay=5, num_sec=15 * 60, fail_func=view.toolbar.reload.click, message="Wait for VM '{}' to enter retired state".format(retire_vm.name) ) retirement_states = ['off', 'suspended', 'unknown', 'terminated'] view = retire_vm.load_details() assert view.entities.summary('Power Management').get_text_of('Power State') in retirement_states
def test_instance_attach_volume(volume, new_instance, appliance): """ Polarion: assignee: mnadeem initialEstimate: 1/4h """ initial_volume_count = new_instance.volume_count new_instance.attach_volume(volume.name) view = appliance.browser.create_view( navigator.get_class(new_instance, 'AttachVolume').VIEW) view.flash.assert_success_message( 'Attaching Cloud Volume "{}" to {} finished'.format( volume.name, new_instance.name)) wait_for(lambda: new_instance.volume_count > initial_volume_count, delay=20, timeout=300, message="Waiting for volume to be attached to instance", fail_func=new_instance.refresh_relationships)
def test_retirement_now_ec2_instance_backed(retire_ec2_s3_vm, tagged, appliance): """Tests on-demand retirement of an instance/vm S3 (instance-backed) EC2 instances that aren't lifecycle tagged won't get shut down Polarion: assignee: tpapaioa casecomponent: Provisioning initialEstimate: 1/6h """ # Tag the VM with lifecycle for full retirement based on parameter if tagged: retire_ec2_s3_vm.add_tag( appliance.collections.categories.instantiate( display_name='Fully retire VM and remove from Provider'). collections.tags.instantiate(display_name='LifeCycle')) expected_power_state = ['terminated'] else: # no tagging expected_power_state = ['on'] # For 5.7+ capture two times to assert the retire time is within a window. # Too finicky to get it down to minute precision, nor is it really needed here retire_times = dict() retire_times['start'] = generate_retirement_date_now() + timedelta( minutes=-5) retire_ec2_s3_vm.retire() view_cls = navigator.get_class(retire_ec2_s3_vm, 'Details').VIEW reload = retire_ec2_s3_vm.appliance.browser.create_view( view_cls).toolbar.reload assert wait_for(lambda: retire_ec2_s3_vm.is_retired, delay=5, num_sec=10 * 60, fail_func=reload.click, message="Wait for VM '{}' to enter retired state".format( retire_ec2_s3_vm.name)) view = retire_ec2_s3_vm.load_details() assert view.entities.power_management.get_text_of( 'Power State') in expected_power_state retire_times['end'] = generate_retirement_date_now() + timedelta(minutes=5) verify_retirement_date(retire_ec2_s3_vm, expected_date=retire_times)
def test_analysis_profile_description_validation(analysis_profile_collection): """ Test to validate profile description. Polarion: assignee: anikifor initialEstimate: 1/4h """ with pytest.raises(AssertionError): analysis_profile_collection.create( name=fauxfactory.gen_alphanumeric(), description="", profile_type=analysis_profile_collection.HOST_TYPE, files=files_list) # Should still be on the form page after create method raises exception view = analysis_profile_collection.create_view(navigator.get_class( analysis_profile_collection, 'AddHostProfile').VIEW, wait='10s') view.flash.assert_message("Description can't be blank") view.cancel.click()
def test_category_crud(appliance, soft_assert): """ Polarion: assignee: anikifor casecomponent: config caseimportance: low initialEstimate: 1/15h """ cg = appliance.collections.categories.create( name=fauxfactory.gen_alphanumeric(8).lower(), description=fauxfactory.gen_alphanumeric(32), display_name=fauxfactory.gen_alphanumeric(32) ) view = appliance.browser.create_view(navigator.get_class(cg.parent, 'All').VIEW) soft_assert(view.flash.assert_message('Category "{}" was added'.format(cg.display_name))) with update(cg): cg.description = fauxfactory.gen_alphanumeric(32) soft_assert(view.flash.assert_message('Category "{}" was saved'.format(cg.name))) cg.delete() soft_assert(view.flash.assert_message('Category "{}": Delete successful'.format(cg.name)))
def test_analysis_profile_duplicate_name(analysis_profile_collection): """ Test to validate duplicate profiles name.""" profile = analysis_profile_collection.create( name=fauxfactory.gen_alphanumeric(), description=fauxfactory.gen_alphanumeric(), profile_type=analysis_profile_collection.VM_TYPE, categories=categories_list) with pytest.raises(AssertionError): analysis_profile_collection.create( name=profile.name, description=profile.description, profile_type=analysis_profile_collection.VM_TYPE, categories=profile.categories) # Should still be on the form page after create method raises exception view = analysis_profile_collection.create_view( navigator.get_class(analysis_profile_collection, 'AddVmProfile').VIEW) assert view.is_displayed view.flash.assert_message("Name has already been taken") view.cancel.click()
def update(self, updates, cancel=False): """ Update tag map method Args: updates: tag map data that should be changed cancel: True - if you want to cancel map edition, by default map will be updated """ view = navigate_to(self, 'Edit') # only category can be updated, as other fields disabled by default view.fill({'category': updates.get('category')}) if cancel: view.cancel_button.click() else: view.save_button.click() view = self.create_view(navigator.get_class(self.parent, 'All').VIEW, override=updates) assert view.is_displayed view.flash.assert_no_error()
def test_crud_service_dialog(appliance): element_data = { 'element_information': { 'ele_label': "ele_" + fauxfactory.gen_alphanumeric(), 'ele_name': fauxfactory.gen_alphanumeric(), 'ele_desc': fauxfactory.gen_alphanumeric(), 'choose_type': "Text Box" }, 'options': { 'default_text_box': "Default text" } } dialog, element = create_dialog(appliance, element_data) view_cls = navigator.get_class(element.parent, 'Add').VIEW view = element.appliance.browser.create_view(view_cls) flash_message = '{} was saved'.format(dialog.label) view.flash.assert_message(flash_message) with update(dialog): dialog.description = "my edited description" dialog.delete()
def test_set_retirement_offset_multiple(create_vms, provider, warn): """Test setting the retirement date of multiple VMs/Instances using 'Time Delay from Now' option. Verify the selected retirement date is reflected in each VM's/Instance's Details page. Polarion: assignee: tpapaioa casecomponent: Provisioning initialEstimate: 1/6h """ retire_offset = {'months': 0, 'weeks': 2, 'days': 1, 'hours': 3} timedelta_offset = retire_offset.copy() timedelta_offset.pop('months') # months not supported in timedelta expected_date = {} # Pad pre-retirement timestamp by 60s. expected_date['start'] = datetime.utcnow() + timedelta(seconds=-60, **timedelta_offset) collection = create_vms[0].parent collection.set_retirement_date(entities=create_vms, offset=retire_offset, warn=warn.string) # Pad post-retirement timestamp by 60s. expected_date['end'] = datetime.utcnow() + timedelta(seconds=60, **timedelta_offset) # Verify flash message view = collection.create_view(navigator.get_class(collection, 'All').VIEW, wait='5s') assert view.is_displayed msg_dates = msg_date_range(expected_date, create_vms[0].RETIRE_DATE_MSG_FMT) flash_regex = re.compile(f"^Retirement dates set to ({msg_dates})$") view.flash.assert_success_message(flash_regex) for vm in create_vms: verify_retirement_date(vm, expected_date=expected_date)
def test_single_datastore_single_vm_migration(request, appliance, v2v_providers, host_creds, conversion_tags, form_data_vm_obj_single_datastore): infrastructure_mapping_collection = appliance.collections.v2v_mappings mapping = infrastructure_mapping_collection.create(form_data_vm_obj_single_datastore.form_data) @request.addfinalizer def _cleanup(): infrastructure_mapping_collection.delete(mapping) # vm_obj is a list, with only 1 VM object, hence [0] src_vm_obj = form_data_vm_obj_single_datastore.vm_list[0] migration_plan_collection = appliance.collections.v2v_plans migration_plan = migration_plan_collection.create( name="plan_{}".format(fauxfactory.gen_alphanumeric()), description="desc_{}" .format(fauxfactory.gen_alphanumeric()), infra_map=mapping.name, vm_list=form_data_vm_obj_single_datastore.vm_list, start_migration=True) # explicit wait for spinner of in-progress status card view = appliance.browser.create_view(navigator.get_class(migration_plan_collection, 'All').VIEW) wait_for(func=view.progress_card.is_plan_started, func_args=[migration_plan.name], message="migration plan is starting, be patient please", delay=5, num_sec=150, handle_exception=True) # wait until plan is in progress wait_for(func=view.plan_in_progress, func_args=[migration_plan.name], message="migration plan is in progress, be patient please", delay=5, num_sec=1800) view.migr_dropdown.item_select("Completed Plans") view.wait_displayed() logger.info("For plan %s, migration status after completion: %s, total time elapsed: %s", migration_plan.name, view.migration_plans_completed_list.get_vm_count_in_plan( migration_plan.name), view.migration_plans_completed_list.get_clock( migration_plan.name)) # validate MAC address matches between source and target VMs assert view.migration_plans_completed_list.is_plan_succeeded(migration_plan.name) migrated_vm = get_migrated_vm_obj(src_vm_obj, v2v_providers.rhv_provider) assert src_vm_obj.mac_address == migrated_vm.mac_address
def test_vmanalysis_profile_description_validation(analysis_profile_collection): """ Test to validate description in vm profiles Polarion: assignee: anikifor casecomponent: Configuration caseimportance: low initialEstimate: 1/20h """ with pytest.raises(AssertionError): analysis_profile_collection.create( name=fauxfactory.gen_alphanumeric(), description=None, profile_type=analysis_profile_collection.VM_TYPE, categories=categories_list ) # Should still be on the form page after create method raises exception view = analysis_profile_collection.create_view( navigator.get_class(analysis_profile_collection, 'AddVmProfile').VIEW, wait='10s' ) view.flash.assert_message("Description can't be blank") view.cancel.click()
def test_analysis_profile_name_validation(analysis_profile_collection): """ Test to validate profile name. Polarion: assignee: tpapaioa casecomponent: Configuration caseimportance: low initialEstimate: 1/20h """ with pytest.raises(AssertionError): analysis_profile_collection.create( name="", description=fauxfactory.gen_alphanumeric(), profile_type=analysis_profile_collection.HOST_TYPE, files=files_list) # Should still be on the form page after create method raises exception view = analysis_profile_collection.create_view(navigator.get_class( analysis_profile_collection, 'AddHostProfile').VIEW, wait='10s') view.flash.assert_message("Name can't be blank") view.cancel.click()
def private_flavor(appliance, provider): prov_data = provider.data['provisioning'] collection = appliance.collections.cloud_flavors private_flavor = collection.create(name=fauxfactory.gen_alpha(), provider=provider, ram=RAM, vcpus=VCPUS, disk=DISK_SIZE, swap=SWAP_SIZE, rxtx=RXTX, is_public=False, tenant=prov_data['cloud_tenant']) view = appliance.browser.create_view(navigator.get_class(collection, 'All').VIEW) view.flash.assert_success_message( 'Add of Flavor "{}" was successfully initialized.'.format(private_flavor.name)) wait_for(lambda: private_flavor.exists, delay=5, timeout=600, fail_func=private_flavor.refresh, message='Wait for flavor to appear') yield private_flavor if private_flavor.exists: private_flavor.delete()
def test_analysis_profile_item_validation(analysis_profile_collection): """ Test to validate analysis profile items. Polarion: assignee: anikifor casecomponent: Configuration caseimportance: low initialEstimate: 1/15h """ profile_name = fauxfactory.gen_alphanumeric() with pytest.raises(AssertionError): analysis_profile_collection.create( name=profile_name, description=profile_name, profile_type=analysis_profile_collection.HOST_TYPE ) # Should still be on the form page after create method raises exception view = analysis_profile_collection.create_view( navigator.get_class(analysis_profile_collection, 'AddHostProfile').VIEW, wait='10s' ) view.flash.assert_message("At least one item must be entered to create Analysis Profile") view.cancel.click()
def test_set_retirement_date_multiple(retire_vm_pair, provider, warn): """Tests setting retirement date of multiple VMs, verifies configured date is reflected in individual VM Details pages. Polarion: assignee: tpapaioa casecomponent: Provisioning initialEstimate: 1/6h """ num_days = 60 retire_date = generate_retirement_date(delta=num_days) # Set retirement date from All VMs/Instances page collection = retire_vm_pair[0].parent collection.set_retirement_date(retire_vm_pair, when=retire_date, warn=warn.string) # Verify flash message view = collection.create_view(navigator.get_class(collection, 'All').VIEW, wait='5s') assert view.is_displayed msg_date = retire_date.strftime('%m/%d/%y %H:%M UTC') view.flash.assert_success_message(f"Retirement dates set to {msg_date}") verify_retirement_date(retire_vm_pair[0], expected_date=retire_date) verify_retirement_date(retire_vm_pair[1], expected_date=retire_date)
def create(self, cancel=False, validate_credentials=True, check_existing=False, validate_inventory=False): """ Creates a provider in the UI Args: cancel (boolean): Whether to cancel out of the creation. The cancel is done after all the information present in the Provider has been filled in the UI. validate_credentials (boolean): Whether to validate credentials - if True and the credentials are invalid, an error will be raised. check_existing (boolean): Check if this provider already exists, skip if it does validate_inventory (boolean): Whether or not to block until the provider stats in CFME match the stats gleaned from the backend management system (default: ``True``) Returns: True if it was created, False if it already existed """ if check_existing and self.exists: created = False else: created = True logger.info('Setting up Infra Provider: %s', self.key) add_view = navigate_to(self, 'Add') if not cancel or (cancel and any(self.view_value_mapping.values())): # filling main part of dialog add_view.fill(self.view_value_mapping) if not cancel or (cancel and self.endpoints): # filling endpoints for endpoint_name, endpoint in self.endpoints.items(): try: # every endpoint class has name like 'default', 'events', etc. # endpoints view can have multiple tabs, the code below tries # to find right tab by passing endpoint name to endpoints view endp_view = getattr( self.endpoints_form(parent=add_view), endpoint_name) except AttributeError: # tabs are absent in UI when there is only single (default) endpoint endp_view = self.endpoints_form(parent=add_view) endp_view.fill(endpoint.view_value_mapping) # filling credentials if hasattr(endpoint, 'credentials'): endp_view.fill(endpoint.credentials.view_value_mapping) # sometimes we have cases that we need to validate even though # there is no credentials, such as Hawkular endpoint if (validate_credentials and hasattr(endp_view, 'validate') and endp_view.validate.is_displayed): # there are some endpoints which don't demand validation like # RSA key pair endp_view.validate.click() # Flash message widget is in add_view, not in endpoints tab logger.info( 'Validating credentials flash message for endpoint %s', endpoint_name) add_view.flash.assert_no_error() add_view.flash.assert_success_message( 'Credential validation was successful') main_view = self.create_view(navigator.get_class(self, 'All').VIEW) if cancel: created = False add_view.cancel.click() cancel_text = ('Add of {} Provider was ' 'cancelled by the user'.format( self.string_name)) main_view.entities.flash.assert_message(cancel_text) main_view.entities.flash.assert_no_error() else: add_view.add.click() if main_view.is_displayed: success_text = '{} Providers "{}" was saved'.format( self.string_name, self.name) main_view.entities.flash.assert_message(success_text) else: add_view.flash.assert_no_error() raise AssertionError( "Provider wasn't added. It seems form isn't accurately" " filled") if validate_inventory: self.validate() return created
def update(self, updates, cancel=False, validate_credentials=True): """ Updates a provider in the UI. Better to use utils.update.update context manager than call this directly. Args: updates (dict): fields that are changing. cancel (boolean): whether to cancel out of the update. validate_credentials (boolean): whether credentials have to be validated """ edit_view = navigate_to(self, 'Edit') # todo: to replace/merge this code with create # update values: # filling main part of dialog endpoints = updates.pop('endpoints', None) if updates: edit_view.fill(updates) # filling endpoints if endpoints: endpoints = self._prepare_endpoints(endpoints) for endpoint in endpoints.values(): # every endpoint class has name like 'default', 'events', etc. # endpoints view can have multiple tabs, the code below tries # to find right tab by passing endpoint name to endpoints view try: endp_view = getattr(self.endpoints_form(parent=edit_view), endpoint.name) except AttributeError: # tabs are absent in UI when there is only single (default) endpoint endp_view = self.endpoints_form(parent=edit_view) endp_view.fill(endpoint.view_value_mapping) # filling credentials # the code below looks for existing endpoint equal to passed one and # compares their credentials. it fills passed credentials # if credentials are different cur_endpoint = self.endpoints[endpoint.name] if hasattr(endpoint, 'credentials'): if not hasattr(cur_endpoint, 'credentials') or \ endpoint.credentials != cur_endpoint.credentials: if hasattr(endp_view, 'change_password'): endp_view.change_password.click() elif hasattr(endp_view, 'change_key'): endp_view.change_key.click() else: NotImplementedError( "Such endpoint doesn't have change password/key button" ) endp_view.fill(endpoint.credentials.view_value_mapping) # sometimes we have cases that we need to validate even though # there is no credentials, such as Hawkular endpoint if (validate_credentials and hasattr(endp_view, 'validate') and endp_view.validate.is_displayed): endp_view.validate.click() # cloud rhos provider always requires validation of all endpoints # there should be a bz about that from cfme.cloud.provider.openstack import OpenStackProvider if self.one_of(OpenStackProvider): for endp in self.endpoints.values(): endp_view = getattr(self.endpoints_form(parent=edit_view), endp.name) if hasattr(endp_view, 'validate') and endp_view.validate.is_displayed: endp_view.validate.click() details_view = self.create_view( navigator.get_class(self, 'Details').VIEW) main_view = self.create_view(navigator.get_class(self, 'All').VIEW) if cancel: edit_view.cancel.click() cancel_text = 'Edit of {type} Provider "{name}" ' \ 'was cancelled by the user'.format(type=self.string_name, name=self.name) main_view.entities.flash.assert_message(cancel_text) main_view.entities.flash.assert_no_error() else: edit_view.save.click() if endpoints: for endp_name, endp in endpoints.items(): self.endpoints[endp_name] = endp if updates: self.name = updates.get('name', self.name) success_text = '{} Provider "{}" was saved'.format( self.string_name, self.name) if main_view.is_displayed: # since 5.8.1 main view is displayed when edit starts from main view main_view.flash.assert_message(success_text) elif details_view.is_displayed: # details view is always displayed up to 5.8.1 details_view.flash.assert_message(success_text) else: edit_view.flash.assert_no_error() raise AssertionError( "Provider wasn't updated. It seems form isn't accurately" " filled")
def test_migration_policy_tag(request, appliance, v2v_providers, host_creds, conversion_tags, form_data_vm_obj_single_datastore, soft_assert): """Test policy to prevent source VM from starting if migration is complete Polarion: assignee: None initialEstimate: None """ infrastructure_mapping_collection = appliance.collections.v2v_mappings mapping = infrastructure_mapping_collection.create( form_data_vm_obj_single_datastore.form_data) @request.addfinalizer def _cleanup(): infrastructure_mapping_collection.delete(mapping) migration_plan_collection = appliance.collections.v2v_plans # vm_obj is a list, with only 1 VM object, hence [0] vm_obj = form_data_vm_obj_single_datastore.vm_list[0] migration_plan = migration_plan_collection.create( name="plan_{}".format(fauxfactory.gen_alphanumeric()), description="desc_{}".format(fauxfactory.gen_alphanumeric()), infra_map=mapping.name, vm_list=form_data_vm_obj_single_datastore.vm_list, start_migration=True, ) # explicit wait for spinner of in-progress status card view = appliance.browser.create_view( navigator.get_class(migration_plan_collection, "All").VIEW.pick()) wait_for( func=view.progress_card.is_plan_started, func_args=[migration_plan.name], message="migration plan is starting, be patient please", delay=5, num_sec=150, handle_exception=True, ) # wait until plan is in progress wait_for( func=view.plan_in_progress, func_args=[migration_plan.name], message="migration plan is in progress, be patient please", delay=15, num_sec=3600, ) view.switch_to("Completed Plans") view.wait_displayed() migration_plan_collection.find_completed_plan(migration_plan) logger.info( "For plan {plan_name}, migration status : {count}, total time elapsed: {clock}" .format(plan_name=migration_plan.name, count=view.migration_plans_completed_list.get_vm_count_in_plan( migration_plan.name), clock=view.migration_plans_completed_list.get_clock( migration_plan.name))) available_tags = vm_obj.get_tags() soft_assert("Migrated" in [tag.display_name for tag in available_tags]) vm_obj.wait_for_vm_state_change(desired_state=vm_obj.STATE_OFF, timeout=720) vm_obj.power_control_from_cfme(option=vm_obj.POWER_ON, cancel=False) view = appliance.browser.create_view(BaseLoggedInPage) view.flash.assert_success_message(text="Start initiated", partial=True) try: vm_obj.wait_for_vm_state_change(desired_state=vm_obj.STATE_ON, timeout=120) except TimedOutError: pass vm_state = vm_obj.find_quadicon().data["state"] soft_assert(vm_state == "off")