'5.5': Table('//div[@id="list_grid"]/table'), '5.4': SplitTable( ('//*[@id="list_grid"]//table[contains(@class, "hdr")]/tbody', 1), ('//*[@id="list_grid"]//table[contains(@class, "obj")]/tbody', 1)) }) edit_tags_form = Form(fields=[( "select_tag", ui.Select("select#tag_cat")), ("select_value", ui.Select("select#tag_add"))]) nav.add_branch('clouds_stacks', { 'clouds_stack': lambda ctx: sel.click(Quadicon(ctx['stack'].name, 'stack')) }) class Stack(Pretty): pretty_attrs = ['name'] def __init__(self, name=None): self.name = name def delete(self): sel.force_navigate('clouds_stack', context={'stack': self}) cfg_btn("Remove this Stack from the VMDB", invokes_alert=True) sel.handle_alert() flash.assert_success_message( 'The selected Orchestration Stack was deleted')
def nav_to_cluster_through_provider(context): sel.force_navigate('infrastructure_provider', context=context) list_acc.select('Relationships', 'Clusters', by_title=False, partial=True) sel.click(Quadicon(context['cluster'].name, 'cluster'))
def step(self): list_acc.select('Relationships', 'Datastores', by_title=False, partial=True) sel.click(Quadicon(self.obj.name, self.obj.quad_name))
def nav_to_datastore_through_provider(context): sel.force_navigate('infrastructure_provider', context=context) list_acc.select('Relationships', 'Show all managed Datastores') sel.click(Quadicon(context['datastore'].name, 'datastore'))
from cfme.web_ui import Quadicon, Region, toolbar as tb from functools import partial from utils.pretty import Pretty from utils.providers import get_crud from utils.wait import wait_for details_page = Region(infoblock_type='detail') cfg_btn = partial(tb.select, 'Configuration') pol_btn = partial(tb.select, 'Policy') nav.add_branch( 'infrastructure_resource_pools', { 'infrastructure_resource_pool': lambda ctx: sel.click( Quadicon(ctx['resource_pool'].name, 'resource_pool')) }) class ResourcePool(Pretty): """ Model of an infrastructure Resource pool in cfme Args: name: Name of the Resource pool. provider_key: Name of the provider this resource pool is attached to. Note: If given a provider_key, it will navigate through ``Infrastructure/Providers`` instead of the direct path through ``Infrastructure/Resourcepool``. """ pretty_attrs = ['name', 'provider_key']
('infra_provider', { version.LOWEST: None, "5.4": Select("select#provider_id"), "5.5": AngularSelect("provider_id")}), ]) details_page = Region(infoblock_type='detail') cfg_btn = partial(tb.select, 'Configuration') pol_btn = partial(tb.select, 'Policy') mon_btn = partial(tb.select, 'Monitoring') nav.add_branch('clouds_providers', {'clouds_provider_new': lambda _: cfg_btn('Add a New Cloud Provider'), 'clouds_provider_discover': lambda _: cfg_btn('Discover Cloud Providers'), 'clouds_provider': [lambda ctx: sel.click(Quadicon(ctx['provider'].name, 'cloud_prov')), {'clouds_provider_edit': lambda _: cfg_btn('Edit this Cloud Provider'), 'clouds_provider_policy_assignment': lambda _: pol_btn('Manage Policies'), 'cloud_provider_timelines': lambda _: mon_btn('Timelines')}]}) class Provider(Pretty, CloudInfraProvider): """ Abstract model of a cloud provider in cfme. See EC2Provider or OpenStackProvider. Args: name: Name of the provider. details: a details record (see EC2Details, OpenStackDetails inner class).
nav.add_branch( 'infrastructure_config_management', { 'infrastructure_config_managers': [ lambda _: (accordion.tree( 'Providers', version.pick({ version.LOWEST: 'All Red Hat Satellite Providers', version.UPSTREAM: 'All Foreman Providers' })), toolbar.set_vms_grid_view()), { 'infrastructure_config_manager_new': lambda _: cfg_btn('Add a new Provider'), 'infrastructure_config_manager': [ lambda ctx: sel.check( Quadicon( '{} Configuration Manager'. format(ctx['manager'].name), None).checkbox), { 'infrastructure_config_manager_edit': lambda _: cfg_btn('Edit Selected item'), 'infrastructure_config_manager_refresh': lambda _: cfg_btn( 'Refresh Relationships and Power states', invokes_alert=True), 'infrastructure_config_manager_remove': lambda _: cfg_btn( 'Remove selected items from the VMDB', invokes_alert=True) } ], 'infrastructure_config_manager_detail': [ lambda ctx: sel.click(
def test_run_datastore_analysis(request, setup_provider, provider, datastore, soft_assert): """Tests smarthost analysis Metadata: test_flag: datastore_analysis """ # Check if there is a host with valid credentials host_names = datastore.get_hosts() assert len(host_names) != 0, "No hosts attached to this datastore found" for host_name in host_names: host_qi = Quadicon(host_name, 'host') if 'checkmark' in host_qi.creds: break else: # If not, get credentials for one of the present hosts found_host = False for host_name in host_names: host_data = get_host_data_by_name(provider.key, host_name) if host_data is None: continue found_host = True test_host = host.Host(name=host_name) # Add them to the host wait_for(lambda: test_host.exists, delay=10, num_sec=120, fail_func=sel.refresh) if not test_host.has_valid_credentials: test_host.update( updates={ 'credentials': host.get_credentials_from_config( host_data['credentials']) }) wait_for(lambda: test_host.has_valid_credentials, delay=10, num_sec=120, fail_func=sel.refresh) # And remove them again when the test is finished def test_host_remove_creds(): test_host.update( updates={ 'credentials': host.Host.Credential( principal="", secret="", verify_secret="") }) request.addfinalizer(test_host_remove_creds) break assert found_host,\ "No credentials found for any of the hosts attached to datastore {}"\ .format(datastore.name) # TODO add support for events # register_event( # None, # "datastore", # datastore_name, # ["datastore_analysis_request_req", "datastore_analysis_complete_req"] # ) # Initiate analysis datastore.run_smartstate_analysis() wait_for(lambda: is_datastore_analysis_finished(datastore.name), delay=15, timeout="10m", fail_func=lambda: toolbar.select('Reload')) c_datastore = datastore.get_detail('Properties', 'Datastore Type') # Check results of the analysis and the datastore type soft_assert( c_datastore == datastore.type.upper(), 'Datastore type does not match the type defined in yaml:' + 'expected "{}" but was "{}"'.format(datastore.type.upper(), c_datastore)) for row_name in CONTENT_ROWS_TO_CHECK: value = InfoBlock('Content', row_name).text soft_assert(value != '0', 'Expected value for {} to be non-empty'.format(row_name))
def test_run_datastore_analysis(request, setup_provider, provider, datastore_type, datastore_name): """Tests smarthost analysis Metadata: test_flag: datastore_analysis """ test_datastore = datastore.Datastore(datastore_name, provider.key) # Check if there is a host with valid credentials host_names = test_datastore.get_hosts() assert len(host_names) != 0, "No hosts attached to this datastore found" for host_name in host_names: host_qi = Quadicon(host_name, 'host') if host_qi.creds == 'checkmark': break else: # If not, get credentials for one of the present hosts found_host = False for host_name in host_names: host_data = get_host_data_by_name(provider.key, host_name) if host_data is None: continue found_host = True test_host = host.Host(name=host_name) # Add them to the host wait_for(lambda: test_host.exists, delay=10, num_sec=120, fail_func=sel.refresh) if not test_host.has_valid_credentials: test_host.update( updates={ 'credentials': host.get_credentials_from_config(host_data['credentials'])} ) wait_for( lambda: test_host.has_valid_credentials, delay=10, num_sec=120, fail_func=sel.refresh ) # And remove them again when the test is finished def test_host_remove_creds(): test_host.update( updates={ 'credentials': host.Host.Credential( principal="", secret="", verify_secret="" ) } ) request.addfinalizer(test_host_remove_creds) break assert found_host,\ "No credentials found for any of the hosts attached to datastore {}"\ .format(datastore_name) # TODO add support for events # register_event( # None, # "datastore", # datastore_name, # ["datastore_analysis_request_req", "datastore_analysis_complete_req"] # ) # Initiate analysis sel.force_navigate('infrastructure_datastore', context={ 'datastore': test_datastore, 'provider': test_datastore.provider }) tb.select('Configuration', 'Perform SmartState Analysis', invokes_alert=True) sel.handle_alert() flash.assert_message_contain('"{}": scan successfully initiated'.format(datastore_name)) # Wait for the task to finish def is_datastore_analysis_finished(): """ Check if analysis is finished - if not, reload page """ if not sel.is_displayed(tasks.tasks_table) or not tabs.is_tab_selected('All Other Tasks'): sel.force_navigate('tasks_all_other') host_analysis_finished = tasks.tasks_table.find_row_by_cells({ 'task_name': "SmartState Analysis for [{}]".format(datastore_name), 'state': 'Finished' }) return host_analysis_finished is not None wait_for( is_datastore_analysis_finished, delay=10, num_sec=300, fail_func=lambda: tb.select('Reload') ) # Delete the task tasks.tasks_table.select_row_by_cells({ 'task_name': "SmartState Analysis for [{}]".format(datastore_name), 'state': 'Finished' }) tb.select('Delete Tasks', 'Delete', invokes_alert=True) sel.handle_alert() # Check results of the analysis and the datastore type assert test_datastore.get_detail('Properties', 'Datastore Type') == datastore_type.upper(),\ 'Datastore type does not match the type defined in yaml' for row_name in CONTENT_ROWS_TO_CHECK: assert test_datastore.get_detail('Content', row_name) != '0',\ '{} in Content infoblock should not be 0'.format(row_name)
def step(self): sel.check(Quadicon(self.obj.name, self.obj.quad_name).checkbox()) pol_btn('Manage Policies')
def step(self): sel.check(Quadicon(self.obj.name, self.obj.quad_name).checkbox()) cfg = self.prerequisite_view.toolbar.configuration cfg.item_select('Edit Selected Infrastructure Providers')
def _wait_f(): navigate_to(self, 'All') q = Quadicon(self.name, self.quad_name) creds = q.creds return "checkmark" in creds
version.LOWEST: "//div[@id='treebox']/div/table", "5.3": "//div[@id='protect_treebox']/ul" }) cfg_btn = partial(tb.select, 'Configuration') pol_btn = partial(tb.select, 'Policy') mon_btn = partial(tb.select, 'Monitoring') nav.add_branch( 'infrastructure_providers', { 'infrastructure_provider_new': lambda _: cfg_btn('Add a New Infrastructure Provider'), 'infrastructure_provider_discover': lambda _: cfg_btn('Discover Infrastructure Providers'), 'infrastructure_provider': [ lambda ctx: sel.click(Quadicon(ctx[ 'provider'].name, 'infra_prov')), { 'infrastructure_provider_edit': lambda _: cfg_btn('Edit this Infrastructure Provider'), 'infrastructure_provider_policy_assignment': lambda _: pol_btn('Manage Policies'), 'infrastructure_provider_timelines': lambda _: mon_btn('Timelines') } ] }) class Provider(Pretty, CloudInfraProvider): """ Abstract model of an infrastructure provider in cfme. See VMwareProvider or RHEVMProvider.
def wait_for_provider_delete(provider): sel.force_navigate('clouds_providers') quad = Quadicon(provider.name, 'cloud_prov') logger.info('Waiting for a provider to delete...') wait_for(lambda prov: not sel.is_displayed(prov), func_args=[quad], fail_condition=False, message="Wait provider to disappear", num_sec=1000, fail_func=sel.refresh)
def wait_for_host_to_appear(host): sel.force_navigate('infrastructure_hosts') quad = Quadicon(host.name, 'host') logger.info('Waiting for a host to appear...') wait_for(sel.is_displayed, func_args=[quad], fail_condition=False, message="Wait host to appear", num_sec=1000, fail_func=sel.refresh)
def exists(self): """Returns whether the manager exists in the UI or not""" navigate_to(self, 'All') if (Quadicon.any_present() and Quadicon(self.quad_name, None).exists): return True return False
})) host_add_btn = FormButton('Add this Host') cfg_btn = partial(tb.select, 'Configuration') pol_btn = partial(tb.select, 'Policy') pow_btn = partial(tb.select, 'Power') nav.add_branch( 'infrastructure_hosts', { 'infrastructure_host_new': lambda _: cfg_btn('Add a New Host'), 'infrastructure_host_discover': lambda _: cfg_btn('Discover Hosts'), 'infrastructure_host': [ lambda ctx: sel.click(Quadicon(ctx['host'].name, 'host')), { 'infrastructure_host_edit': lambda _: cfg_btn('Edit this Host'), 'infrastructure_host_policy_assignment': lambda _: pol_btn('Manage Policies') } ] }) class Host(Updateable): """ Model of an infrastructure host in cfme. Args: name: Name of the host.
def step(self): sel.check(Quadicon(self.obj.quad_name, None).checkbox()) cfg_btn('Edit Selected item')
toolbar as tb, InfoBlock) from cfme.web_ui.menu import nav from utils.browser import ensure_browser_open from utils.db import cfmedb from utils.pretty import Pretty from utils.varmeth import variable from . import cfg_btn, mon_btn, pol_btn, details_page nav.add_branch( 'containers_providers', { 'containers_provider_new': lambda _: cfg_btn('Add a New Containers Provider'), 'containers_provider': [ lambda ctx: sel.check( Quadicon(ctx['provider'].name, None).checkbox), { 'containers_provider_edit': lambda _: cfg_btn('Edit Selected Containers Provider'), 'containers_provider_edit_tags': lambda _: pol_btn('Edit Tags') } ], 'containers_provider_detail': [ lambda ctx: sel.click(Quadicon(ctx['provider'].name, None)), { 'containers_provider_edit_detail': lambda _: cfg_btn('Edit this Containers Provider'), 'containers_provider_timelines_detail': lambda _: mon_btn('Timelines'), 'containers_provider_edit_tags_detail': lambda _: pol_btn('Edit Tags'), 'containers_provider_topology_detail':
def step(self): sel.check(Quadicon(self.obj.name, None)) cfg_btn('Provision Configured Systems')
details_page = Region(infoblock_type='detail') cfg_btn = partial(tb.select, 'Configuration') pol_btn = partial(tb.select, 'Policy') def nav_to_datastore_through_provider(context): sel.force_navigate('infrastructure_provider', context=context) list_acc.select('Relationships', 'Show all managed Datastores') sel.click(Quadicon(context['datastore'].name, 'datastore')) nav.add_branch( 'infrastructure_datastores', { 'infrastructure_datastore': lambda ctx: sel.click(Quadicon(ctx['datastore'].name, 'datastore')) if 'provider' not in ctx else nav_to_datastore_through_provider(ctx) }) class Datastore(Pretty): """ Model of an infrastructure datastore in cfme Args: name: Name of the datastore. provider_key: Name of the provider this datastore is attached to. Note: If given a provider_key, it will navigate through ``Infrastructure/Providers`` instead of the direct path through ``Infrastructure/Datastores``. """
def step(self): sel.check(Quadicon(self.obj.name, None)) cfg_btn('Edit Tags')
def _wait_f(): sel.force_navigate("{}_providers".format(self.page_name)) q = Quadicon(self.name, self.quad_name) creds = q.creds return creds == "checkmark"
def navigate_quadicons(q_names, q_type, page_name, nav_limit, ui_worker_pid, prod_tail, soft_assert, acc_topbars=[]): pages = [] count = 0 if nav_limit == 0: count = -1 assert len(q_names) > 0 while (count < nav_limit): for q in q_names: for page in paginator.pages(): quadicon = Quadicon(str(q), q_type) if sel.is_displayed(quadicon): pages.extend( analyze_page_stat( perf_click(ui_worker_pid, prod_tail, True, sel.click, quadicon), soft_assert)) for topbar in acc_topbars: try: if not list_acc.is_active(topbar): list_acc.click(topbar) links = list_acc.get_active_links(topbar) for link in range(len(links)): # Every click makes the previous list of links invalid links = list_acc.get_active_links(topbar) if link <= len(links): # Do not navigate to any link containing: dnn = [ 'parent', 'Capacity & Utilization', 'Timelines', 'Show tree of all VMs by Resource Pool in this Cluster', 'Show host drift history', 'Show VMs' ] if any_in(dnn, links[link].title): logger.debug('DNN Skipping: %s', links[link].title) else: pages.extend( analyze_page_stat( perf_click( ui_worker_pid, prod_tail, True, links[link].click), soft_assert)) except NoSuchElementException: logger.warning( 'NoSuchElementException - page_name:%s, Quadicon:%s,' ' topbar:%s', page_name, q, topbar) soft_assert( False, 'NoSuchElementException - page_name:{}, Quadicon:{},' ' topbar:{}'.format(page_name, q, topbar)) break count += 1 break pages.extend( analyze_page_stat( perf_click(ui_worker_pid, prod_tail, True, sel.force_navigate, page_name), soft_assert)) # If nav_limit == 0 , every item is navigated to if not nav_limit == 0 and count == nav_limit: break return pages
details_page = Region(infoblock_type='detail') cfg_btn = partial(tb.select, 'Configuration') pol_btn = partial(tb.select, 'Policy') def nav_to_cluster_through_provider(context): sel.force_navigate('infrastructure_provider', context=context) list_acc.select('Relationships', 'Clusters', by_title=False, partial=True) sel.click(Quadicon(context['cluster'].name, 'cluster')) nav.add_branch( 'infrastructure_clusters', { 'infrastructure_cluster': lambda ctx: sel.click(Quadicon(ctx['cluster'].name, 'cluster')) if 'provider' not in ctx else nav_to_cluster_through_provider(ctx) }) class Cluster(Pretty): """ Model of an infrastructure cluster in cfme Args: name: Name of the cluster. provider_key: Name of the provider this cluster is attached to. Note: If given a provider_key, it will navigate through ``Infrastructure/Providers`` instead of the direct path through ``Infrastructure/Clusters``. """
version.LOWEST: FormButton('Add this Host'), "5.5": FormButton("Add") } default_host_filter_btn = FormButton('Set the current filter as my default') cfg_btn = partial(tb.select, 'Configuration') pol_btn = partial(tb.select, 'Policy') pow_btn = partial(tb.select, 'Power') lif_btn = partial(tb.select, 'Lifecycle') nav.add_branch('infrastructure_hosts', {'infrastructure_host_new': lambda _: cfg_btn( version.pick({version.LOWEST: 'Add a New Host', '5.4': 'Add a New item'})), 'infrastructure_host_discover': lambda _: cfg_btn( 'Discover Hosts'), 'infrastructure_host': [lambda ctx: sel.click(Quadicon(ctx['host'].name, 'host')), {'infrastructure_host_edit': lambda _: cfg_btn( version.pick({version.LOWEST: 'Edit this Host', '5.4': 'Edit this item'})), 'infrastructure_host_policy_assignment': lambda _: pol_btn('Manage Policies'), 'infrastructure_provision_host': lambda _: lif_btn( version.pick({version.LOWEST: 'Provision this Host', '5.4': 'Provision this item'}))}]}) class Host(Updateable, Pretty): """ Model of an infrastructure host in cfme.
def step(self): sel.click(Quadicon(self.obj.name, self.obj.quad_name))
def wait_for_host_delete(host): sel.force_navigate('infrastructure_hosts') quad = Quadicon(host.name, 'host') logger.info('Waiting for a host to delete...') wait_for(lambda: not sel.is_displayed(quad), fail_condition=False, message="Wait host to disappear", num_sec=500, fail_func=sel.refresh)
def _setup_providers(cloud_or_infra, validate, check_existing): """Helper to set up all cloud or infra providers, and then validate them Args: cloud_or_infra: Like the name says: 'cloud' or 'infra' (a string) validate: see description in :py:func:`setup_provider` check_existing: see description in :py:func:`setup_provider` Returns: A list of provider objects that have been created. """ # Pivot behavior on cloud_or_infra options_map = { 'cloud': { 'navigate': 'clouds_providers', 'quad': 'cloud_prov', 'list': list_cloud_providers }, 'infra': { 'navigate': 'infrastructure_providers', 'quad': 'infra_prov', 'list': list_infra_providers } } # Check for existing providers all at once, to prevent reloading # the providers page for every provider in cfme_data if not options_map[cloud_or_infra]['list'](): return [] if check_existing: sel.force_navigate(options_map[cloud_or_infra]['navigate']) add_providers = [] for provider_key in options_map[cloud_or_infra]['list'](): provider_name = conf.cfme_data.get('management_systems', {})[provider_key]['name'] quad = Quadicon(provider_name, options_map[cloud_or_infra]['quad']) for page in paginator.pages(): if sel.is_displayed(quad): logger.debug('Provider "%s" exists, skipping' % provider_key) break else: add_providers.append(provider_key) else: # Add all cloud or infra providers unconditionally add_providers = options_map[cloud_or_infra]['list']() if add_providers: logger.info('Providers to be added: %s' % ', '.join(add_providers)) # Save the provider objects for validation and return added_providers = [] for provider_name in add_providers: # Don't validate in this step; add all providers, then go back and validate in order provider = setup_provider(provider_name, validate=False, check_existing=False) added_providers.append(provider) if validate: map(methodcaller('validate'), added_providers) return added_providers
def check_vm_add(self, add_vm_name): view = navigate_to(self, 'Details') # TODO - replace Quadicon later quadicon = Quadicon(add_vm_name, "vm") sel.click(quadicon) view.flash.assert_no_error()