diff --git a/cfme/common/__init__.py b/cfme/common/__init__.py index 61865bba14..6daa43060a 100644 --- a/cfme/common/__init__.py +++ b/cfme/common/__init__.py @@ -367,6 +367,40 @@ def step(self, *args, **kwargs): self.prerequisite_view.toolbar.policy.item_select('Manage Policies') +class ComparableCommonBase: + """ + This will be the base class for a Mixin for comparing entities. + Not sure yet what will go here versus Comparable + """ + pass + + +class ComparableMixin(ComparableCommonBase): + """ + Mixin for comparing entities + Todo: Update this!!! + """ + DROPDOWN_TEXT = 'Compare Selected items' + + def compare_entities_col(self, provider, entities_list=None): + from cfme.utils.appliance.implementations.ui import navigate_to + from cfme.common.host_views import HostsCompareView + from cfme.common.host_views import ProviderHostsCompareView + from cfme.common.vm import VM + entity_view = navigate_to(self, "All") + for item in entities_list: + v_entity = entity_view.entities.get_entity(name=item.name) + v_entity.ensure_checked() + entity_view.toolbar.configuration.item_select( + self.DROPDOWN_TEXT, handle_alert=True) + if self.parent != provider: + compare_entity_view = provider.create_view(self.COMPARE_APP_VIEW) + else: + compare_entity_view = provider.create_view(self.COMPARE_VIEW) + assert compare_entity_view.is_displayed + return compare_entity_view + + class CompareView(BaseLoggedInPage): """generic class for compare views""" title = Text('.//div[@id="center_div" or @id="main-content"]//h1') diff --git a/cfme/common/host_views.py b/cfme/common/host_views.py index 3bafdd3452..e318837f7d 100644 --- a/cfme/common/host_views.py +++ b/cfme/common/host_views.py @@ -332,6 +332,17 @@ def is_displayed(self): class HostsCompareView(CompareView, ComputeInfrastructureHostsView): """Compare Host / Node page.""" + @View.nested + class toolbar(View): + all_attributes = Button(title="All attributes") + different_values_attributes = Button(title="Attributes with different values") + same_values_attributes = Button(title="Attributes with same values") + details_mode = Button(title="Details Mode") + exists_mode = Button(title="Exists Mode") + # add expanded view, compressed view buttons. + download = Dropdown('Download') + view_selector = View.nested(ItemsToolBarViewSelector) + @property def is_displayed(self): title = "Compare Host / Node" diff --git a/cfme/infrastructure/virtual_machines.py b/cfme/infrastructure/virtual_machines.py index b7b9defb3f..e03667d110 100644 --- a/cfme/infrastructure/virtual_machines.py +++ b/cfme/infrastructure/virtual_machines.py @@ -27,7 +27,6 @@ from cfme.common import BaseLoggedInPage from cfme.common import ComparableMixin -from cfme.common import CompareView from cfme.common import TimelinesView from cfme.common.provider_views import TemplatesCompareView from cfme.common.vm import Template @@ -311,6 +310,8 @@ def is_displayed(self): class VmTemplatesCompareView(TemplatesCompareView): """Compare Templates page.""" + title = Text('.//div[@id="center_div" or @id="main-content"]//h1') + comparison_table = Table(locator='//div[@id="compare-grid"]/table') @property def is_displayed(self): @@ -1314,9 +1315,12 @@ def vm_default_args_rest(self): @attr.s -class InfraVmCollection(VMCollection): +class InfraVmCollection(ComparableMixin, VMCollection): ENTITY = InfraVm + # COMPARE_VIEW = ProviderInfraVmCompareView # I'll need to create this. + # COMPARE_APP_VIEW = InfraVmCompareView + def all(self): """Return entities for all items in collection""" # provider filter means we're viewing vms through provider details relationships @@ -1371,6 +1375,19 @@ def NAV_STRING(self): parent = self.filters.get('parent') # None if no filter return 'ProviderTemplates' if parent else 'TemplatesOnly' + from cfme.common.provider_views import TemplatesCompareView + COMPARE_VIEW = TemplatesCompareView + COMPARE_APP_VIEW = VmTemplatesCompareView + DROPDOWN_TEXT = 'Compare Selected Templates' + NAV_STRING = 'TemplatesOnly' + + @property + def name(self): + try: + return self.filters.get('provider').name + except Exception: + pass + def all(self): """Return entities for all items in collection""" # provider filter means we're viewing templates through provider details relationships @@ -1728,6 +1745,38 @@ def step(self, *args, **kwargs): raise DestinationNotFound("the destination isn't found") +@navigator.register(InfraTemplateCollection, 'TemplatesOnly2') +class TemplatesAll2(CFMENavigateStep): + prerequisite = NavigateToSibling('All') + + @property + def VIEW(self): # noqa + from cfme.infrastructure.provider import ProviderTemplatesView + from cfme.infrastructure.provider import InfraProvider + try: + if self.obj.parent.one_of(InfraProvider): + return ProviderTemplatesView # ProviderTemplatesOnlyAllView?? What is this? + except Exception: + pass + return TemplatesOnlyAllView + + def step(self, *args, **kwargs): + from cfme.infrastructure.provider import InfraProvider + try: + if self.obj.parent.one_of(InfraProvider): + navigate_to(self.obj.parent, 'ProviderTemplates') + return + except Exception: + pass + if 'filter_folder' not in kwargs: + self.view.sidebar.templates.tree.click_path('All Templates') + elif 'filter_folder' in kwargs and 'filter_name' in kwargs: + self.view.sidebar.templates.tree.click_path('All Templates', kwargs['filter_folder'], + kwargs['filter_name']) + else: + raise DestinationNotFound("the destination isn't found") + + @navigator.register(InfraVmCollection, 'Provision') class ProvisionVM(CFMENavigateStep): VIEW = ProvisionView diff --git a/cfme/tests/infrastructure/test_host.py b/cfme/tests/infrastructure/test_host.py index 93ec397dbe..04a8effdce 100644 --- a/cfme/tests/infrastructure/test_host.py +++ b/cfme/tests/infrastructure/test_host.py @@ -18,6 +18,7 @@ from cfme.common.host_views import HostsView from cfme.common.host_views import HostVmmInfoView from cfme.common.provider_views import InfraProviderDetailsView +from cfme.common.provider_views import InfraProvidersView from cfme.common.provider_views import ProviderNodesView from cfme.fixtures.provider import setup_or_skip from cfme.infrastructure.provider import InfraProvider @@ -32,6 +33,7 @@ from cfme.utils.appliance.implementations.ui import navigate_to from cfme.utils.blockers import BZ from cfme.utils.conf import credentials +from cfme.utils.log import logger from cfme.utils.log_validator import LogValidator from cfme.utils.update import update from cfme.utils.wait import wait_for @@ -502,6 +504,39 @@ def test_infrastructure_hosts_navigation_after_download_from_compare( hosts_view.navigation.select("Compute") assert hosts_view.is_displayed +# we need to handle appliance and provider nav, number of hosts, list of hosts?? +# +# ? view = navigate_to(self, 'All' if provider=None else 'AllForProvider') ?? is AllForProvider +# the same as provider.collections and All same as appliance.collections?? +# set defaults and use a list of hosts or num hosts. Error if neither is passed. +# host_list will not use get all, but will use other methods to get by name +# make this work for hosts first then look at differences needed to support other entities. +# There may be just too many differences to make using one method useful. +# may be easier just to put unique one in class def +# !!!If we want to remove navigation from this we can just pass in the starting view? + + +def compare_hosts(appliance, provider=None, num_hosts=2, host_list=None): + if num_hosts < 2: + pass # display error. OR just make = 2? + if host_list: + pass # add functionality + else: + ent_slice = slice(0, num_hosts, None) + if provider: + hosts_view = navigate_to(provider.collections.hosts, "All") + else: + hosts_view = navigate_to(appliance.collections.hosts, "All") # use different nav so don't + # need appliance + for h in hosts_view.entities.get_all(slice=ent_slice): + h.ensure_checked() + hosts_view.toolbar.configuration.item_select('Compare Selected items', + handle_alert=True) + compare_hosts_view = provider.create_view(HostsCompareView) + assert compare_hosts_view.is_displayed + # do we want to compare values on the compare view? Clone and update method used in templates. + return compare_hosts_view + @test_requirements.rhev @pytest.mark.provider([RHEVMProvider], required_fields=['hosts'], selector=ONE) diff --git a/cfme/tests/infrastructure/test_vm_compare.py b/cfme/tests/infrastructure/test_vm_compare.py new file mode 100644 index 0000000000..cf75092164 --- /dev/null +++ b/cfme/tests/infrastructure/test_vm_compare.py @@ -0,0 +1,46 @@ +import pytest + +from cfme.fixtures.provider import setup_or_skip +from cfme.infrastructure.provider import InfraProvider +from cfme.infrastructure.virtual_machines import InfraVmCollection +from cfme.markers.env_markers.provider import ONE +from cfme.markers.env_markers.provider import ONE_PER_TYPE +from cfme.utils.blockers import BZ + +pytestmark = [ + pytest.mark.tier(3), + pytest.mark.provider([InfraProvider], + scope='module', + selector=ONE_PER_TYPE), +] + + +@pytest.fixture +def setup_provider_min_vms(request, appliance, provider, min_vms): + if len(provider.mgmt.list_vms()) < min_vms: + pytest.skip(f'Number of templates on {provider} does not meet minimum ' + f'for test parameter {min_vms}, skipping and not setting up provider') + # Function-scoped fixture to set up a provider + setup_or_skip(request, provider) + + +@pytest.mark.provider([InfraProvider], selector=ONE, scope="function") +@pytest.mark.parametrize("min_vms", [2, 4]) +@pytest.mark.parametrize("vm_collection", ["provider", "appliance"]) +@pytest.mark.meta(blockers=[BZ(1784180, forced_streams=["5.10"])], automates=[1784180]) +def test_compare_vms(appliance, setup_provider_min_vms, provider, min_vms, vm_collection): + """ + Polarion: + assignee: prichard ???????? + casecomponent: Infra + caseimportance: high + initialEstimate: 1/6h + """ + if vm_collection == 'provider': + provider.collections.vms = InfraVmCollection(provider, filters={'provider': provider}) + t_coll = provider.collections.vms.all()[:min_vms] + provider.collections.vms.compare_entities_col(provider, entities_list=t_coll) + elif vm_collection == 'appliance': + appliance.collections.vms = InfraVmCollection(appliance) + t_coll = appliance.collections.templates.all()[:min_vms] + appliance.collections.vms.compare_entities_col(provider, entities_list=t_coll)