├── .gitattributes ├── .github └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── .gitmodules ├── .pre-commit-config.yaml ├── .readthedocs.yml ├── .ropeproject └── config.py ├── .travis.yml ├── COPYING ├── README.md ├── artifactor ├── __init__.py ├── __main__.py ├── example_tests │ └── artifactor_simple_example.py └── plugins │ ├── __init__.py │ ├── filedump.py │ ├── logger.py │ ├── ostriz.py │ ├── post_result.py │ ├── reporter.py │ ├── test.py │ └── video.py ├── cfme ├── __init__.py ├── ansible │ ├── __init__.py │ ├── credentials.py │ ├── playbooks.py │ └── repositories.py ├── ansible_tower │ ├── __init__.py │ ├── explorer.py │ └── jobs.py ├── automate │ ├── __init__.py │ ├── buttons.py │ ├── dialog_import_export.py │ ├── dialogs │ │ ├── __init__.py │ │ ├── dialog_box.py │ │ ├── dialog_element.py │ │ ├── dialog_tab.py │ │ └── service_dialogs.py │ ├── explorer │ │ ├── __init__.py │ │ ├── common.py │ │ ├── domain.py │ │ ├── instance.py │ │ ├── klass.py │ │ ├── method.py │ │ └── namespace.py │ ├── import_export.py │ ├── provisioning_dialogs.py │ ├── requests.py │ └── simulation.py ├── base │ ├── __init__.py │ ├── credential.py │ ├── rest.py │ ├── ssui.py │ └── ui.py ├── cloud │ ├── __init__.py │ ├── availability_zone.py │ ├── flavor.py │ ├── host_aggregates.py │ ├── instance │ │ ├── __init__.py │ │ ├── azure.py │ │ ├── ec2.py │ │ ├── gce.py │ │ ├── image.py │ │ └── openstack.py │ ├── keypairs.py │ ├── provider │ │ ├── __init__.py │ │ ├── azure.py │ │ ├── ec2.py │ │ ├── gce.py │ │ ├── openstack.py │ │ └── vcloud.py │ ├── security_groups.py │ ├── stack.py │ └── tenant.py ├── common │ ├── __init__.py │ ├── candu_views.py │ ├── datastore_views.py │ ├── host_views.py │ ├── physical_server_views.py │ ├── physical_switch_views.py │ ├── provider.py │ ├── provider_views.py │ ├── topology.py │ ├── vm.py │ ├── vm_console.py │ └── vm_views.py ├── configure │ ├── __init__.py │ ├── about.py │ ├── access_control │ │ └── __init__.py │ ├── configuration │ │ ├── __init__.py │ │ ├── analysis_profile.py │ │ ├── diagnostics_settings.py │ │ ├── region_settings.py │ │ ├── server_settings.py │ │ └── system_schedules.py │ ├── documentation.py │ ├── settings.py │ └── tasks.py ├── containers │ ├── __init__.py │ ├── build.py │ ├── container.py │ ├── image.py │ ├── image_registry.py │ ├── node.py │ ├── overview.py │ ├── pod.py │ ├── project.py │ ├── provider │ │ ├── __init__.py │ │ └── openshift.py │ ├── replicator.py │ ├── route.py │ ├── service.py │ ├── template.py │ ├── topology.py │ └── volume.py ├── control │ ├── __init__.py │ ├── explorer │ │ ├── __init__.py │ │ ├── actions.py │ │ ├── alert_profiles.py │ │ ├── alerts.py │ │ ├── conditions.py │ │ ├── policies.py │ │ └── policy_profiles.py │ ├── import_export.py │ ├── log.py │ └── simulation.py ├── dashboard.py ├── exceptions.py ├── fixtures │ ├── __init__.py │ ├── ansible_fixtures.py │ ├── ansible_tower.py │ ├── appliance.py │ ├── appliance_update.py │ ├── artifactor_plugin.py │ ├── authentication.py │ ├── automate.py │ ├── base.py │ ├── blockers.py │ ├── browser.py │ ├── bzs.py │ ├── candu.py │ ├── cfme_data.py │ ├── cli.py │ ├── datafile.py │ ├── depot.py │ ├── dev_branch.py │ ├── disable_forgery_protection.py │ ├── embedded_ansible.py │ ├── events.py │ ├── fixtureconf.py │ ├── generic_object.py │ ├── has_persistent_volume.py │ ├── log.py │ ├── maximized.py │ ├── model_collections.py │ ├── multi_region.py │ ├── multi_tenancy.py │ ├── nelson.py │ ├── networks.py │ ├── nuage.py │ ├── page_screenshots.py │ ├── parallelizer │ │ ├── __init__.py │ │ ├── hooks.py │ │ ├── parallelizer_tester.py │ │ └── remote.py │ ├── perf.py │ ├── physical_switch.py │ ├── portset.py │ ├── prov_filter.py │ ├── provider.py │ ├── pxe.py │ ├── pytest_store.py │ ├── qa_contact.py │ ├── randomness.py │ ├── rbac.py │ ├── rdb.py │ ├── sauce.py │ ├── screenshots.py │ ├── service_fixtures.py │ ├── single_appliance_sprout.py │ ├── skip_not_implemented.py │ ├── smtp.py │ ├── soft_assert.py │ ├── ssh_client.py │ ├── tag.py │ ├── tccheck.py │ ├── templateloader.py │ ├── templates.py │ ├── terminalreporter.py │ ├── ui_coverage.py │ ├── update_tests.py │ ├── utility_vm.py │ ├── v2v_fixtures.py │ ├── version_info.py │ ├── video.py │ ├── virtual_machine.py │ ├── vm.py │ ├── vm_console.py │ ├── vporizer.py │ └── xunit_tools.py ├── generic_objects │ ├── __init__.py │ ├── definition │ │ ├── __init__.py │ │ ├── associations.py │ │ ├── button_groups.py │ │ ├── definition_views.py │ │ ├── rest.py │ │ └── ui.py │ └── instance │ │ ├── __init__.py │ │ ├── rest.py │ │ └── ui.py ├── infrastructure │ ├── __init__.py │ ├── cluster.py │ ├── config_management │ │ ├── __init__.py │ │ ├── ansible_tower.py │ │ ├── config_profiles.py │ │ ├── config_systems │ │ │ ├── __init__.py │ │ │ ├── ansible_tower.py │ │ │ └── satellite.py │ │ └── satellite.py │ ├── datastore.py │ ├── deployment_roles.py │ ├── host.py │ ├── networking.py │ ├── openstack_node.py │ ├── provider │ │ ├── __init__.py │ │ ├── kubevirt.py │ │ ├── openstack_infra.py │ │ ├── rhevm.py │ │ ├── scvmm.py │ │ └── virtualcenter.py │ ├── pxe.py │ ├── resource_pool.py │ └── virtual_machines.py ├── intelligence │ ├── __init__.py │ ├── chargeback │ │ ├── __init__.py │ │ ├── assignments.py │ │ └── rates.py │ ├── optimization.py │ ├── reports │ │ ├── __init__.py │ │ ├── dashboards.py │ │ ├── menus.py │ │ ├── reports.py │ │ ├── saved.py │ │ ├── schedules.py │ │ └── widgets │ │ │ ├── __init__.py │ │ │ ├── chart_widgets.py │ │ │ ├── menu_widgets.py │ │ │ ├── report_widgets.py │ │ │ └── rss_widgets.py │ ├── rss.py │ └── timelines.py ├── js.py ├── markers │ ├── __init__.py │ ├── composite.py │ ├── crud.py │ ├── destructive.py │ ├── env.py │ ├── env_markers │ │ ├── __init__.py │ │ └── provider.py │ ├── fixtureconf.py │ ├── isolation.py │ ├── manual.py │ ├── marker_filters.py │ ├── meta.py │ ├── perf.py │ ├── polarion.py │ ├── regression.py │ ├── requires.py │ ├── rhel_tests.py │ ├── sauce.py │ ├── serial.py │ ├── skipper.py │ ├── smoke.py │ ├── stream_excluder.py │ ├── uncollect.py │ └── uses.py ├── metaplugins │ ├── __init__.py │ ├── blockers.py │ └── server_roles.py ├── modeling │ ├── __init__.py │ ├── base.py │ └── tests │ │ ├── __init__.py │ │ └── test_collections.py ├── networks │ ├── __init__.py │ ├── balancer.py │ ├── cloud_network.py │ ├── floating_ips.py │ ├── network_port.py │ ├── network_router.py │ ├── provider │ │ ├── __init__.py │ │ └── nuage.py │ ├── security_group.py │ ├── subnet.py │ ├── topology.py │ └── views.py ├── optimize │ ├── __init__.py │ ├── bottlenecks.py │ └── utilization.py ├── physical │ ├── __init__.py │ ├── physical_chassis.py │ ├── physical_rack.py │ ├── physical_server.py │ ├── physical_storage.py │ ├── physical_switch.py │ └── provider │ │ ├── __init__.py │ │ ├── lenovo.py │ │ └── redfish.py ├── provisioning.py ├── rest │ ├── __init__.py │ ├── abc.py │ └── gen_data.py ├── roles.py ├── scripting │ ├── __init__.py │ ├── appliance.py │ ├── bz.py │ ├── conf.py │ ├── disable_bytecode.py │ ├── ipyshell.py │ ├── link_config.py │ ├── miq.py │ ├── polarion.py │ ├── quickstart │ │ ├── __init__.py │ │ ├── __main__.py │ │ ├── proc.py │ │ └── system.py │ ├── release.py │ ├── requirement.py │ ├── runtest.py │ ├── setup_env.py │ ├── sprout.py │ └── tests │ │ ├── __init__.py │ │ └── test_quickstart.py ├── services │ ├── __init__.py │ ├── catalogs │ │ ├── __init__.py │ │ ├── catalog.py │ │ ├── catalog_items │ │ │ ├── __init__.py │ │ │ ├── ansible_catalog_items.py │ │ │ └── catalog_bundles.py │ │ └── orchestration_template.py │ ├── dashboard │ │ ├── __init__.py │ │ └── ssui.py │ ├── myservice │ │ ├── __init__.py │ │ ├── rest.py │ │ ├── ssui.py │ │ └── ui.py │ ├── requests.py │ ├── service_catalogs │ │ ├── __init__.py │ │ ├── ssui.py │ │ └── ui.py │ └── workloads.py ├── storage │ ├── __init__.py │ ├── manager.py │ ├── object_store_container.py │ ├── object_store_object.py │ ├── volume.py │ ├── volume_backup.py │ ├── volume_snapshot.py │ └── volume_type.py ├── test_framework │ ├── __init__.py │ ├── appliance.py │ ├── appliance_hooks.py │ ├── appliance_log_collector.py │ ├── appliance_police.py │ ├── browser_isolation.py │ ├── config.py │ ├── pytest_plugin.py │ └── sprout │ │ ├── __init__.py │ │ ├── client.py │ │ └── plugin.py ├── test_requirements.py ├── tests │ ├── .polarion_tests │ ├── __init__.py │ ├── ansible │ │ ├── test_embedded_ansible_actions.py │ │ ├── test_embedded_ansible_automate.py │ │ ├── test_embedded_ansible_basic.py │ │ ├── test_embedded_ansible_crud.py │ │ ├── test_embedded_ansible_manual.py │ │ ├── test_embedded_ansible_rest.py │ │ ├── test_embedded_ansible_services.py │ │ └── test_embedded_ansible_tags.py │ ├── automate │ │ ├── __init__.py │ │ ├── custom_button │ │ │ ├── __init__.py │ │ │ ├── test_buttons.py │ │ │ ├── test_catalog_custom_button.py │ │ │ ├── test_cloud_objects.py │ │ │ ├── test_container_objects.py │ │ │ ├── test_custom_menu.py │ │ │ ├── test_generic_objects.py │ │ │ ├── test_import_export.py │ │ │ ├── test_infra_objects.py │ │ │ ├── test_infra_objects_ansible.py │ │ │ ├── test_rest_custom_button.py │ │ │ ├── test_service_objects.py │ │ │ └── test_service_vm_custom_button.py │ │ ├── generic_objects │ │ │ ├── buttons │ │ │ │ └── test_generic_class_custom_button.py │ │ │ ├── test_definitions.py │ │ │ └── test_instances.py │ │ ├── test_ansible_tower_automate.py │ │ ├── test_automate_manual.py │ │ ├── test_class.py │ │ ├── test_common_methods.py │ │ ├── test_customization_paginator.py │ │ ├── test_domain.py │ │ ├── test_domain_priority.py │ │ ├── test_file_import.py │ │ ├── test_git_import.py │ │ ├── test_instance.py │ │ ├── test_method.py │ │ ├── test_namespace.py │ │ ├── test_provisioning_dialogs.py │ │ ├── test_rest.py │ │ ├── test_service_automate.py │ │ ├── test_service_dialog.py │ │ ├── test_simulation.py │ │ ├── test_smoke.py │ │ └── test_vmware_methods.py │ ├── candu │ │ ├── __init__.py │ │ ├── test_azone_graph.py │ │ ├── test_candu_manual.py │ │ ├── test_cluster_graph.py │ │ ├── test_datastore_graph.py │ │ ├── test_gap_collection.py │ │ ├── test_graph_groupbytag.py │ │ ├── test_host_graph.py │ │ ├── test_nor_rightsize.py │ │ ├── test_utilization.py │ │ ├── test_utilization_metrics.py │ │ └── test_vm_graph.py │ ├── cli │ │ ├── __init__.py │ │ ├── test_appliance_cli.py │ │ ├── test_appliance_console.py │ │ ├── test_appliance_console_db_restore.py │ │ ├── test_appliance_log_rotate.py │ │ ├── test_appliance_update.py │ │ ├── test_appliance_update_manual.py │ │ ├── test_evmserverd.py │ │ └── test_rake_evm_automate-53.py │ ├── cloud │ │ ├── __init__.py │ │ ├── test_azure_manual.py │ │ ├── test_cloud_events.py │ │ ├── test_cloud_timelines.py │ │ ├── test_delete_cloud_object.py │ │ ├── test_instance_power_control.py │ │ ├── test_instance_reconfigure.py │ │ ├── test_keypairs.py │ │ ├── test_providers.py │ │ ├── test_quota.py │ │ ├── test_quota_tagging.py │ │ ├── test_snapshot.py │ │ ├── test_stack.py │ │ ├── test_tag_mapping.py │ │ ├── test_targeted_refresh.py │ │ ├── test_tenant.py │ │ └── test_tenant_quota.py │ ├── cloud_infra_common │ │ ├── __init__.py │ │ ├── test_cloud_init_provisioning.py │ │ ├── test_cockpit_server.py │ │ ├── test_custom_attributes_rest.py │ │ ├── test_discovery_and_support.py │ │ ├── test_events.py │ │ ├── test_genealogy.py │ │ ├── test_html5_vm_console.py │ │ ├── test_html5_vm_console_ssui.py │ │ ├── test_policy_simulation.py │ │ ├── test_power_control_manual.py │ │ ├── test_power_control_rest.py │ │ ├── test_provisioning.py │ │ ├── test_provisioning_manual.py │ │ ├── test_quota_manual.py │ │ ├── test_quota_with_multiple_providers.py │ │ ├── test_relationships.py │ │ ├── test_rest_providers.py │ │ ├── test_retirement.py │ │ ├── test_snapshots.py │ │ ├── test_snapshots_rest.py │ │ ├── test_tag_objects.py │ │ ├── test_tag_visibility.py │ │ ├── test_vm_instance_analysis.py │ │ ├── test_vm_instance_analysis_manual.py │ │ └── test_vm_ownership.py │ ├── configure │ │ ├── __init__.py │ │ ├── test_about.py │ │ ├── test_access_control.py │ │ ├── test_analysis_profiles.py │ │ ├── test_config_diagnostics.py │ │ ├── test_config_manual.py │ │ ├── test_database_ui.py │ │ ├── test_db_backup_schedule.py │ │ ├── test_default_filters.py │ │ ├── test_default_views_cloud.py │ │ ├── test_default_views_infra.py │ │ ├── test_display_settings.py │ │ ├── test_docs.py │ │ ├── test_email.py │ │ ├── test_landing_page.py │ │ ├── test_log_depot_operation.py │ │ ├── test_log_depot_operation_manual.py │ │ ├── test_logs.py │ │ ├── test_ntp_server.py │ │ ├── test_paginator.py │ │ ├── test_proxy.py │ │ ├── test_rbac_landing_page.py │ │ ├── test_region.py │ │ ├── test_register_appliance.py │ │ ├── test_remote_server_tabs.py │ │ ├── test_rest_access_control.py │ │ ├── test_rest_config.py │ │ ├── test_schedule_operations.py │ │ ├── test_server_name.py │ │ ├── test_server_roles.py │ │ ├── test_session_timeout.py │ │ ├── test_tag.py │ │ ├── test_tag_category.py │ │ ├── test_timeprofile.py │ │ ├── test_version.py │ │ ├── test_visual_cloud.py │ │ ├── test_visual_infra.py │ │ ├── test_vmware_console_settings.py │ │ ├── test_workers.py │ │ └── test_zones.py │ ├── containers │ │ ├── __init__.py │ │ ├── test_ad_hoc_metrics.py │ │ ├── test_alerts.py │ │ ├── test_basic_metrics.py │ │ ├── test_blacklisted_container_events.py │ │ ├── test_breadcrumbs.py │ │ ├── test_chargeback.py │ │ ├── test_cockpit.py │ │ ├── test_configurable_menus.py │ │ ├── test_container_provider_crud.py │ │ ├── test_container_provider_refresh.py │ │ ├── test_containers_smartstate_analysis.py │ │ ├── test_containers_smartstate_analysis_multiple_images.py │ │ ├── test_containers_summary.py │ │ ├── test_labels.py │ │ ├── test_logging.py │ │ ├── test_manageiq_ansible_custom_attributes.py │ │ ├── test_node.py │ │ ├── test_overview_data_integrity.py │ │ ├── test_pause_resume_workers.py │ │ ├── test_project_quota_historical_data.py │ │ ├── test_projects_dashboard.py │ │ ├── test_properties.py │ │ ├── test_provider_configuration_menu.py │ │ ├── test_provider_openscap_policy_attached.py │ │ ├── test_relationships.py │ │ ├── test_reload_button_provider.py │ │ ├── test_reports.py │ │ ├── test_search_bar.py │ │ ├── test_ssa_set_cve_image_inspector_per_provider.py │ │ ├── test_ssl_providers.py │ │ ├── test_start_page.py │ │ ├── test_static_custom_attributes.py │ │ ├── test_table_views.py │ │ ├── test_tables_fields.py │ │ ├── test_tables_sort.py │ │ ├── test_tags.py │ │ └── test_topology.py │ ├── control │ │ ├── __init__.py │ │ ├── test_actions.py │ │ ├── test_alerts.py │ │ ├── test_basic.py │ │ ├── test_bugs.py │ │ ├── test_compliance.py │ │ ├── test_control_simulation.py │ │ ├── test_default_alerts.py │ │ ├── test_export_policies.py │ │ ├── test_import_policies.py │ │ ├── test_rest_control.py │ │ └── test_smoke_control.py │ ├── distributed │ │ ├── test_appliance_file_permissions.py │ │ ├── test_appliance_manual.py │ │ └── test_appliance_replication.py │ ├── infrastructure │ │ ├── __init__.py │ │ ├── test_advanced_search_host.py │ │ ├── test_advanced_search_providers.py │ │ ├── test_advanced_search_vms.py │ │ ├── test_child_tenant.py │ │ ├── test_cluster_analysis.py │ │ ├── test_config_management.py │ │ ├── test_config_management_rest.py │ │ ├── test_customization_template.py │ │ ├── test_datastore_analysis.py │ │ ├── test_delete_infra_object.py │ │ ├── test_host.py │ │ ├── test_host_analysis.py │ │ ├── test_host_drift_analysis.py │ │ ├── test_host_manual.py │ │ ├── test_host_provisioning.py │ │ ├── test_individual_host_creds.py │ │ ├── test_infra_tag_filters_combination.py │ │ ├── test_iso_datastore.py │ │ ├── test_iso_provisioning.py │ │ ├── test_kubevirt.py │ │ ├── test_project_quota.py │ │ ├── test_provider_discovery.py │ │ ├── test_providers.py │ │ ├── test_provisioning_dialog.py │ │ ├── test_provisioning_rest.py │ │ ├── test_publish_vm_to_template.py │ │ ├── test_pxe.py │ │ ├── test_pxe_provisioning.py │ │ ├── test_quota.py │ │ ├── test_quota_tagging.py │ │ ├── test_rest_automation_request.py │ │ ├── test_rest_templates.py │ │ ├── test_scvmm_specific.py │ │ ├── test_set_default_filter.py │ │ ├── test_snapshot.py │ │ ├── test_ssa_vddk.py │ │ ├── test_system_image_type.py │ │ ├── test_tenant_quota.py │ │ ├── test_timelines.py │ │ ├── test_vm_clone.py │ │ ├── test_vm_delete.py │ │ ├── test_vm_engine_relationship.py │ │ ├── test_vm_migrate.py │ │ ├── test_vm_ownership.py │ │ ├── test_vm_power_control.py │ │ ├── test_vm_reconfigure.py │ │ ├── test_vm_rest.py │ │ ├── test_vm_retirement_rest.py │ │ ├── test_vmrc_console.py │ │ ├── test_vmware_provider.py │ │ └── test_webmks_console.py │ ├── integration │ │ ├── __init__.py │ │ ├── test_auth_manual.py │ │ ├── test_auth_scripts.py │ │ ├── test_aws_iam_auth_and_roles.py │ │ ├── test_cfme_auth.py │ │ ├── test_db_auth.py │ │ ├── test_external_auth.py │ │ ├── test_ldap_auth.py │ │ └── test_ldap_auth_and_roles.py │ ├── intelligence │ │ ├── __init__.py │ │ ├── chargeback │ │ │ ├── test_chargeback_long_term_rates.py │ │ │ └── test_resource_allocation.py │ │ ├── reports │ │ │ ├── __init__.py │ │ │ ├── test_canned_corresponds.py │ │ │ ├── test_crud.py │ │ │ ├── test_generate_report.py │ │ │ ├── test_import_export_reports_widgets.py │ │ │ ├── test_menus.py │ │ │ ├── test_metering_report.py │ │ │ ├── test_report_chargeback.py │ │ │ ├── test_report_corresponds.py │ │ │ ├── test_reports.py │ │ │ ├── test_reports_schedules.py │ │ │ ├── test_validate_chargeback_report.py │ │ │ ├── test_validate_chargeback_report_manual.py │ │ │ ├── test_views.py │ │ │ └── test_widgets.py │ │ ├── test_chargeback.py │ │ ├── test_chargeback_assignments.py │ │ ├── test_chargeback_manual.py │ │ ├── test_dashboard.py │ │ ├── test_download_report.py │ │ ├── test_optimization.py │ │ ├── test_reports_with_timelines.py │ │ ├── test_rss.py │ │ └── test_timelines_rss_removed.py │ ├── migration_analytics │ │ ├── __init__.py │ │ └── test_migration_analytics.py │ ├── networks │ │ ├── __init__.py │ │ ├── nuage │ │ │ ├── __init__.py │ │ │ ├── test_automation.py │ │ │ ├── test_events_are_triggered.py │ │ │ ├── test_inventory.py │ │ │ └── test_operations.py │ │ ├── test_network_providers.py │ │ ├── test_provision_to_virtual_network.py │ │ ├── test_sdn_balancers.py │ │ ├── test_sdn_crud.py │ │ ├── test_sdn_downloads.py │ │ ├── test_sdn_inventory_collection.py │ │ ├── test_sdn_navigation.py │ │ ├── test_sdn_ports.py │ │ ├── test_sdn_security_groups.py │ │ ├── test_sdn_topology.py │ │ └── test_tag_tagvis.py │ ├── openstack │ │ ├── __init__.py │ │ ├── cloud │ │ │ ├── __init__.py │ │ │ ├── test_flavors.py │ │ │ ├── test_instances.py │ │ │ ├── test_networks.py │ │ │ ├── test_provider.py │ │ │ ├── test_volume_backup.py │ │ │ └── test_volumes.py │ │ └── infrastructure │ │ │ ├── __init__.py │ │ │ ├── test_host_lifecycle.py │ │ │ ├── test_host_power_control.py │ │ │ ├── test_hosts.py │ │ │ ├── test_provider.py │ │ │ ├── test_relationships.py │ │ │ ├── test_resources.py │ │ │ └── test_roles.py │ ├── optimize │ │ └── test_bottlenecks.py │ ├── perf │ │ ├── __init__.py │ │ └── workloads │ │ │ ├── __init__.py │ │ │ ├── test_capacity_and_utilization.py │ │ │ ├── test_capacity_and_utilization_replication.py │ │ │ ├── test_idle.py │ │ │ ├── test_memory_leak.py │ │ │ ├── test_provisioning.py │ │ │ ├── test_refresh_providers.py │ │ │ ├── test_refresh_vms.py │ │ │ └── test_smartstate_analysis.py │ ├── physical_infrastructure │ │ ├── __init__.py │ │ ├── api │ │ │ ├── test_physical_server_api.py │ │ │ ├── test_physical_server_events_api.py │ │ │ ├── test_physical_server_inventory_api.py │ │ │ ├── test_physical_switch_api.py │ │ │ └── test_physical_switch_inventory_api.py │ │ ├── test_physical_rack.py │ │ ├── test_providers.py │ │ ├── test_redfish_physical_chassis.py │ │ ├── test_redfish_physical_infra_events.py │ │ ├── test_redfish_physical_racks.py │ │ ├── test_redfish_physical_server_details.py │ │ ├── test_redfish_providers.py │ │ └── ui │ │ │ ├── test_physical_overview.py │ │ │ ├── test_physical_server_details.py │ │ │ ├── test_physical_server_details_buttons.py │ │ │ ├── test_physical_server_list.py │ │ │ ├── test_physical_server_list_buttons.py │ │ │ ├── test_physical_switch_details.py │ │ │ └── test_physical_switch_list.py │ ├── platform │ │ ├── test_advanced_config.py │ │ └── test_locale.py │ ├── pod │ │ ├── __init__.py │ │ └── test_appliance_crud.py │ ├── satellite │ │ └── test_satellite_manual.py │ ├── services │ │ ├── __init__.py │ │ ├── test_add_remove_vm_to_service.py │ │ ├── test_ansible_workflow_servicecatalogs.py │ │ ├── test_catalog.py │ │ ├── test_catalog_item.py │ │ ├── test_cloud_service_catalogs.py │ │ ├── test_config_provider_servicecatalogs.py │ │ ├── test_dialog_element_in_catalog.py │ │ ├── test_dialog_regex_validation_in_catalog.py │ │ ├── test_different_dialogs_in_catalogs.py │ │ ├── test_dynamicdd_dialogelement.py │ │ ├── test_generic_service_catalogs.py │ │ ├── test_iso_service_catalogs.py │ │ ├── test_myservice.py │ │ ├── test_operations.py │ │ ├── test_orchestration_template.py │ │ ├── test_provision_stack.py │ │ ├── test_pxe_service_catalogs.py │ │ ├── test_request.py │ │ ├── test_rest_services.py │ │ ├── test_service_catalog_dialog_manual.py │ │ ├── test_service_catalogs.py │ │ ├── test_service_catalogs_bundles.py │ │ ├── test_service_catalogs_multi_region.py │ │ ├── test_service_customer_bz.py │ │ ├── test_service_manual_approval.py │ │ ├── test_service_performance.py │ │ ├── test_service_rbac.py │ │ └── test_tower_manual.py │ ├── ssui │ │ ├── test_ssui_ansible_service.py │ │ ├── test_ssui_dashboard.py │ │ ├── test_ssui_myservice.py │ │ ├── test_ssui_service_catalogs.py │ │ ├── test_ssui_service_dialog.py │ │ └── test_ssui_tags.py │ ├── storage │ │ ├── __init__.py │ │ ├── test_manager.py │ │ ├── test_object_store_container.py │ │ ├── test_object_store_object.py │ │ ├── test_volume.py │ │ ├── test_volume_backup.py │ │ ├── test_volume_snapshot.py │ │ └── test_volume_types.py │ ├── test_appliance.py │ ├── test_csrf.py │ ├── test_db_migrate.py │ ├── test_db_migrate_manual.py │ ├── test_login.py │ ├── test_manual.py │ ├── test_modules_importable.py │ ├── test_providerless_rest.py │ ├── test_replication.py │ ├── test_rest.py │ ├── test_rest_manual.py │ ├── test_server_manual.py │ ├── test_ui.py │ ├── test_utilization.py │ ├── v2v │ │ ├── test_conversion_host_ui.py │ │ ├── test_csv_import.py │ │ ├── test_migration_throttling.py │ │ ├── test_post_migrations.py │ │ ├── test_rest_migrations.py │ │ ├── test_v2v_ansible.py │ │ ├── test_v2v_cancel_migrations.py │ │ ├── test_v2v_manual.py │ │ ├── test_v2v_migrations.py │ │ ├── test_v2v_migrations_single_vcenter.py │ │ ├── test_v2v_migrations_ui.py │ │ ├── test_v2v_schedule_migrations.py │ │ └── test_v2v_smoke.py │ └── webui │ │ ├── test_advanced_search.py │ │ ├── test_expression_editor.py │ │ ├── test_general_ui.py │ │ ├── test_general_ui_manual.py │ │ ├── test_rest.py │ │ └── test_splitter.py ├── utils │ ├── __init__.py │ ├── ansible.py │ ├── ansible_conf │ │ ├── custom_attributes_basic_script.yml │ │ ├── providers_basic_script.yml │ │ ├── tags_basic_script.yml │ │ └── users_basic_script.yml │ ├── apidoc.py │ ├── appliance │ │ ├── __init__.py │ │ ├── console.py │ │ ├── constants.py │ │ ├── db.py │ │ ├── implementations │ │ │ ├── __init__.py │ │ │ ├── common.py │ │ │ ├── rest.py │ │ │ ├── ssui.py │ │ │ └── ui.py │ │ ├── plugin.py │ │ └── services.py │ ├── auth │ │ └── __init__.py │ ├── blockers.py │ ├── browser.py │ ├── bz.py │ ├── category.py │ ├── conf.py │ ├── datafile.py │ ├── db.py │ ├── deprecation.py │ ├── dockerbot │ │ ├── README.md │ │ ├── __init__.py │ │ ├── build_container.py │ │ ├── check_prs.py │ │ ├── dockerbot.py │ │ ├── pytestbase │ │ │ ├── Dockerfile │ │ │ ├── __init__.py │ │ │ ├── check_provisioned.py │ │ │ ├── get_keys.py │ │ │ ├── post_result.py │ │ │ ├── setup.sh │ │ │ └── verify_commit.py │ │ └── sel_container.py │ ├── error.py │ ├── events.py │ ├── events_db.py │ ├── ftp.py │ ├── generators.py │ ├── grafana.py │ ├── ipmi.py │ ├── log.py │ ├── log_validator.py │ ├── net.py │ ├── ocp_cli.py │ ├── path.py │ ├── perf.py │ ├── perf_message_stats.py │ ├── ports.py │ ├── pretty.py │ ├── providers.py │ ├── pytest_shortcuts.py │ ├── quote.py │ ├── rest.py │ ├── smem_memory_monitor.py │ ├── smtp_collector_client.py │ ├── soft_get.py │ ├── ssh.py │ ├── ssh_expect.py │ ├── stats.py │ ├── template │ │ ├── README.md │ │ ├── __init__.py │ │ ├── base.py │ │ ├── ec2.py │ │ ├── gce.py │ │ ├── openstack.py │ │ ├── rhevm.py │ │ ├── rhopenshift.py │ │ ├── scvmm.py │ │ ├── template_upload.py │ │ └── virtualcenter.py │ ├── testgen.py │ ├── tests │ │ ├── README │ │ ├── test_connect_ssh.py │ │ ├── test_datafile_fixture.py │ │ ├── test_fixtureconf_fixture.py │ │ ├── test_instance_class_method.py │ │ ├── test_ipappliance.py │ │ ├── test_metadoc.py │ │ ├── test_process_pytest_path.py │ │ ├── test_providers.py │ │ ├── test_pytest_shortcuts.py │ │ ├── test_safe_string.py │ │ ├── test_simple_locators.py │ │ ├── test_soft_assert.py │ │ ├── test_soft_get.py │ │ ├── test_ssh_client.py │ │ ├── test_units.py │ │ ├── test_version.py │ │ ├── test_vm_name_assignee.py │ │ └── test_vm_name_assignee_func_scope.py │ ├── timeutil.py │ ├── tracer.py │ ├── trackerbot.py │ ├── units.py │ ├── update.py │ ├── version.py │ ├── video.py │ ├── virtual_machines.py │ ├── wait.py │ └── workloads.py └── v2v │ ├── __init__.py │ ├── infrastructure_mapping.py │ ├── migration_plans.py │ └── migration_settings.py ├── cfme_test.sh ├── conf ├── cfme_data.yaml.template ├── credentials.yaml.template ├── docker.yaml.template ├── env.yaml.template ├── perf_tests.yaml.template ├── polarion_tools.local.yaml.template ├── polarion_tools.yaml ├── polarion_tools.yaml.template ├── supportability.yaml └── supportability.yaml.template ├── conftest.py ├── data ├── az_pwsh_cloudinit.cfg ├── basiccloudinit.cfg ├── bugzilla-queries │ └── fixed_in_query.yaml ├── cert-auths │ └── cmqe-tests-openshift-signer.crt ├── cfme │ └── utils │ │ └── test_datafile_fixture │ │ └── test_template ├── cli │ └── QECliTesting.yaml ├── firefox_profile.js.template ├── orchestration │ ├── aws_vm_template.json │ ├── aws_vm_template.yaml │ ├── azure_vm_template.json │ ├── openstack_vm_template.data │ └── rhos13_vm_template.data ├── patches │ ├── autofocus.js.diff │ ├── autofocus_57.js.diff │ ├── miq_application.js.diff │ └── ovirt_gem.patch ├── qe_event_handler.xml ├── reports_crud │ └── basic01.yaml ├── resources │ └── middleware │ │ ├── cfme_test_ear_middleware.ear │ │ ├── cfme_test_jar_middleware.jar │ │ ├── cfme_test_war_middleware.war │ │ └── new_cfme_test_war_middleware.war ├── rhel6-iso.cfg ├── rhel6.cfg ├── rhel7.cfg ├── rhel8.cfg ├── rootpass.cfg ├── schedules_crud │ └── basic01.yaml ├── suite.yaml ├── templates │ ├── base.html │ ├── dist │ │ ├── css │ │ │ ├── bootstrap-select.min.css │ │ │ ├── bootstrap-theme.min.css │ │ │ ├── bootstrap.min.css │ │ │ ├── font-awesome.min.css │ │ │ ├── patternfly.css │ │ │ └── patternfly.min.css │ │ ├── fonts │ │ │ ├── FontAwesome.otf │ │ │ ├── OpenSans-Bold-webfont.ttf │ │ │ ├── OpenSans-Bold-webfont.woff │ │ │ ├── OpenSans-Light-webfont.ttf │ │ │ ├── OpenSans-Light-webfont.woff │ │ │ ├── OpenSans-Regular-webfont.ttf │ │ │ ├── OpenSans-Regular-webfont.woff │ │ │ ├── OpenSans-Semibold-webfont.ttf │ │ │ ├── OpenSans-Semibold-webfont.woff │ │ │ ├── PatternFlyIcons-webfont.eot │ │ │ ├── PatternFlyIcons-webfont.svg │ │ │ ├── PatternFlyIcons-webfont.ttf │ │ │ ├── PatternFlyIcons-webfont.woff │ │ │ ├── fontawesome-webfont.eot │ │ │ ├── fontawesome-webfont.svg │ │ │ ├── fontawesome-webfont.ttf │ │ │ ├── fontawesome-webfont.woff │ │ │ ├── glyphicons-halflings-regular.eot │ │ │ ├── glyphicons-halflings-regular.svg │ │ │ ├── glyphicons-halflings-regular.ttf │ │ │ └── glyphicons-halflings-regular.woff │ │ ├── img │ │ │ ├── brand.svg │ │ │ ├── console.png │ │ │ ├── favicon.ico │ │ │ ├── spinner-lg.gif │ │ │ ├── spinner-sm.gif │ │ │ ├── spinner-xs.gif │ │ │ └── spinner.gif │ │ ├── js │ │ │ ├── bootstrap-select.min.js │ │ │ ├── bootstrap.min.js │ │ │ ├── html5shiv.min.js │ │ │ ├── jquery.min.js │ │ │ └── patternfly.min.js │ │ ├── jstree.min.js │ │ ├── libs │ │ │ ├── jquery.js │ │ │ └── require.js │ │ └── themes │ │ │ └── default │ │ │ ├── 32px.png │ │ │ ├── 40px.png │ │ │ ├── style.css │ │ │ ├── style.min.css │ │ │ └── throbber.gif │ ├── event_testing.html │ ├── failed_browser_tests.html │ ├── jenkins_report.html │ ├── pattern_base.html │ ├── smtp_result.html │ ├── template_tester_report.html │ ├── test_matrix.html │ ├── test_report.html │ ├── test_report_provider.html │ └── usage_report.html ├── ui │ ├── automate │ │ ├── ds2.xml │ │ └── test_create_snapshot_via_ae.rb │ ├── control │ │ ├── default_alerts.yaml │ │ ├── invalid.yaml │ │ └── policies.yaml │ ├── infrastructure │ │ └── test_host_provisioning │ │ │ └── vmware_esx_55.cfg │ └── intelligence │ │ ├── import_report.yaml │ │ └── import_widget.yaml ├── utils │ ├── cfmedb_load_config.rbt │ ├── cfmedb_set_config.rbt │ └── test_simple_locators │ │ └── elements.html └── vmware_esx_55_remote.cfg ├── dockerfiles ├── cfme_tests_base │ └── Dockerfile └── cfme_tests_img │ ├── Dockerfile │ └── xstartup ├── docs ├── Makefile ├── _static │ ├── .placeholder │ └── framework.png ├── conf.py ├── getting_started.rst ├── guides.rst ├── guides │ ├── abbrev.rst │ ├── browser_configuration.rst │ ├── bugzilla.rst │ ├── collections.rst │ ├── container.rst │ ├── debugging.rst │ ├── dev_guide.rst │ ├── documenting.rst │ ├── editors.rst │ ├── faq.rst │ ├── gotchas.rst │ ├── lint.rst │ ├── newprovider.rst │ ├── tipsntricks.rst │ ├── ui_modeling.rst │ └── vnc_selenium.rst ├── index.rst ├── inventory.py ├── modules.rst ├── pr_process.png └── requirements.txt ├── eng.user-words ├── entry_points.txt ├── log └── .placeholder ├── notebooks ├── BasicApplianceSetup.ipynb ├── Browser Session.ipynb ├── Interaction with Timelines Notebook.ipynb ├── MultiProcessing.ipynb └── SSUI Login.ipynb ├── pytest.ini ├── requirements.txt ├── requirements ├── .gitignore ├── __init__.py ├── constraints.txt ├── dev.txt ├── docs.txt ├── docs │ ├── positional-1.1.1-py2.py3-none-any.whl │ ├── readme.txt │ ├── yaycl-0.2.0-cp27-none-any.whl │ └── yaycl_crypt-0.2.0-cp27-none-any.whl ├── frozen.txt ├── frozen_docs.py3.txt ├── on_rtd.txt ├── package_map.yaml ├── perf.txt ├── quickstart │ └── needs.txt ├── template_docs.txt ├── template_non_imported.txt └── template_scanned_imports.txt ├── scripts ├── __init__.py ├── apishow.py ├── azure_cleanup.py ├── browser.py ├── clean_appliance.py ├── cleanup_edomain_templates.py ├── cleanup_old_vms.py ├── cleanup_openstack_fips.py ├── cleanup_openstack_instance_snapshot.py ├── cleanup_openstack_volumes.py ├── clone_domain.py ├── clone_template.py ├── coverage_report_jenkins.py ├── coverage_result.py ├── create_cu_vm.py ├── data │ ├── coverage │ │ ├── coverage_gem.rb │ │ ├── coverage_hook.rb │ │ ├── coverage_merger.rb │ │ └── manageiq-17302.patch │ └── enable-internal-db.rbt ├── ec2cleanup.py ├── enable_external_db.py ├── enable_internal_db.py ├── encrypt_conf.py ├── fetch_jenkins_artifacts.py ├── gen_ssl_cert.py ├── get_unregistered_vmware_files.py ├── gh-find.py ├── harden_security.py ├── image_upload_glance.py ├── install_netapp_lib.py ├── install_snmp_listener.py ├── install_vddk.py ├── jenkins_failure_analysis.py ├── jsongut.py ├── list_provider_vms.py ├── list_tests.py ├── loosen_pgssl_connections.py ├── mappings │ ├── metadata.json │ └── smem.json ├── matrix.py ├── ocp_cleanup.py ├── openshift │ ├── add_remove_persistent_volumes.sh │ ├── change_metrics_collection_threshold.rb │ └── create_ip_aliases.sh ├── perf_collect_logs.sh ├── post_jenkins_result.py ├── precompile_assets.py ├── print_tables.py ├── provider_usage.py ├── providers.py ├── record.py ├── refactoring │ ├── checkallimports.py │ ├── provider_move.py │ └── utils_move.py ├── restore.py ├── scap.rb ├── smtp_collector.py ├── sprout-cli.py ├── sync_template_tracker.py ├── template_tester.py ├── templates │ ├── cfme-run.smem │ └── cfme-run.summary ├── update_rhel.py ├── update_template.sh ├── utility-vm │ ├── Makefile │ ├── README │ ├── customization-script.sh │ ├── meta-data │ ├── rhel7.repo.template │ ├── rhel8.repo.template │ └── user-data.yaml └── wait_for_appliance_ui.py ├── setup.cfg ├── setup.py ├── sprout ├── .gitignore ├── README.rst ├── __init__.py ├── appliances │ ├── __init__.py │ ├── admin.py │ ├── api.py │ ├── context_processors.py │ ├── migrations │ │ ├── 0001_initial.py │ │ ├── 0002_delayedprovisiontask.py │ │ ├── 0003_auto_20141218_1534.py │ │ ├── 0004_provider_appliance_limit.py │ │ ├── 0005_template_usable.py │ │ ├── 0006_auto_20150122_1256.py │ │ ├── 0007_provider_num_simultaneous_configuring.py │ │ ├── 0008_appliance_uuid.py │ │ ├── 0009_appliancepool_provider.py │ │ ├── 0010_appliance_power_state_changed.py │ │ ├── 0011_auto_20150212_0945.py │ │ ├── 0012_template_preconfigured.py │ │ ├── 0013_appliancepool_preconfigured.py │ │ ├── 0014_group_unconfigured_template_pool_size.py │ │ ├── 0015_auto_20150324_1528.py │ │ ├── 0016_appliancepool_not_needed_anymore.py │ │ ├── 0017_appliancepool_finished.py │ │ ├── 0018_mismatchversionmailer.py │ │ ├── 0019_auto_20150430_1546.py │ │ ├── 0020_appliance_lun_disk_connected.py │ │ ├── 0021_userappliancequota.py │ │ ├── 0022_appliancepool_yum_update.py │ │ ├── 0023_provider_disabled.py │ │ ├── 0024_template_suggested_delete.py │ │ ├── 0025_auto_20160106_1446.py │ │ ├── 0026_template_parent_template.py │ │ ├── 0027_auto_20160310_1637.py │ │ ├── 0028_auto_20160311_0918.py │ │ ├── 0029_provider_hidden.py │ │ ├── 0029_provider_user_groups.py │ │ ├── 0030_bugquery.py │ │ ├── 0030_merge.py │ │ ├── 0031_auto_20160506_0848.py │ │ ├── 0031_auto_20160511_0826.py │ │ ├── 0032_merge.py │ │ ├── 0033_merge.py │ │ ├── 0034_provider_allow_renaming.py │ │ ├── 0035_auto_20160922_1635.py │ │ ├── 0036_template_ga_released.py │ │ ├── 0037_auto_20170131_1058.py │ │ ├── 0038_auto_20170131_1512.py │ │ ├── 0039_auto_20170131_1512.py │ │ ├── 0040_provider_memory_limit.py │ │ ├── 0041_auto_20170131_1518.py │ │ ├── 0042_auto_20170131_1526.py │ │ ├── 0043_auto_20170131_1609.py │ │ ├── 0044_auto_20170201_1218.py │ │ ├── 0045_auto_20170403_0918.py │ │ ├── 0046_auto_20180201_1342.py │ │ ├── 0047_auto_20180216_1634.py │ │ ├── 0048_openshift_appliances_support.py │ │ ├── 0049_provider_provider_type.py │ │ ├── 0050_template_template_type.py │ │ ├── 0051_appliancepool_template_type.py │ │ ├── 0052_remove_appliancepool_is_container.py │ │ ├── 0053_ipaddress_made_bigger.py │ │ ├── 0054_openshift_project_made_bigger.py │ │ ├── 0055_migration_to_django225.py │ │ └── __init__.py │ ├── models.py │ ├── static │ │ ├── app-js │ │ │ ├── base.js │ │ │ └── my_appliances.js │ │ ├── css │ │ ├── custom.css │ │ ├── fonts │ │ ├── img │ │ └── js │ ├── tasks │ │ ├── __init__.py │ │ ├── maintainance.py │ │ ├── provisioning.py │ │ ├── service_ops.py │ │ └── template.py │ ├── templates │ │ ├── appliances │ │ │ ├── _dates.html │ │ │ ├── _providers.html │ │ │ ├── _versions.html │ │ │ ├── apidoc.html │ │ │ ├── my_appliances.html │ │ │ ├── provider_usage.html │ │ │ ├── providers.html │ │ │ ├── shepherd.html │ │ │ ├── swap_offenders.html │ │ │ ├── template_conf.html │ │ │ ├── templates.html │ │ │ └── vms │ │ │ │ ├── _buttons.html │ │ │ │ ├── _list.html │ │ │ │ └── index.html │ │ ├── base.html │ │ ├── bugs │ │ │ ├── bugs_base.html │ │ │ ├── list_query.html │ │ │ └── new_query.html │ │ ├── index.html │ │ ├── login.html │ │ └── password.html │ ├── templatetags │ │ ├── __init__.py │ │ └── appliances_extras.py │ ├── tests.py │ ├── urls.py │ └── views.py ├── celery_runner ├── dockerfiles │ └── Dockerfile ├── logserver.py ├── manage.py ├── requirements.txt ├── sprout.sh └── sprout │ ├── __init__.py │ ├── celery.py │ ├── irc_bot.py │ ├── log.py │ ├── settings.py │ ├── urls.py │ └── wsgi.py └── widgetastic_manageiq ├── __init__.py ├── expression_editor.py └── vm_reconfigure.py /.gitattributes: -------------------------------------------------------------------------------- 1 | # Set the default behavior, in case people don't have core.autocrlf set. 2 | * text=auto 3 | 4 | # Explicitly declare text files you want to always be normalized and converted 5 | # to native line endings on checkout. 6 | *.py text 7 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/.gitmodules -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | exclude: ^(data|sprout)/ 2 | 3 | substitutions: 4 | - &exclude 5 | exclude: ^(cfme|scripts) # for now disable - we shall gradually reenable it 6 | repos: 7 | - repo: https://github.com/asottile/reorder_python_imports 8 | rev: v2.1.0 9 | hooks: 10 | - id: reorder-python-imports 11 | - repo: https://github.com/ambv/black 12 | rev: 19.10b0 13 | hooks: 14 | - id: black 15 | args: [--safe, --line-length, '100'] 16 | language_version: python3.7 17 | <<: *exclude 18 | - repo: https://github.com/asottile/pyupgrade 19 | rev: v2.1.0 20 | hooks: 21 | - id: pyupgrade 22 | language_version: python3.7 23 | args: [--py36-plus] 24 | - repo: https://gitlab.com/pycqa/flake8 25 | rev: 3.7.9 26 | hooks: 27 | - id: flake8 28 | language_version: python3.7 29 | additional_dependencies: [polarion-docstrings, bugzilla-docstrings] 30 | - repo: https://github.com/pre-commit/pre-commit-hooks 31 | rev: v2.5.0 32 | hooks: 33 | - id: trailing-whitespace 34 | - id: end-of-file-fixer 35 | - id: check-yaml 36 | - id: debug-statements 37 | exclude: ^(sprout|scripts|cfme/fixtures/rdb.py) 38 | -------------------------------------------------------------------------------- /.readthedocs.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | 3 | sphinx: 4 | configuration: docs/conf.py 5 | 6 | build: 7 | image: latest 8 | 9 | formats: [] 10 | 11 | python: 12 | version: 3.7 13 | install: 14 | - requirements: requirements/frozen_docs.py3.txt 15 | -------------------------------------------------------------------------------- /.ropeproject/config.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/.ropeproject/config.py -------------------------------------------------------------------------------- /artifactor/example_tests/artifactor_simple_example.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | from cfme.utils.log import logger as log 4 | 5 | 6 | def test_pass(): 7 | log.info("pass") 8 | 9 | 10 | @pytest.mark.skip(reason="example") 11 | def test_skip(): 12 | pass 13 | 14 | 15 | def test_skip_imp(): 16 | log.info("skip") 17 | pytest.skip("example") 18 | 19 | 20 | def test_fail(): 21 | log.info("fail") 22 | raise ValueError() 23 | -------------------------------------------------------------------------------- /artifactor/plugins/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/artifactor/plugins/__init__.py -------------------------------------------------------------------------------- /artifactor/plugins/test.py: -------------------------------------------------------------------------------- 1 | """ Test plugin for Artifactor """ 2 | import time 3 | 4 | from artifactor import ArtifactorBasePlugin 5 | 6 | 7 | class Test(ArtifactorBasePlugin): 8 | def plugin_initialize(self): 9 | self.register_plugin_hook("start_test", self.start_test) 10 | self.register_plugin_hook("finish_test", self.finish_test) 11 | 12 | def start_test(self, test_name, test_location, artifact_path): 13 | filename = artifact_path + "-" + self.ident + ".log" 14 | with open(filename, "a+") as f: 15 | f.write(test_name + "\n") 16 | f.write(str(time.time()) + "\n") 17 | for i in range(2): 18 | time.sleep(2) 19 | print("houh") 20 | 21 | def finish_test(self, test_name, artifact_path): 22 | print("finished") 23 | -------------------------------------------------------------------------------- /cfme/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/cfme/__init__.py -------------------------------------------------------------------------------- /cfme/ansible/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/cfme/ansible/__init__.py -------------------------------------------------------------------------------- /cfme/ansible_tower/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/cfme/ansible_tower/__init__.py -------------------------------------------------------------------------------- /cfme/cloud/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/cfme/cloud/__init__.py -------------------------------------------------------------------------------- /cfme/configure/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/cfme/configure/__init__.py -------------------------------------------------------------------------------- /cfme/configure/configuration/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/cfme/configure/configuration/__init__.py -------------------------------------------------------------------------------- /cfme/containers/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/cfme/containers/__init__.py -------------------------------------------------------------------------------- /cfme/containers/topology.py: -------------------------------------------------------------------------------- 1 | import attr 2 | from navmazing import NavigateToAttribute 3 | 4 | from cfme.modeling.base import BaseCollection 5 | from cfme.utils.appliance.implementations.ui import CFMENavigateStep 6 | from cfme.utils.appliance.implementations.ui import navigator 7 | 8 | 9 | @attr.s 10 | class TopologyCollection(BaseCollection): 11 | pass 12 | 13 | 14 | @navigator.register(TopologyCollection, 'All') 15 | class All(CFMENavigateStep): 16 | 17 | prerequisite = NavigateToAttribute('appliance.server', 'LoggedIn') 18 | 19 | def step(self, *args, **kwargs): 20 | self.prerequisite_view.navigation.select('Compute', 'Containers', 'Topology') 21 | -------------------------------------------------------------------------------- /cfme/control/__init__.py: -------------------------------------------------------------------------------- 1 | from cfme.control import explorer # noqa: F401 2 | from cfme.control import import_export # noqa: F401 3 | from cfme.control import log # noqa: F401 4 | from cfme.control import simulation # noqa: F401 5 | -------------------------------------------------------------------------------- /cfme/control/log.py: -------------------------------------------------------------------------------- 1 | from navmazing import NavigateToSibling 2 | from widgetastic.widget import Text 3 | from widgetastic_patternfly import Button 4 | 5 | from cfme.base import Server 6 | from cfme.common import BaseLoggedInPage 7 | from cfme.utils.appliance.implementations.ui import CFMENavigateStep 8 | from cfme.utils.appliance.implementations.ui import navigator 9 | 10 | 11 | class ControlLogView(BaseLoggedInPage): 12 | """Basic view for Control/Log tab.""" 13 | title = Text(".//div[@id='main-content']//h1") 14 | subtitle = Text(".//div[@id='main_div']/h3") 15 | refresh_button = Button(id="refresh_log") 16 | download = Button(id="fetch_log") 17 | 18 | @property 19 | def is_displayed(self): 20 | return ( 21 | self.title.text == "Log" and 22 | "Last 1000 lines from server" in self.subtitle.text and 23 | self.refresh_button.is_displayed and 24 | self.download.is_displayed 25 | ) 26 | 27 | 28 | @navigator.register(Server) 29 | class ControlLog(CFMENavigateStep): 30 | VIEW = ControlLogView 31 | prerequisite = NavigateToSibling("LoggedIn") 32 | 33 | def step(self, *args, **kwargs): 34 | self.view.navigation.select("Control", "Log") 35 | -------------------------------------------------------------------------------- /cfme/fixtures/__init__.py: -------------------------------------------------------------------------------- 1 | """A variety of modules intended to make life easier for QE developers. 2 | 3 | * :py:mod:`cfme.fixtures.login` - A module providing a login generator 4 | * :py:mod:`cfme.fixtures.pytest_selenium` - A module offering a large number 5 | of CFME optimized selenium wrappers and other auxilliary functions. 6 | """ 7 | -------------------------------------------------------------------------------- /cfme/fixtures/base.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/cfme/fixtures/base.py -------------------------------------------------------------------------------- /cfme/fixtures/cfme_data.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | from cfme.utils import conf 4 | 5 | 6 | @pytest.fixture(scope="session") 7 | def cfme_data(): 8 | return conf.cfme_data 9 | -------------------------------------------------------------------------------- /cfme/fixtures/fixtureconf.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | 4 | @pytest.fixture 5 | def fixtureconf(request): 6 | """Provides easy access to the fixtureconf dict in fixtures""" 7 | return request.node._fixtureconf 8 | -------------------------------------------------------------------------------- /cfme/fixtures/has_persistent_volume.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | 4 | @pytest.fixture(scope='function') 5 | def has_persistent_volume(provider, appliance): 6 | """Verifying that some persistent volume exists""" 7 | vols = provider.mgmt.list_persistent_volume() 8 | vols_count = len(vols) 9 | if vols_count: 10 | yield 11 | else: 12 | pytest.skip(f'No Persistent Volumes Detected on OpenShift Provider {provider.name}') 13 | -------------------------------------------------------------------------------- /cfme/fixtures/maximized.py: -------------------------------------------------------------------------------- 1 | """ 2 | Created on Mar 4, 2013 3 | 4 | @author: bcrochet 5 | """ 6 | import pytest 7 | 8 | 9 | @pytest.fixture 10 | def maximized(): 11 | # Included for backward compatibility, will be going away 12 | pass 13 | -------------------------------------------------------------------------------- /cfme/fixtures/model_collections.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | 4 | @pytest.fixture(scope='function') 5 | def dashboards(appliance): 6 | return appliance.collections.dashboards 7 | 8 | 9 | @pytest.fixture(scope="function") 10 | def objects(appliance): 11 | return appliance.collections.object_store_objects 12 | -------------------------------------------------------------------------------- /cfme/fixtures/page_screenshots.py: -------------------------------------------------------------------------------- 1 | def pytest_addoption(parser): 2 | # Create the cfme option group for use in other plugins 3 | parser.getgroup('cfme') 4 | parser.addoption("--page-screenshots", action="store_true", default=False, 5 | help="take screenshots for each page visited") 6 | -------------------------------------------------------------------------------- /cfme/fixtures/parallelizer/hooks.py: -------------------------------------------------------------------------------- 1 | """parallelizer hooks 2 | 3 | Custom hooks to help keep runtime ordering straight with regard to the parallelizer's state 4 | 5 | """ 6 | 7 | 8 | def pytest_parallel_configured(parallel_session): 9 | """called after the parallel session is configured 10 | 11 | This is *always* called, whether running parallel or not. 12 | 13 | If running standalone, ``parallel_session`` will be None. 14 | 15 | """ 16 | -------------------------------------------------------------------------------- /cfme/fixtures/perf.py: -------------------------------------------------------------------------------- 1 | """Fixtures specifically for performance tests.""" 2 | import pytest 3 | 4 | from cfme.utils.perf import get_worker_pid 5 | from cfme.utils.perf import set_rails_loglevel 6 | 7 | 8 | @pytest.fixture(scope='session') 9 | def cfme_log_level_rails_debug(): 10 | set_rails_loglevel('debug') 11 | yield 12 | set_rails_loglevel('info') 13 | 14 | 15 | @pytest.fixture(scope='module') 16 | def ui_worker_pid(): 17 | yield get_worker_pid('MiqUiWorker') 18 | -------------------------------------------------------------------------------- /cfme/fixtures/physical_switch.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | 4 | @pytest.fixture(scope="function") 5 | def physical_switch(appliance, provider, setup_provider): 6 | try: 7 | physical_switch = appliance.rest_api.collectiions.physical_switches.filter( 8 | {"provider": provider} 9 | ).all()[0] 10 | except IndexError: 11 | pytest.skip('No physical switch on provider') 12 | except AttributeError: 13 | pytest.skip('No physical switches in rest API collection') 14 | return physical_switch 15 | -------------------------------------------------------------------------------- /cfme/fixtures/portset.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | from cfme.utils import ports 4 | from cfme.utils.log import logger 5 | 6 | 7 | def pytest_addoption(parser): 8 | group = parser.getgroup('Port override') 9 | group.addoption('--port-db', 10 | action='store', 11 | default=None, 12 | dest='port_db', 13 | help="Override appliance's database port.") 14 | group.addoption('--port-ssh', 15 | action='store', 16 | default=None, 17 | dest='port_ssh', 18 | help="Override appliance's SSH port.") 19 | 20 | 21 | @pytest.hookimpl(tryfirst=True) 22 | def pytest_configure(config): 23 | if config.getoption('--help'): 24 | return 25 | # SSH 26 | port_ssh = config.getoption("port_ssh") 27 | if port_ssh is not None: 28 | logger.info("Overriding SSH port to {}.".format(str(port_ssh))) 29 | ports.SSH = int(port_ssh) 30 | # DB 31 | port_db = config.getoption("port_db") 32 | if port_db is not None: 33 | logger.info("Overriding DB port to {}.".format(str(port_db))) 34 | ports.DB = int(port_db) 35 | -------------------------------------------------------------------------------- /cfme/fixtures/prov_filter.py: -------------------------------------------------------------------------------- 1 | from cfme.utils.log import logger 2 | from cfme.utils.providers import global_filters 3 | from cfme.utils.providers import list_providers 4 | from cfme.utils.providers import ProviderFilter 5 | 6 | 7 | def pytest_addoption(parser): 8 | # Create the cfme option group for use in other plugins 9 | parser.getgroup('cfme') 10 | parser.addoption("--use-provider", action="append", default=[], 11 | help="list of provider keys or provider tags to include in test") 12 | 13 | 14 | def pytest_configure(config): 15 | """ Filters the list of providers as part of pytest configuration 16 | 17 | Note: 18 | Additional filter is added to the global_filters dict of active filters here. 19 | """ 20 | if config.getoption('--help'): 21 | return 22 | 23 | cmd_filter = config.getvalueorskip('use_provider') 24 | if not cmd_filter: 25 | cmd_filter = ["default"] 26 | 27 | new_filter = ProviderFilter(keys=cmd_filter, required_tags=cmd_filter, conjunctive=False) 28 | global_filters['use_provider'] = new_filter 29 | 30 | logger.debug('Filtering providers with {}, leaves {}'.format( 31 | cmd_filter, [prov.key for prov in list_providers()])) 32 | -------------------------------------------------------------------------------- /cfme/fixtures/pxe.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | from cfme.infrastructure.pxe import get_pxe_server_from_config 4 | 5 | 6 | @pytest.fixture 7 | def pxe_server_crud(appliance, pxe_name): 8 | return get_pxe_server_from_config(pxe_name, appliance=appliance) 9 | -------------------------------------------------------------------------------- /cfme/fixtures/randomness.py: -------------------------------------------------------------------------------- 1 | import fauxfactory 2 | import pytest 3 | 4 | 5 | @pytest.fixture # IGNORE:E1101 6 | def random_uuid_as_string(): 7 | """Creates a random uuid and returns is as a string""" 8 | return fauxfactory.gen_uuid() 9 | 10 | 11 | @pytest.fixture 12 | def random_string(): 13 | """Generate a random string for use in tests""" 14 | return fauxfactory.gen_alphanumeric(8) 15 | -------------------------------------------------------------------------------- /cfme/fixtures/sauce.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | 4 | @pytest.hookimpl(trylast=True) 5 | def pytest_runtest_teardown(item, nextitem): 6 | if item.config.getoption('sauce'): 7 | from cfme.utils.browser import ensure_browser_open, quit, browser 8 | ensure_browser_open() 9 | browser().execute_script(f"sauce:job-name={item.name}") 10 | quit() 11 | -------------------------------------------------------------------------------- /cfme/fixtures/single_appliance_sprout.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/cfme/fixtures/single_appliance_sprout.py -------------------------------------------------------------------------------- /cfme/fixtures/skip_not_implemented.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | 4 | @pytest.hookimpl(hookwrapper=True, tryfirst=True) 5 | def pytest_runtest_setup(item): 6 | """Pytest hook ensuring that failures caused by NotImplementedError show up as skips instead""" 7 | outcome = yield 8 | try: 9 | outcome.get_result() 10 | except NotImplementedError as e: 11 | pytest.skip(str(e)) 12 | 13 | 14 | @pytest.hookimpl(hookwrapper=True, tryfirst=True) 15 | def pytest_runtest_call(item): 16 | """Pytest hook ensuring that failures caused by NotImplementedError show up as skips instead""" 17 | outcome = yield 18 | try: 19 | outcome.get_result() 20 | except NotImplementedError as e: 21 | pytest.skip(str(e)) 22 | -------------------------------------------------------------------------------- /cfme/fixtures/ssh_client.py: -------------------------------------------------------------------------------- 1 | import diaper 2 | import pytest 3 | 4 | from cfme.fixtures.pytest_store import store 5 | from cfme.utils import ssh 6 | from cfme.utils.log import logger 7 | 8 | 9 | @pytest.hookimpl(hookwrapper=True) 10 | def pytest_sessionfinish(session, exitstatus): 11 | """Loop through the appliance stack and close ssh connections""" 12 | 13 | for ssh_client in store.ssh_clients_to_close: 14 | logger.debug('Closing ssh connection on %r', ssh_client) 15 | try: 16 | ssh_client.close() 17 | except Exception: 18 | logger.exception('Closing ssh connection on %r failed, but ignoring', ssh_client) 19 | for session in ssh._client_session: 20 | with diaper: 21 | session.close() 22 | yield 23 | -------------------------------------------------------------------------------- /cfme/fixtures/terminalreporter.py: -------------------------------------------------------------------------------- 1 | # FlexibleTerminalReporter is imported for backward compatibility; 2 | # it should be imported from pytest_store 3 | from cfme.fixtures.pytest_store import store 4 | from cfme.utils import diaper 5 | from cfme.utils.log import logger 6 | 7 | 8 | def reporter(config=None): 9 | """Return a py.test terminal reporter that will write to the console no matter what 10 | 11 | Only useful when trying to write to the console before or during a 12 | :py:func:`pytest_configure ` hook. 13 | 14 | """ 15 | # config arg is accepted, but no longer needed thanks to pytest_store, so it is ignored 16 | return store.terminalreporter 17 | 18 | 19 | def disable(): 20 | # Cloud be a FlexibleTerminalReporter, which is a subclass of TerminalReporter, 21 | # so match the type directly 22 | with diaper: 23 | store.pluginmanager.unregister(store.terminalreporter) 24 | logger.debug('terminalreporter disabled') 25 | 26 | 27 | def enable(): 28 | with diaper: 29 | store.pluginmanager.register(store.terminalreporter, 'terminalreporter') 30 | logger.debug('terminalreporter enabled') 31 | -------------------------------------------------------------------------------- /cfme/fixtures/update_tests.py: -------------------------------------------------------------------------------- 1 | def pytest_addoption(parser): 2 | parser.addoption('--old_version', help="update tests will update from this version") 3 | -------------------------------------------------------------------------------- /cfme/generic_objects/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/cfme/generic_objects/__init__.py -------------------------------------------------------------------------------- /cfme/generic_objects/definition/associations.py: -------------------------------------------------------------------------------- 1 | # TODO: add more association types 2 | _ASSOCIATION_TYPES_MAPPING = { 3 | 'Service': {'rest_collection': 'services'}, 4 | 'Vms': {'rest_collection': 'vms'}, 5 | } 6 | 7 | 8 | def get_rest_resource(appliance, association_type, resource): 9 | mapping = _ASSOCIATION_TYPES_MAPPING.get(association_type) 10 | if not mapping: 11 | raise NotImplementedError(f'Mapping is not implemented for `{association_type}`.') 12 | 13 | rest_collection = getattr(appliance.rest_api.collections, mapping['rest_collection']) 14 | return rest_collection.find_by(name=resource.name) 15 | -------------------------------------------------------------------------------- /cfme/infrastructure/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/cfme/infrastructure/__init__.py -------------------------------------------------------------------------------- /cfme/infrastructure/config_management/config_systems/ansible_tower.py: -------------------------------------------------------------------------------- 1 | import attr 2 | 3 | from cfme.infrastructure.config_management.config_systems import ConfigSystem 4 | from cfme.infrastructure.config_management.config_systems import ConfigSystemsCollection 5 | 6 | 7 | @attr.s 8 | class AnsibleTowerSystem(ConfigSystem): 9 | pass 10 | 11 | 12 | @attr.s 13 | class AnsibleTowerSystemsCollection(ConfigSystemsCollection): 14 | ENTITY = AnsibleTowerSystem 15 | type_name = "ansible_tower" 16 | -------------------------------------------------------------------------------- /cfme/infrastructure/config_management/config_systems/satellite.py: -------------------------------------------------------------------------------- 1 | import attr 2 | 3 | from cfme.infrastructure.config_management.config_systems import ConfigSystem 4 | from cfme.infrastructure.config_management.config_systems import ConfigSystemsCollection 5 | 6 | 7 | @attr.s 8 | class SatelliteSystem(ConfigSystem): 9 | pass 10 | 11 | 12 | @attr.s 13 | class SatelliteSystemsCollection(ConfigSystemsCollection): 14 | ENTITY = SatelliteSystem 15 | type_name = "satellite" 16 | -------------------------------------------------------------------------------- /cfme/intelligence/__init__.py: -------------------------------------------------------------------------------- 1 | """This is a directory of modules, each one represents one menu sub-item. 2 | 3 | * :py:mod:`cfme.intelligence.reports` 4 | * :py:mod:`cfme.intelligence.chargeback` 5 | """ 6 | -------------------------------------------------------------------------------- /cfme/intelligence/chargeback/__init__.py: -------------------------------------------------------------------------------- 1 | from widgetastic.widget import View 2 | from widgetastic_patternfly import Accordion 3 | 4 | from cfme.common import BaseLoggedInPage 5 | from widgetastic_manageiq import ManageIQTree 6 | 7 | 8 | class ChargebackView(BaseLoggedInPage): 9 | 10 | @property 11 | def in_chargeback(self): 12 | return ( 13 | self.logged_in_as_current_user 14 | and self.navigation.currently_selected == ['Overview', 'Chargeback'] 15 | ) 16 | 17 | @property 18 | def is_displayed(self): 19 | return self.in_chargeback 20 | 21 | @View.nested 22 | class reports(Accordion): # noqa 23 | tree = ManageIQTree() 24 | 25 | @View.nested 26 | class rates(Accordion): # noqa 27 | tree = ManageIQTree() 28 | 29 | @View.nested 30 | class assignments(Accordion): # noqa 31 | tree = ManageIQTree() 32 | -------------------------------------------------------------------------------- /cfme/intelligence/rss.py: -------------------------------------------------------------------------------- 1 | from cfme.common import BaseLoggedInPage 2 | from widgetastic_manageiq import Table 3 | 4 | 5 | class RSSView(BaseLoggedInPage): 6 | 7 | table = Table('//div[@id="tab_div"]/table') 8 | 9 | @property 10 | def is_displayed(self): 11 | return ( 12 | self.logged_in_as_current_user 13 | and self.navigation.currently_selected == ['Overview', 'RSS'] 14 | ) 15 | -------------------------------------------------------------------------------- /cfme/intelligence/timelines.py: -------------------------------------------------------------------------------- 1 | from widgetastic.widget import View 2 | from widgetastic_patternfly import Accordion 3 | 4 | from cfme.common import BaseLoggedInPage 5 | from widgetastic_manageiq import ManageIQTree 6 | from widgetastic_manageiq import TimelinesChart 7 | 8 | 9 | class CloudIntelTimelinesView(BaseLoggedInPage): 10 | 11 | chart = TimelinesChart(locator='//div/*[@class="timeline-pf-chart"]') 12 | 13 | @property 14 | def is_displayed(self): 15 | return ( 16 | self.logged_in_as_current_user 17 | and self.navigation.currently_selected == ['Overview', 'Timelines'] 18 | ) 19 | 20 | @View.nested 21 | class timelines(Accordion): # noqa 22 | tree = ManageIQTree() 23 | -------------------------------------------------------------------------------- /cfme/markers/__init__.py: -------------------------------------------------------------------------------- 1 | # look at conftest for plugin loading via entrypoints 2 | -------------------------------------------------------------------------------- /cfme/markers/crud.py: -------------------------------------------------------------------------------- 1 | """crud: Marker for marking the test as a CRUD test (crud) 2 | 3 | Useful for eg. running only crud tests. 4 | Tests will be marked automatically if: 5 | 6 | * their name starts with crud_ 7 | * their name ends with _crud 8 | * their name contains _crud_ 9 | """ 10 | import re 11 | 12 | matcher = re.compile(r'^crud_|_crud_|_crud$') 13 | marker = "crud" 14 | 15 | 16 | def pytest_configure(config): 17 | config.addinivalue_line('markers', __doc__.splitlines()[0]) 18 | 19 | 20 | def pytest_itemcollected(item): 21 | if matcher.search(item.name) is not None: 22 | item.add_marker(marker) 23 | item.extra_keyword_matches.add(marker) 24 | -------------------------------------------------------------------------------- /cfme/markers/destructive.py: -------------------------------------------------------------------------------- 1 | # register the non_destructive marker 2 | # for use on tests that are non-destructive to the appliance, and can be run concurrently 3 | 4 | 5 | def pytest_configure(config): 6 | config.addinivalue_line( 7 | 'markers', 8 | 'non_destructive: mark tests that are non-destructive to the appliance' 9 | ) 10 | -------------------------------------------------------------------------------- /cfme/markers/env_markers/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/cfme/markers/env_markers/__init__.py -------------------------------------------------------------------------------- /cfme/markers/fixtureconf.py: -------------------------------------------------------------------------------- 1 | """fixtureconf: Marker for passing args and kwargs to test fixtures 2 | 3 | Positional and keyword arguments to this marker will be stored on test items 4 | in the _fixtureconf attribute (dict). kwargs will be stored as-is, the args 5 | tuple will be packed into the dict under the 'args' key. 6 | 7 | Use the "fixtureconf" fixture in tests to easily access the fixtureconf dict 8 | """ 9 | 10 | 11 | def pytest_configure(config): 12 | config.addinivalue_line('markers', __doc__.splitlines()[0]) 13 | 14 | 15 | def pytest_runtest_setup(item): 16 | fixtureconf_mark = item.get_closest_marker('fixtureconf') 17 | args = getattr(fixtureconf_mark, 'args', tuple()) 18 | kwargs = getattr(fixtureconf_mark, 'kwargs', dict()) 19 | fixtureconf = dict() 20 | fixtureconf['args'] = args 21 | fixtureconf.update(kwargs) 22 | # "item" becomes "request.node" in fixtures down the line 23 | # remember to use the request fixture in fixture funcargs 24 | item._fixtureconf = fixtureconf 25 | -------------------------------------------------------------------------------- /cfme/markers/isolation.py: -------------------------------------------------------------------------------- 1 | """Marker for browser isolation on specific tests""" 2 | import pytest 3 | 4 | from cfme.test_framework.browser_isolation import browser_implementation_quits 5 | from cfme.utils.log import logger 6 | 7 | 8 | # Add Marker 9 | def pytest_configure(config): 10 | config.addinivalue_line('markers', 'browser_isolation: Mark a test case for browser isolation') 11 | 12 | 13 | @pytest.hookimpl(hookwrapper=True, tryfirst=True) 14 | def pytest_runtest_setup(item): 15 | if item.get_closest_marker('browser_isolation'): 16 | logger.info('Browser isolation for marker in setup') 17 | browser_implementation_quits(item) 18 | yield 19 | 20 | 21 | @pytest.hookimpl(hookwrapper=True, trylast=True) 22 | def pytest_runtest_teardown(item, nextitem): 23 | yield 24 | if item.get_closest_marker("browser_isolation"): 25 | logger.info('Browser isolation for marker in teardown') 26 | browser_implementation_quits(item) 27 | -------------------------------------------------------------------------------- /cfme/markers/manual.py: -------------------------------------------------------------------------------- 1 | """manual: Marker for marking tests as manual tests.""" 2 | import pytest 3 | 4 | from cfme.fixtures.pytest_store import store 5 | 6 | 7 | def pytest_configure(config): 8 | config.addinivalue_line("markers", __doc__.splitlines()[0]) 9 | 10 | 11 | def pytest_addoption(parser): 12 | """Adds options for the composite uncollection system""" 13 | parser.addoption("--manual", action="store_true", default=False, 14 | help="Collect manual tests (only for --collect-only)") 15 | parser.addoption("--include-manual", action="store_true", default=False, 16 | help="Collect also manual tests (only for --collect-only)") 17 | 18 | 19 | @pytest.hookimpl(tryfirst=True) 20 | def pytest_collection_modifyitems(session, config, items): 21 | if config.getvalue('include_manual'): 22 | return 23 | is_manual = config.getvalue('manual') 24 | 25 | keep, discard = [], [] 26 | for item in items: 27 | if bool(item.get_closest_marker("manual")) == is_manual: 28 | keep.append(item) 29 | else: 30 | discard.append(item) 31 | 32 | items[:] = keep 33 | config.hook.pytest_deselected(items=discard) 34 | 35 | store.uncollection_stats['manual'] = len(discard) 36 | -------------------------------------------------------------------------------- /cfme/markers/perf.py: -------------------------------------------------------------------------------- 1 | # auto-mark items in the perf directory with perf marker 2 | import pytest 3 | 4 | 5 | @pytest.hookimpl(tryfirst=True) 6 | def pytest_collection_modifyitems(session, config, items): 7 | # mark all perf tests here so we don't have to maintain the mark in those modules 8 | for item in items: 9 | if item.nodeid.startswith('cfme/tests/perf'): 10 | item.add_marker(pytest.mark.perf) 11 | -------------------------------------------------------------------------------- /cfme/markers/regression.py: -------------------------------------------------------------------------------- 1 | # register the regression marker 2 | # for use on tests that dare written for regressions 3 | 4 | 5 | def pytest_configure(config): 6 | config.addinivalue_line( 7 | 'markers', 8 | 'regression: mark tests written for regressions' 9 | ) 10 | -------------------------------------------------------------------------------- /cfme/markers/rhel_tests.py: -------------------------------------------------------------------------------- 1 | # register the rhel_testing marker 2 | # for use on tests that deal directly with the OS that MIQ/CFME is running in 3 | 4 | 5 | def pytest_configure(config): 6 | config.addinivalue_line( 7 | 'markers', 8 | 'rhel_testing: mark tests that deal with the base OS directly' 9 | ) 10 | -------------------------------------------------------------------------------- /cfme/markers/sauce.py: -------------------------------------------------------------------------------- 1 | """sauce: Mark a test to run on sauce 2 | 3 | Mark a single test to run on sauce. 4 | 5 | """ 6 | 7 | 8 | def pytest_addoption(parser): 9 | group = parser.getgroup('cfme') 10 | group.addoption('--sauce', dest='sauce', action='store_true', default=False, 11 | help="Run tests with the sauce marker on sauce labs.") 12 | 13 | 14 | def pytest_configure(config): 15 | config.addinivalue_line('markers', __doc__.splitlines()[0]) 16 | if config.option.sauce: 17 | if config.option.markexpr: 18 | config.option.markexpr = f'sauce and ({config.option.markexpr})' 19 | else: 20 | config.option.markexpr = 'sauce' 21 | -------------------------------------------------------------------------------- /cfme/markers/serial.py: -------------------------------------------------------------------------------- 1 | """ 2 | serial: Marker for marking test modules as "serial" tests. Serial is in quotes because this is not 3 | meant to guarantee that tests will run in a specific order but instead meant to make sure 4 | that all the tests in the test module will be sent to a single slave. 5 | 6 | The parallelizer is designed to divy up tests to slaves according to their parametrization. 7 | So tests with similar parameters end up going to the same slave. The problem this marker 8 | seeks to address is when the same fixture is evaluated on multiple slaves. When the auth 9 | tests were changed to use a temp appliance, this resulted in a new temp appliance being 10 | pulled for each slave that the tests were sent to. This created an unnecessary load on 11 | sprout and resulted in test errors due to not receiving an appliance. 12 | 13 | IMPORTANT: The serial marker SHOULD NOT be used on provider parametrized test cases, this 14 | will result in lengthy test runs due to having to constantly setup and tear down providers. 15 | """ 16 | 17 | 18 | def pytest_configure(config): 19 | config.addinivalue_line( 20 | 'markers', 21 | 'serial: Mark a test case to run serially (all parameters on a single appliance)' 22 | ) 23 | -------------------------------------------------------------------------------- /cfme/metaplugins/__init__.py: -------------------------------------------------------------------------------- 1 | pytest_plugins = [ 2 | 'cfme.metaplugins.blockers', 3 | 'cfme.metaplugins.server_roles', 4 | ] 5 | -------------------------------------------------------------------------------- /cfme/modeling/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/cfme/modeling/__init__.py -------------------------------------------------------------------------------- /cfme/modeling/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/cfme/modeling/tests/__init__.py -------------------------------------------------------------------------------- /cfme/networks/topology.py: -------------------------------------------------------------------------------- 1 | from navmazing import NavigateToAttribute 2 | 3 | from cfme.common.topology import BaseTopologyElementsCollection 4 | from cfme.common.topology import BaseTopologyView 5 | from cfme.utils.appliance.implementations.ui import CFMENavigateStep 6 | from cfme.utils.appliance.implementations.ui import navigator 7 | 8 | 9 | class NetworkTopologyView(BaseTopologyView): 10 | 11 | @property 12 | def is_displayed(self): 13 | return ( 14 | self.logged_in_as_current_user and 15 | self.navigation.currently_selected == ["Networks", "Topology"] 16 | ) 17 | 18 | 19 | class NetworkTopologyElementsCollection(BaseTopologyElementsCollection): 20 | pass 21 | 22 | 23 | @navigator.register(NetworkTopologyElementsCollection) 24 | class All(CFMENavigateStep): 25 | VIEW = NetworkTopologyView 26 | prerequisite = NavigateToAttribute("appliance.server", "LoggedIn") 27 | 28 | def step(self, *args, **kwargs): 29 | self.view.navigation.select("Networks", "Topology") 30 | -------------------------------------------------------------------------------- /cfme/optimize/__init__.py: -------------------------------------------------------------------------------- 1 | from navmazing import NavigateToSibling 2 | from widgetastic.widget import View 3 | 4 | from cfme.base import Server 5 | from cfme.common import BaseLoggedInPage 6 | from cfme.utils.appliance.implementations.ui import CFMENavigateStep 7 | from cfme.utils.appliance.implementations.ui import navigator 8 | from widgetastic_manageiq import Accordion 9 | from widgetastic_manageiq import ManageIQTree 10 | 11 | 12 | class BottlenecksView(BaseLoggedInPage): 13 | def in_explorer(self): 14 | return ( 15 | self.logged_in_as_current_user and 16 | self.navigation.currently_selected == ['Optimize', 'Bottlenecks']) 17 | 18 | @View.nested 19 | class bottlenecks(Accordion): # noqa 20 | ACCORDION_NAME = "Bottlenecks" 21 | 22 | tree = ManageIQTree() 23 | 24 | 25 | @navigator.register(Server) 26 | class Bottlenecks(CFMENavigateStep): 27 | VIEW = BottlenecksView 28 | prerequisite = NavigateToSibling("LoggedIn") 29 | 30 | def step(self, *args, **kwargs): 31 | self.view.navigation.select("Optimize", "Bottlenecks") 32 | -------------------------------------------------------------------------------- /cfme/physical/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/cfme/physical/__init__.py -------------------------------------------------------------------------------- /cfme/rest/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/cfme/rest/__init__.py -------------------------------------------------------------------------------- /cfme/rest/abc.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/cfme/rest/abc.py -------------------------------------------------------------------------------- /cfme/scripting/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/cfme/scripting/__init__.py -------------------------------------------------------------------------------- /cfme/scripting/disable_bytecode.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | from os import path 3 | 4 | from cfme.utils.log import logger 5 | 6 | 7 | DISABLE_BYTECODE = "import sys\nsys.dont_write_bytecode = True\n" 8 | 9 | 10 | def ensure_file_contains(target, content): 11 | if path.exists(target): 12 | with open(target) as fp: 13 | if content not in fp.read(): 14 | print(f'{target!r} has unexpected content') 15 | print('please open the file and add the following:') 16 | print(content) 17 | print("# end") 18 | else: 19 | with open(target, 'w') as fp: 20 | fp.write(content) 21 | 22 | 23 | if __name__ == '__main__': 24 | try: 25 | import site 26 | site_packages = site.getsitepackages()[0] 27 | print(site_packages) 28 | target = path.join(site_packages, 'sitecustomize.py') 29 | ensure_file_contains(target, content=DISABLE_BYTECODE) 30 | except AttributeError: 31 | logger.warning('bytecode NOT disabled, site.getsitepackages not found.' 32 | 'Something is wrong with the site module, due to virtualenv creation.') 33 | -------------------------------------------------------------------------------- /cfme/scripting/quickstart/__main__.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | from cfme.scripting.quickstart import IN_VIRTUAL_ENV 4 | from cfme.scripting.quickstart import main 5 | from cfme.scripting.quickstart import mk_parser 6 | IS_SCRIPT = sys.argv[0] == __file__ 7 | 8 | if IS_SCRIPT: 9 | if IN_VIRTUAL_ENV: 10 | parser = mk_parser(sys.prefix) 11 | else: 12 | parser = mk_parser('.cfme_venv') 13 | main(parser.parse_args()) 14 | -------------------------------------------------------------------------------- /cfme/scripting/quickstart/proc.py: -------------------------------------------------------------------------------- 1 | import os 2 | import subprocess 3 | import sys 4 | from pipes import quote 5 | 6 | 7 | PRISTINE_ENV = dict(os.environ) 8 | if PRISTINE_ENV.get('CFME_QUICKSTART_DEBUG'): 9 | _call = subprocess.check_call 10 | else: 11 | _call = subprocess.check_output 12 | 13 | 14 | def command_text(command, shell): 15 | if shell: 16 | return command 17 | else: 18 | return ' '.join(map(quote, command)) 19 | 20 | 21 | def run_cmd_or_exit(command, shell=False, long_running=False, 22 | call=_call, **kw): 23 | res = None 24 | try: 25 | if long_running: 26 | print( 27 | 'QS $', command_text(command, shell), 28 | '# this may take some time to finish ...') 29 | else: 30 | print('QS $', command_text(command, shell)) 31 | res = call(command, shell=shell, **kw) 32 | except Exception as e: 33 | print("Running command failed!") 34 | print(repr(e)) 35 | sys.exit(1) 36 | return res 37 | -------------------------------------------------------------------------------- /cfme/scripting/runtest.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | 4 | from cfme.scripting import quickstart 5 | QUICKSTART_DONE = 'MIQ_RUNTEST_QUICKSTART_DONE' 6 | 7 | 8 | def main(): 9 | if QUICKSTART_DONE not in os.environ: 10 | quickstart.main(quickstart.args_for_current_venv()) 11 | os.environ[QUICKSTART_DONE] = QUICKSTART_DONE 12 | os.execl(sys.executable, sys.executable, *sys.argv) 13 | else: 14 | import pytest 15 | return pytest.main() 16 | -------------------------------------------------------------------------------- /cfme/scripting/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/cfme/scripting/tests/__init__.py -------------------------------------------------------------------------------- /cfme/services/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/cfme/services/__init__.py -------------------------------------------------------------------------------- /cfme/services/dashboard/__init__.py: -------------------------------------------------------------------------------- 1 | import importscan 2 | import sentaku 3 | 4 | from cfme.utils.appliance import Navigatable 5 | 6 | 7 | class Dashboard(Navigatable, sentaku.modeling.ElementMixin): 8 | """ Dashboard main class for SSUI.""" 9 | 10 | num_of_rows = sentaku.ContextualMethod() 11 | results = sentaku.ContextualMethod() 12 | total_services = sentaku.ContextualMethod() 13 | total_requests = sentaku.ContextualMethod() 14 | retiring_soon = sentaku.ContextualMethod() 15 | current_services = sentaku.ContextualMethod() 16 | retired_services = sentaku.ContextualMethod() 17 | monthly_charges = sentaku.ContextualMethod() 18 | pending_requests = sentaku.ContextualMethod() 19 | approved_requests = sentaku.ContextualMethod() 20 | denied_requests = sentaku.ContextualMethod() 21 | 22 | def __init__(self, appliance): 23 | self.appliance = appliance 24 | self.parent = self.appliance.context 25 | 26 | 27 | from cfme.services.dashboard import ssui # NOQA last for import cycles 28 | importscan.scan(ssui) 29 | -------------------------------------------------------------------------------- /cfme/services/myservice/rest.py: -------------------------------------------------------------------------------- 1 | from cfme.services.myservice import MyService 2 | from cfme.utils.appliance import MiqImplementationContext 3 | from cfme.utils.appliance.implementations.rest import ViaREST 4 | 5 | 6 | @MiqImplementationContext.external_for(MyService.add_resource_generic_object, ViaREST) 7 | def add_resource_generic_object(self, gen_obj): 8 | """ Add a generic object instance to the service """ 9 | self.rest_api_entity.action.add_resource( 10 | resource=self.appliance.rest_api.collections.generic_objects.get( 11 | name=gen_obj.name 12 | )._ref_repr() 13 | ) 14 | 15 | 16 | @MiqImplementationContext.external_for(MyService.retire, ViaREST) 17 | def retire(self, wait=True): 18 | retire_request = self.rest_api_entity.action.request_retire() 19 | service_request = self.appliance.collections.requests.instantiate( 20 | description=retire_request.description 21 | ) 22 | if wait: 23 | service_request.wait_for_request() 24 | return service_request 25 | -------------------------------------------------------------------------------- /cfme/storage/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/cfme/storage/__init__.py -------------------------------------------------------------------------------- /cfme/test_framework/__init__.py: -------------------------------------------------------------------------------- 1 | import warnings 2 | with warnings.catch_warnings(): 3 | warnings.simplefilter('ignore', ImportWarning) 4 | __import__('oslo_i18n') 5 | -------------------------------------------------------------------------------- /cfme/test_framework/pytest_plugin.py: -------------------------------------------------------------------------------- 1 | """ 2 | cfme main plugin 3 | 4 | This provides the option group and disables pytest logging plugin 5 | 6 | Also provides uncollection stats during testrun/collection 7 | """ 8 | import pytest 9 | 10 | 11 | @pytest.hookimpl(tryfirst=True) 12 | def pytest_addoption(parser): 13 | # Create the cfme option group for use in other plugins 14 | parser.getgroup('cfme', 'cfme: options related to cfme/miq appliances') 15 | 16 | 17 | def pytest_configure(config): 18 | # also disable the pytest logging system since its triggering issues with our own 19 | config.pluginmanager.set_blocked('logging-plugin') 20 | 21 | 22 | def pytest_collection_finish(session): 23 | from cfme.fixtures.pytest_store import store 24 | store.terminalreporter.write( 25 | "Uncollection Stats:\n", bold=True) 26 | 27 | for reason, value in store.uncollection_stats.items(): 28 | store.terminalreporter.write( 29 | f" {reason}: {value}\n", bold=True) 30 | store.terminalreporter.write( 31 | " {} tests left after all uncollections\n".format(len(session.items)), 32 | bold=True) 33 | -------------------------------------------------------------------------------- /cfme/test_framework/sprout/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/cfme/test_framework/sprout/__init__.py -------------------------------------------------------------------------------- /cfme/tests/.polarion_tests: -------------------------------------------------------------------------------- 1 | Marker for directory containing Polarion tests. 2 | -------------------------------------------------------------------------------- /cfme/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/cfme/tests/__init__.py -------------------------------------------------------------------------------- /cfme/tests/cloud/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/cfme/tests/cloud/__init__.py -------------------------------------------------------------------------------- /cfme/tests/cloud/test_instance_reconfigure.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | from cfme import test_requirements 4 | from cfme.cloud.provider.openstack import OpenStackProvider 5 | from cfme.markers.env_markers.provider import ONE_PER_TYPE 6 | from cfme.utils.appliance import ViaREST 7 | from cfme.utils.appliance import ViaUI 8 | 9 | 10 | pytestmark = [ 11 | pytest.mark.usefixtures('setup_provider'), 12 | pytest.mark.long_running, 13 | ] 14 | 15 | 16 | @pytest.mark.manual 17 | @pytest.mark.tier(2) 18 | @pytest.mark.parametrize('context', [ViaREST, ViaUI]) 19 | @pytest.mark.provider([OpenStackProvider], required_fields=['templates'], selector=ONE_PER_TYPE) 20 | @test_requirements.multi_region 21 | @test_requirements.reconfigure 22 | def test_vm_reconfigure_from_global_region(context): 23 | """ 24 | reconfigure a VM via CA 25 | 26 | Polarion: 27 | assignee: tpapaioa 28 | caseimportance: medium 29 | casecomponent: Infra 30 | initialEstimate: 1/3h 31 | testSteps: 32 | 1. Have a VM created in the provider in the Remote region which is 33 | subscribed to Global. 34 | 2. Reconfigure the VM using the Global appliance. 35 | expectedResults: 36 | 1. 37 | 2. VM reconfigured, no errors. 38 | """ 39 | pass 40 | -------------------------------------------------------------------------------- /cfme/tests/cloud_infra_common/__init__.py: -------------------------------------------------------------------------------- 1 | """This package contains tests that test functionality that is shared between Cloud and Infra.""" 2 | -------------------------------------------------------------------------------- /cfme/tests/cloud_infra_common/test_snapshots.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | from cfme.cloud.provider.openstack import OpenStackProvider 4 | from cfme.infrastructure.provider.rhevm import RHEVMProvider 5 | from cfme.infrastructure.provider.virtualcenter import VMwareProvider 6 | 7 | 8 | pytestmark = [ 9 | pytest.mark.long_running, 10 | pytest.mark.tier(2), 11 | pytest.mark.manual, 12 | pytest.mark.provider([VMwareProvider, RHEVMProvider, OpenStackProvider], scope='module'), 13 | ] 14 | 15 | 16 | @pytest.mark.meta(coverage=[1708758]) 17 | def test_snapshot_image_copies_system_info(): 18 | """ 19 | Verify that system info is copied to image during making a snapshot of vm 20 | 21 | Polarion: 22 | assignee: prichard 23 | casecomponent: Appliance 24 | initialEstimate: 1/2h 25 | tags: smartstate, providers 26 | testSteps: 27 | 1. Add a Provider. 28 | 2. provision vm and make sure it has os_version and os_distro set 29 | 3. make an image of it by creating snapshot 30 | expectedResults: 31 | 1. 32 | 2. 33 | 3. vm/system info is present in the image 34 | """ 35 | -------------------------------------------------------------------------------- /cfme/tests/configure/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/cfme/tests/configure/__init__.py -------------------------------------------------------------------------------- /cfme/tests/configure/test_about.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | from cfme import test_requirements 4 | from cfme.configure import about 5 | 6 | pytestmark = [test_requirements.general_ui] 7 | 8 | 9 | @pytest.mark.ignore_stream("5.10") 10 | @pytest.mark.meta(automates=[1402112]) 11 | def test_about_region(appliance): 12 | """ 13 | Polarion: 14 | assignee: pvala 15 | casecomponent: WebUI 16 | caseimportance: medium 17 | initialEstimate: 1/4h 18 | testSteps: 19 | 1. Open `About` modal and check the value of Region. 20 | 21 | Bugzilla: 22 | 1402112 23 | """ 24 | about_version = about.get_detail(about.REGION, appliance.server) 25 | assert about_version == appliance.region()[-1] 26 | 27 | 28 | @pytest.mark.ignore_stream("5.10") 29 | @pytest.mark.meta(automates=[1402112]) 30 | def test_about_zone(appliance): 31 | """ 32 | Polarion: 33 | assignee: pvala 34 | casecomponent: WebUI 35 | caseimportance: medium 36 | initialEstimate: 1/4h 37 | testSteps: 38 | 1. Open `About` modal and check the value of Zone. 39 | 40 | Bugzilla: 41 | 1402112 42 | """ 43 | about_version = about.get_detail(about.ZONE, appliance.server) 44 | assert about_version == appliance.server.zone.name 45 | -------------------------------------------------------------------------------- /cfme/tests/configure/test_email.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | from cfme import test_requirements 4 | from cfme.utils.wait import wait_for 5 | 6 | 7 | pytestmark = [ 8 | test_requirements.configuration, 9 | pytest.mark.rhel_testing, 10 | pytest.mark.tier(3) 11 | ] 12 | 13 | 14 | def test_send_test_email(smtp_test, random_string, appliance): 15 | """ This test checks whether the mail sent for testing really arrives. 16 | 17 | Polarion: 18 | assignee: tpapaioa 19 | casecomponent: Configuration 20 | caseimportance: critical 21 | initialEstimate: 1/10h 22 | """ 23 | e_mail = random_string + "@email.test" 24 | appliance.server.settings.send_test_email(email=e_mail) 25 | wait_for(lambda: len(smtp_test.get_emails(to_address=e_mail)) > 0, num_sec=60) 26 | -------------------------------------------------------------------------------- /cfme/tests/configure/test_version.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | from cfme import test_requirements 4 | from cfme.configure import about 5 | 6 | 7 | @test_requirements.appliance 8 | @pytest.mark.tier(3) 9 | @pytest.mark.sauce 10 | def test_appliance_version(appliance): 11 | """Check version presented in UI against version retrieved directly from the machine. 12 | 13 | Version retrieved from appliance is in this format: 1.2.3.4 14 | Version in the UI is always: 1.2.3.4.20140505xyzblabla 15 | 16 | So we check whether the UI version starts with SSH version 17 | 18 | Polarion: 19 | assignee: jhenner 20 | casecomponent: Appliance 21 | caseimportance: high 22 | initialEstimate: 1/4h 23 | """ 24 | ssh_version = str(appliance.version) 25 | ui_version = about.get_detail(about.VERSION, server=appliance.server) 26 | assert ui_version.startswith(ssh_version), f"UI: {ui_version}, SSH: {ssh_version}" 27 | -------------------------------------------------------------------------------- /cfme/tests/configure/test_vmware_console_settings.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | 4 | @pytest.mark.tier(3) 5 | @pytest.mark.sauce 6 | def test_vmware_console_support(request, appliance): 7 | """Tests that the VMware Console Support setting may be changed. 8 | 9 | Polarion: 10 | assignee: apagac 11 | caseimportance: medium 12 | casecomponent: Appliance 13 | initialEstimate: 1/4h 14 | """ 15 | old_vm_console_type = appliance.server.settings.vmware_console_values['console_type'] 16 | # Set back to original console type 17 | request.addfinalizer( 18 | lambda: appliance.server.settings.update_vmware_console( 19 | {'console_type': old_vm_console_type} 20 | ) 21 | ) 22 | assert old_vm_console_type, "The default VMware console type should not be empty" 23 | 24 | for new_vm_console_type in appliance.server.settings.CONSOLE_TYPES: 25 | appliance.server.settings.update_vmware_console({'console_type': new_vm_console_type}) 26 | 27 | cur_vm_console_type = appliance.server.settings.vmware_console_values['console_type'] 28 | assert cur_vm_console_type == new_vm_console_type 29 | -------------------------------------------------------------------------------- /cfme/tests/containers/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/cfme/tests/containers/__init__.py -------------------------------------------------------------------------------- /cfme/tests/containers/test_alerts.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | from cfme import test_requirements 4 | from cfme.containers.provider import ContainersProvider 5 | 6 | 7 | pytestmark = [ 8 | pytest.mark.provider(classes=[ContainersProvider], required_flags=['prometheus_alerts']), 9 | test_requirements.containers 10 | ] 11 | 12 | # TODO There needs to be more to this test 13 | 14 | 15 | def test_add_alerts_provider(provider): 16 | """ 17 | Polarion: 18 | assignee: juwatts 19 | initialEstimate: 1/4h 20 | caseimportance: low 21 | casecomponent: Containers 22 | """ 23 | provider.setup() 24 | -------------------------------------------------------------------------------- /cfme/tests/containers/test_reload_button_provider.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | from cfme import test_requirements 4 | from cfme.containers.provider import ContainersProvider 5 | 6 | 7 | pytestmark = [ 8 | pytest.mark.usefixtures('setup_provider'), 9 | pytest.mark.tier(2), 10 | pytest.mark.provider([ContainersProvider], scope='function'), 11 | test_requirements.containers 12 | ] 13 | 14 | 15 | def test_reload_button_provider(provider): 16 | """ This test verifies the data integrity of the fields in 17 | the Relationships table after clicking the "reload" 18 | button. 19 | 20 | Polarion: 21 | assignee: juwatts 22 | caseimportance: high 23 | casecomponent: Containers 24 | initialEstimate: 1/6h 25 | """ 26 | 27 | provider.validate_stats(ui=True) 28 | -------------------------------------------------------------------------------- /cfme/tests/distributed/test_appliance_file_permissions.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | from cfme import test_requirements 4 | 5 | pytestmark = [test_requirements.distributed] 6 | 7 | 8 | @pytest.mark.tier(1) 9 | @pytest.mark.uncollectif(lambda appliance: appliance.is_pod, 10 | reason="it isn't applicable to pod appliance") 11 | def test_v2_key_permissions(appliance): 12 | """Verifies that the v2_key has proper permissions 13 | 14 | Polarion: 15 | assignee: tpapaioa 16 | casecomponent: Configuration 17 | initialEstimate: 1/60h 18 | """ 19 | stdout = appliance.ssh_client.run_command( 20 | "stat --format '%a' /var/www/miq/vmdb/certs/v2_key").output 21 | assert int(stdout) == 400 22 | -------------------------------------------------------------------------------- /cfme/tests/infrastructure/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/cfme/tests/infrastructure/__init__.py -------------------------------------------------------------------------------- /cfme/tests/infrastructure/test_iso_datastore.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | from cfme import test_requirements 4 | from cfme.infrastructure import pxe 5 | from cfme.infrastructure.provider import InfraProvider 6 | 7 | 8 | pytestmark = [ 9 | pytest.mark.usefixtures('uses_infra_providers'), 10 | pytest.mark.tier(2), 11 | pytest.mark.provider([InfraProvider], required_fields=[('iso_datastore', True)]), 12 | ] 13 | 14 | 15 | @pytest.fixture() 16 | def no_iso_dss(provider): 17 | template_crud = pxe.ISODatastore(provider.name) 18 | if template_crud.exists(): 19 | template_crud.delete(cancel=False) 20 | 21 | 22 | @test_requirements.rhev 23 | def test_iso_datastore_crud(setup_provider, no_iso_dss, provider): 24 | """ 25 | Basic CRUD test for ISO datastores. 26 | 27 | Note: 28 | An ISO datastore cannot be edited. 29 | 30 | Metadata: 31 | test_flag: iso 32 | 33 | Polarion: 34 | assignee: jhenner 35 | initialEstimate: 1/4h 36 | casecomponent: Infra 37 | caseimportance: critical 38 | """ 39 | template_crud = pxe.ISODatastore(provider.name) 40 | template_crud.create() 41 | template_crud.delete(cancel=False) 42 | -------------------------------------------------------------------------------- /cfme/tests/infrastructure/test_pxe.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | from cfme import test_requirements 4 | from cfme.infrastructure import pxe 5 | from cfme.utils.testgen import generate 6 | from cfme.utils.testgen import pxe_servers 7 | from cfme.utils.update import update 8 | 9 | 10 | pytest_generate_tests = generate(gen_func=pxe_servers) 11 | 12 | 13 | @pytest.fixture(scope='function') 14 | def has_no_pxe_servers(): 15 | pxe.remove_all_pxe_servers() 16 | 17 | 18 | @pytest.mark.tier(2) 19 | @pytest.mark.usefixtures('has_no_pxe_servers') 20 | @test_requirements.provision 21 | def test_pxe_server_crud(pxe_name, pxe_server_crud): 22 | """ 23 | Basic Add test for PXE server including refresh. 24 | 25 | Polarion: 26 | assignee: jhenner 27 | casecomponent: Provisioning 28 | caseimportance: medium 29 | initialEstimate: 1/6h 30 | upstream: yes 31 | """ 32 | pxe_server_crud.create(refresh_timeout=300) 33 | with update(pxe_server_crud): 34 | pxe_server_crud.name = f"{pxe_server_crud.name}_update" 35 | pxe_server_crud.delete(cancel=False) 36 | -------------------------------------------------------------------------------- /cfme/tests/infrastructure/test_vm_engine_relationship.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | from cfme import test_requirements 4 | from cfme.infrastructure.provider import InfraProvider 5 | from cfme.infrastructure.virtual_machines import InfraVm 6 | from cfme.markers.env_markers.provider import ONE_PER_TYPE 7 | 8 | pytestmark = [ 9 | pytest.mark.tier(2), 10 | pytest.mark.provider(classes=[InfraProvider], selector=ONE_PER_TYPE), 11 | pytest.mark.usefixtures('setup_provider'), 12 | test_requirements.rhev, 13 | test_requirements.general_ui 14 | ] 15 | 16 | 17 | @pytest.mark.meta(automates=[1534400]) 18 | def test_edit_management_relationship(appliance, create_vm): 19 | """ 20 | check that Edit Management Relationship works for the VM 21 | 22 | Bugzilla: 23 | 1534400 24 | 25 | Polarion: 26 | assignee: jhenner 27 | casecomponent: WebUI 28 | caseimportance: high 29 | initialEstimate: 1/6h 30 | """ 31 | vm_relationship = InfraVm.CfmeRelationship(create_vm) 32 | 33 | for i in range(2): # do it 2 times and leave the vm w/o relationship 34 | # set relationship 35 | vm_relationship.set_relationship(appliance.server.name, appliance.server.sid) 36 | # unset relationship 37 | vm_relationship.remove_relationship() 38 | -------------------------------------------------------------------------------- /cfme/tests/integration/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/cfme/tests/integration/__init__.py -------------------------------------------------------------------------------- /cfme/tests/integration/test_auth_scripts.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | from cfme import test_requirements 4 | 5 | 6 | @pytest.mark.tier(1) 7 | @pytest.mark.meta(automates=[1577303]) 8 | @test_requirements.appliance 9 | def test_fixauth_dryrun_has_feedback(temp_appliance_preconfig): 10 | """ 11 | Check whether the fixauth says it is running in dry mode 12 | 13 | Polarion: 14 | assignee: jhenner 15 | casecomponent: Appliance 16 | initialEstimate: 1/60h 17 | 18 | Bugzilla: 19 | 1577303 20 | """ 21 | appliance = temp_appliance_preconfig 22 | run_command = appliance.ssh_client.run_command 23 | dry_run_message = ( 24 | 'is executing in dry-run mode, and no actual changes will be made **') 25 | assert dry_run_message in run_command("fix_auth -d").output 26 | assert dry_run_message in run_command("fix_auth -d -i invalid").output 27 | assert dry_run_message in run_command("fix_auth -d --databaseyml").output 28 | assert dry_run_message not in run_command("fix_auth").output 29 | -------------------------------------------------------------------------------- /cfme/tests/intelligence/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/cfme/tests/intelligence/__init__.py -------------------------------------------------------------------------------- /cfme/tests/intelligence/reports/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/cfme/tests/intelligence/reports/__init__.py -------------------------------------------------------------------------------- /cfme/tests/intelligence/test_rss.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | import requests 3 | 4 | from cfme.utils.appliance.implementations.ui import navigate_to 5 | 6 | pytestmark = [pytest.mark.ignore_stream("5.11")] 7 | 8 | 9 | @pytest.mark.tier(3) 10 | def test_verify_rss_links(appliance): 11 | """ 12 | Polarion: 13 | assignee: jhenner 14 | initialEstimate: 1/4h 15 | casecomponent: WebUI 16 | """ 17 | view = navigate_to(appliance.server, 'RSS') 18 | for row in view.table.rows(): 19 | url = row[3].text 20 | req = requests.get(url, verify=False) 21 | assert 200 <= req.status_code < 400, "The url {} seems malformed".format(repr(url)) 22 | -------------------------------------------------------------------------------- /cfme/tests/migration_analytics/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/cfme/tests/migration_analytics/__init__.py -------------------------------------------------------------------------------- /cfme/tests/networks/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/cfme/tests/networks/__init__.py -------------------------------------------------------------------------------- /cfme/tests/networks/nuage/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/cfme/tests/networks/nuage/__init__.py -------------------------------------------------------------------------------- /cfme/tests/openstack/__init__.py: -------------------------------------------------------------------------------- 1 | """Tests for Openstack cloud and infra providers""" 2 | -------------------------------------------------------------------------------- /cfme/tests/openstack/cloud/__init__.py: -------------------------------------------------------------------------------- 1 | """Tests for Openstack cloud provider""" 2 | -------------------------------------------------------------------------------- /cfme/tests/openstack/infrastructure/__init__.py: -------------------------------------------------------------------------------- 1 | """Tests for Openstack infrastructure provider""" 2 | -------------------------------------------------------------------------------- /cfme/tests/perf/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/cfme/tests/perf/__init__.py -------------------------------------------------------------------------------- /cfme/tests/perf/workloads/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/cfme/tests/perf/workloads/__init__.py -------------------------------------------------------------------------------- /cfme/tests/physical_infrastructure/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/cfme/tests/physical_infrastructure/__init__.py -------------------------------------------------------------------------------- /cfme/tests/physical_infrastructure/test_providers.py: -------------------------------------------------------------------------------- 1 | import uuid 2 | 3 | import pytest 4 | 5 | from cfme import test_requirements 6 | from cfme.physical.provider.lenovo import LenovoProvider 7 | from cfme.utils.update import update 8 | 9 | pytestmark = [ 10 | pytest.mark.provider([LenovoProvider], scope="function") 11 | ] 12 | 13 | 14 | @pytest.mark.tier(3) 15 | @pytest.mark.sauce 16 | @test_requirements.discovery 17 | def test_physical_infra_provider_crud(provider, has_no_providers): 18 | """Tests provider add with good credentials 19 | 20 | Metadata: 21 | test_flag: crud 22 | 23 | Polarion: 24 | assignee: rhcf3_machine 25 | casecomponent: Infra 26 | initialEstimate: 1/4h 27 | """ 28 | provider.create() 29 | 30 | # Fails on upstream, all provider types - BZ1087476 31 | provider.validate_stats(ui=True) 32 | 33 | old_name = provider.name 34 | with update(provider): 35 | provider.name = str(uuid.uuid4()) # random uuid 36 | 37 | with update(provider): 38 | provider.name = old_name # old name 39 | 40 | provider.delete() 41 | provider.wait_for_delete() 42 | -------------------------------------------------------------------------------- /cfme/tests/physical_infrastructure/test_redfish_physical_chassis.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | from cfme.physical.provider.redfish import RedfishProvider 4 | 5 | pytestmark = [ 6 | pytest.mark.provider([RedfishProvider], scope="function"), 7 | ] 8 | 9 | 10 | def get_physical_chassis(appliance, provider): 11 | """Get and return the physical chassis collection.""" 12 | return appliance.collections.redfish_physical_chassis.all(provider) 13 | 14 | 15 | def test_redfish_physical_chassis_details_stats(appliance, provider, setup_provider_funcscope): 16 | """Navigate to the physical chassis' details page and verify that the stats match.""" 17 | for phys_ch in get_physical_chassis(appliance, provider): 18 | phys_ch.validate_stats(ui=True) 19 | -------------------------------------------------------------------------------- /cfme/tests/physical_infrastructure/test_redfish_physical_infra_events.py: -------------------------------------------------------------------------------- 1 | """This module tests Redfish physical infrastructure events.""" 2 | import pytest 3 | 4 | from cfme.physical.provider.redfish import RedfishProvider 5 | 6 | 7 | pytestmark = [ 8 | pytest.mark.provider([RedfishProvider], scope="function"), 9 | ] 10 | 11 | # Name of the source for the events related to the Redfish provider 12 | SOURCE = 'REDFISH' 13 | 14 | 15 | def test_get_redfish_events_any(setup_provider_funcscope, register_event): 16 | """ 17 | Test that the provider accounts for any Redfish-related event. 18 | 19 | The test assumes that events are generated regularly without needing to 20 | trigger any action. 21 | """ 22 | register_event(source=SOURCE) 23 | -------------------------------------------------------------------------------- /cfme/tests/physical_infrastructure/test_redfish_physical_racks.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | from cfme.physical.provider.redfish import RedfishProvider 4 | 5 | pytestmark = [pytest.mark.provider([RedfishProvider], scope="function")] 6 | 7 | 8 | def get_physical_racks(appliance, provider): 9 | """Get and return the physical racks collection.""" 10 | return appliance.collections.redfish_physical_racks.all(provider) 11 | 12 | 13 | def test_redfish_physical_racks_details_stats(appliance, provider, setup_provider_funcscope): 14 | """Navigate to the physical racks' details page and verify that the stats match.""" 15 | for physical_rack in get_physical_racks(appliance, provider): 16 | physical_rack.validate_stats(ui=True) 17 | -------------------------------------------------------------------------------- /cfme/tests/physical_infrastructure/test_redfish_providers.py: -------------------------------------------------------------------------------- 1 | import fauxfactory 2 | import pytest 3 | 4 | from cfme.physical.provider.redfish import RedfishProvider 5 | from cfme.utils.update import update 6 | 7 | pytestmark = [ 8 | pytest.mark.provider([RedfishProvider], scope="function") 9 | ] 10 | 11 | 12 | def test_redfish_provider_crud(provider, has_no_physical_providers): 13 | """Tests provider add with good credentials 14 | 15 | Polarion: 16 | assignee: rhcf3_machine 17 | casecomponent: Infra 18 | initialEstimate: 1/4h 19 | """ 20 | provider.create() 21 | 22 | provider.validate_stats(ui=True) 23 | 24 | old_name = provider.name 25 | with update(provider): 26 | provider.name = fauxfactory.gen_alphanumeric(8) # random uuid 27 | 28 | with update(provider): 29 | provider.name = old_name # old name 30 | 31 | provider.delete() 32 | provider.wait_for_delete() 33 | -------------------------------------------------------------------------------- /cfme/tests/platform/test_locale.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | from cfme import test_requirements 4 | 5 | 6 | @pytest.mark.manual 7 | @pytest.mark.tier(1) 8 | @test_requirements.appliance 9 | def test_automated_locale_switching(): 10 | """ 11 | Having the automatic locale selection selected, the appliance"s locale 12 | changes accordingly with user"s preferred locale in the browser. 13 | 14 | Polarion: 15 | assignee: jhenner 16 | casecomponent: Appliance 17 | caseimportance: medium 18 | initialEstimate: 1/8h 19 | """ 20 | pass 21 | -------------------------------------------------------------------------------- /cfme/tests/pod/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/cfme/tests/pod/__init__.py -------------------------------------------------------------------------------- /cfme/tests/services/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/cfme/tests/services/__init__.py -------------------------------------------------------------------------------- /cfme/tests/services/test_service_catalog_dialog_manual.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | from cfme import test_requirements 4 | 5 | pytestmark = [ 6 | pytest.mark.manual, 7 | test_requirements.service 8 | ] 9 | 10 | 11 | @pytest.mark.manual 12 | @pytest.mark.tier(3) 13 | def test_request_filter_on_request_page(): 14 | """ 15 | Polarion: 16 | assignee: nansari 17 | casecomponent: Services 18 | testtype: functional 19 | initialEstimate: 1/4h 20 | startsin: 5.9 21 | tags: service 22 | Bugzilla: 23 | 1498237 24 | """ 25 | pass 26 | -------------------------------------------------------------------------------- /cfme/tests/ssui/test_ssui_ansible_service.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | from cfme import test_requirements 4 | from cfme.services.myservice import MyService 5 | from cfme.services.service_catalogs import ServiceCatalogs 6 | from cfme.utils.appliance import ViaSSUI 7 | 8 | pytestmark = [ 9 | pytest.mark.meta(server_roles="+automate"), 10 | test_requirements.ssui, 11 | pytest.mark.long_running, 12 | pytest.mark.ignore_stream("upstream") 13 | ] 14 | 15 | 16 | @pytest.mark.rhel_testing 17 | @pytest.mark.parametrize('context', [ViaSSUI]) 18 | def test_service_catalog_crud_ui(appliance, context, order_ansible_service_in_ops_ui, request): 19 | """Tests Ansible Service Catalog in SSUI. 20 | 21 | Polarion: 22 | assignee: nansari 23 | initialEstimate: 1/4h 24 | casecomponent: Services 25 | tags: service 26 | """ 27 | 28 | service_name = order_ansible_service_in_ops_ui 29 | with appliance.context.use(context): 30 | service = ServiceCatalogs(appliance, name=service_name) 31 | service.add_to_shopping_cart() 32 | service.order() 33 | 34 | @request.addfinalizer 35 | def _finalize(): 36 | _service = MyService(appliance, service_name) 37 | _service.delete() 38 | -------------------------------------------------------------------------------- /cfme/tests/ssui/test_ssui_tags.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | from cfme import test_requirements 4 | 5 | pytestmark = [test_requirements.tag] 6 | 7 | 8 | @pytest.mark.manual 9 | @pytest.mark.tier(2) 10 | def test_tagvis_ssui_catalog_items(): 11 | """ 12 | Polarion: 13 | assignee: prichard 14 | casecomponent: SelfServiceUI 15 | caseimportance: medium 16 | initialEstimate: 1/8h 17 | testSteps: 18 | 1.Create groups with tag 19 | 2. Create user and assign it to group 20 | 3. As admin create service catalog and catalog item 21 | 4. Log in as user to ssui 22 | 5. Check catalog item list -> User should not see any items 23 | 6. As admin set tag to catalog item 24 | 7. As user, check visibility -> User should see tagged catalog item 25 | """ 26 | pass 27 | -------------------------------------------------------------------------------- /cfme/tests/storage/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/cfme/tests/storage/__init__.py -------------------------------------------------------------------------------- /cfme/tests/test_csrf.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | from cfme import test_requirements 4 | from cfme.utils.appliance.implementations.ui import navigate_to 5 | from cfme.utils.wait import TimedOutError 6 | from cfme.utils.wait import wait_for 7 | 8 | 9 | pytestmark = [test_requirements.general_ui] 10 | 11 | 12 | @pytest.mark.tier(2) 13 | def test_csrf_post(appliance): 14 | """CSRF should prevent forged POST requests 15 | 16 | POST requests use the CSRF token to validate requests, so setting the token 17 | to something invalid should set off the CSRF detector and reject the request 18 | 19 | 20 | Polarion: 21 | assignee: pvala 22 | initialEstimate: 1/4h 23 | casecomponent: WebUI 24 | """ 25 | dashboard = navigate_to(appliance.server, 'Dashboard') 26 | dashboard.csrf_token = "Bogus!" 27 | dashboard.reset_widgets(cancel=False) 28 | 29 | try: 30 | wait_for( 31 | lambda: dashboard.logged_out, num_sec=15, delay=0.2) 32 | except TimedOutError: 33 | pytest.fail("CSRF attack succeeded!") 34 | -------------------------------------------------------------------------------- /cfme/utils/ansible_conf/custom_attributes_basic_script.yml: -------------------------------------------------------------------------------- 1 | - hosts: localhost 2 | tasks: 3 | - manageiq_custom_attributes: 4 | custom_attributes: 5 | - {name: ca1, value: value 1} 6 | - {name: ca2, value: value 2} 7 | entity_name: 8 | entity_type: provider 9 | miq_password: 10 | miq_url: 11 | miq_username: 12 | state: present 13 | miq_verify_ssl: false 14 | name: Add Custom Attributes to Openshift containers provider 15 | register: result 16 | - {debug: var=result} 17 | -------------------------------------------------------------------------------- /cfme/utils/ansible_conf/providers_basic_script.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - 3 | hosts: localhost 4 | tasks: 5 | - 6 | manageiq_provider: 7 | monitoring: 'hawkular' 8 | monitoring_hostname: 9 | monitoring_port: 443 10 | miq_password: 11 | miq_url: 12 | miq_username: 13 | name: 14 | provider_api_auth_token: ~ 15 | provider_api_hostname: ~ 16 | provider_api_port: 8443 17 | provider_type: 'openshift-origin' 18 | state: present 19 | miq_verify_ssl: false 20 | provider_verify_ssl: false 21 | name: "Add Openshift Containers Provider to ManageIQ" 22 | register: result 23 | - 24 | debug: var=result 25 | -------------------------------------------------------------------------------- /cfme/utils/ansible_conf/tags_basic_script.yml: -------------------------------------------------------------------------------- 1 | - hosts: localhost 2 | tasks: 3 | - manageiq_tag_assignment: 4 | tags: 5 | - {category: ca1, name: value 1} 6 | - {category: ca2, name: value 2} 7 | resource: provider 8 | resource_name: 9 | miq_password: 10 | miq_url: 11 | miq_username: 12 | miq_verify_ssl: false 13 | state: 14 | name: Create a tag in ManageIQ 15 | register: result 16 | - {debug: var=result} 17 | -------------------------------------------------------------------------------- /cfme/utils/ansible_conf/users_basic_script.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - 3 | hosts: localhost 4 | tasks: 5 | - 6 | manageiq_user: 7 | fullname: 8 | group: EvmGroup-user 9 | miq_password: 10 | miq_url: 11 | miq_username: 12 | name: 13 | password: 14 | state: present 15 | miq_verify_ssl: false 16 | name: "Create a user in ManageIQ" 17 | register: result 18 | - 19 | debug: var=result 20 | -------------------------------------------------------------------------------- /cfme/utils/appliance/constants.py: -------------------------------------------------------------------------------- 1 | from enum import Enum 2 | 3 | 4 | class DownloadOptions(Enum): 5 | TEXT = 'Download as Text' 6 | CSV = 'Download as CSV' 7 | PDF = 'Print or export as PDF' 8 | -------------------------------------------------------------------------------- /cfme/utils/appliance/implementations/rest.py: -------------------------------------------------------------------------------- 1 | class ViaREST: 2 | 3 | name = "REST" 4 | navigator = None 5 | 6 | def __init__(self, owner): 7 | self.owner = owner 8 | 9 | @property 10 | def appliance(self): 11 | return self.owner 12 | 13 | def __str__(self): 14 | return 'REST' 15 | -------------------------------------------------------------------------------- /cfme/utils/category.py: -------------------------------------------------------------------------------- 1 | """Module used for handling categories of let's say form values and for categorizing them.""" 2 | 3 | 4 | class CategoryBase: 5 | """Base class for categories 6 | 7 | Args: 8 | value: Value to be categorized. 9 | """ 10 | def __init__(self, value): 11 | self.value = value 12 | 13 | def __str__(self): 14 | return str(self.value) 15 | 16 | def __repr__(self): 17 | return "{}({})".format(type(self).__name__, str(repr(self.value))) 18 | 19 | 20 | def categorize(iterable, cat): 21 | """Function taking iterable of values and a dictionary of rules to categorize the values. 22 | 23 | Keys of the dictionary are callables, taking one parameter - the current iterable item. If the 24 | call on it returns positive, then the value part of dictionary is taken (assumed callable) 25 | and it is called with the current item. 26 | 27 | Args: 28 | iterable: Iterable to categorize. 29 | cat: Category specification dictionary 30 | """ 31 | for item in iterable: 32 | for cond, func in cat.items(): 33 | if callable(cond) and cond(item): 34 | func(item) 35 | break 36 | else: 37 | cat.get("default", lambda item: None)(item) 38 | -------------------------------------------------------------------------------- /cfme/utils/conf.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | from cfme.test_framework.config import DeprecatedConfigWrapper 4 | from cfme.test_framework.config import global_configuration 5 | from cfme.utils import path 6 | 7 | global_configuration.configure( 8 | config_dir=path.conf_path.strpath, 9 | crypt_key_file=path.project_path.join('.yaml_key').strpath, 10 | ) 11 | 12 | sys.modules[__name__] = DeprecatedConfigWrapper(global_configuration) 13 | -------------------------------------------------------------------------------- /cfme/utils/deprecation.py: -------------------------------------------------------------------------------- 1 | import warnings 2 | 3 | from debtcollector.removals import remove 4 | 5 | 6 | warnings.simplefilter('once', category=DeprecationWarning) 7 | 8 | removed_in_fw30 = remove( 9 | removal_version="framework 3.0", 10 | ) 11 | -------------------------------------------------------------------------------- /cfme/utils/dockerbot/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/cfme/utils/dockerbot/__init__.py -------------------------------------------------------------------------------- /cfme/utils/dockerbot/build_container.py: -------------------------------------------------------------------------------- 1 | import subprocess 2 | import sys 3 | 4 | import py 5 | 6 | 7 | def main(): 8 | here = py.path.local(__file__).dirpath() 9 | sys.exit(subprocess.call([ 10 | 'docker', 'build', '-t', 'py_test_base', str(here / 'pytestbase') 11 | ])) 12 | 13 | 14 | if __name__ == "__main__": 15 | main() 16 | -------------------------------------------------------------------------------- /cfme/utils/dockerbot/pytestbase/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM fedora:30 2 | 3 | #TODO rewrite this to use quickstart 4 | 5 | RUN dnf install -y gcc postgresql-devel libxml2-devel libxslt-devel zeromq-devel git nano python3-devel gnupg gnupg2 libcurl-devel redhat-rpm-config findutils libffi-devel openssl-devel tesseract freetype-devel gcc-c++ python3-pip python3 libjpeg-devel iputils && dnf clean all 6 | ARG CFME_REPO=https://github.com/ManageIQ/integration_tests.git 7 | ARG CFME_BRANCH=master 8 | RUN git clone -b $CFME_BRANCH $CFME_REPO /cfme_tests 9 | RUN cd /cfme_tests && PYCURL_SSL_LIBRARY=openssl pip3 install --user -U -r /cfme_tests/requirements/frozen.txt --no-cache-dir 10 | RUN python3 -c 'import pycurl' 11 | ADD setup.sh /setup.sh 12 | ADD post_result.py /post_result.py 13 | ADD get_keys.py /get_keys.py 14 | ADD verify_commit.py /verify_commit.py 15 | ADD check_provisioned.py /check_provisioned.py 16 | -------------------------------------------------------------------------------- /cfme/utils/dockerbot/pytestbase/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/cfme/utils/dockerbot/pytestbase/__init__.py -------------------------------------------------------------------------------- /cfme/utils/dockerbot/pytestbase/check_provisioned.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import datetime 3 | import sys 4 | 5 | from cfme.utils.conf import env 6 | 7 | 8 | def main(): 9 | print(datetime.date.today()) 10 | if env.appliances[0].hostname == "SPROUT_SHOULD_OVERRIDE_THIS": 11 | print("sprout provisioning failed") 12 | sys.exit(1) 13 | else: 14 | print("sprout provisioning worked") 15 | 16 | 17 | if __name__ == '__main__': 18 | main() 19 | -------------------------------------------------------------------------------- /cfme/utils/dockerbot/pytestbase/get_keys.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import random 3 | import subprocess 4 | import sys 5 | 6 | from cfme.utils import conf 7 | 8 | 9 | def main(): 10 | key_list = [key[-9:].replace(' ', '') for key in conf['gpg']['allowed_keys']] 11 | servers = conf['gpg']['servers'] 12 | 13 | for _ in range(3): 14 | server = random.choice(servers) 15 | gpg_cmd = ['gpg', '--recv-keys', '--keyserver', server] + key_list 16 | print("running command: {}".format(" ".join(gpg_cmd))) 17 | proc = subprocess.Popen(gpg_cmd) 18 | proc.wait() 19 | if proc.returncode == 0: 20 | sys.exit(proc.returncode) 21 | else: 22 | print("keyserver: {s} not available. exit code: {c}".format(s=server, 23 | c=proc.returncode)) 24 | 25 | 26 | if __name__ == "__main__": 27 | main() 28 | -------------------------------------------------------------------------------- /cfme/utils/dockerbot/pytestbase/post_result.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import os 3 | import sys 4 | 5 | from cfme.utils import safe_string 6 | from cfme.utils.trackerbot import post_task_result 7 | 8 | 9 | def main(): 10 | with open("{}/setup.txt".format(os.environ['ARTIFACTOR_DIR'])) as f: 11 | data = f.read() 12 | 13 | coverage = 0.0 14 | try: 15 | with open("{}/coverage_result.txt".format(os.environ['CFME_REPO_DIR'])) as f: 16 | data = f.read().strip("\n") 17 | coverage = float(data) 18 | except Exception: 19 | pass 20 | 21 | print(sys.argv[1], sys.argv[2], coverage) 22 | post_task_result(sys.argv[1], sys.argv[2], safe_string(data), coverage) 23 | 24 | 25 | if __name__ == "__main__": 26 | main() 27 | -------------------------------------------------------------------------------- /cfme/utils/dockerbot/pytestbase/verify_commit.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import re 3 | import subprocess 4 | import sys 5 | 6 | from cfme.utils import conf 7 | 8 | 9 | def main(): 10 | commit = sys.argv[1] 11 | 12 | key_list = [key.replace(' ', '') for key in conf['gpg']['allowed_keys']] 13 | proc = subprocess.Popen(['git', 'verify-commit', commit], stdout=subprocess.PIPE, 14 | stderr=subprocess.PIPE) 15 | proc.wait() 16 | output = proc.stderr.read().decode('utf-8') 17 | if re.findall('^gpg: Good signature', output, re.M): 18 | gpg = re.findall('fingerprint: ([A-F0-9 ]+)', output)[0].replace(' ', '') 19 | if gpg in key_list: 20 | print(f"Good sig and match for {gpg}") 21 | sys.exit(0) 22 | print("ERROR: Bad signature. Please sign your commits!") 23 | print(f"git output: {output}") 24 | sys.exit(127) 25 | 26 | 27 | if __name__ == "__main__": 28 | main() 29 | -------------------------------------------------------------------------------- /cfme/utils/error.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/cfme/utils/error.py -------------------------------------------------------------------------------- /cfme/utils/generators.py: -------------------------------------------------------------------------------- 1 | import re 2 | 3 | import fauxfactory 4 | 5 | 6 | def random_vm_name(context=None, max_length=15): 7 | """Generates a valid VM name that should be valid for any provider we use. 8 | 9 | Constraints: 10 | * Maximum string length 15 characters (by default) 11 | * Only [a-z0-9-] 12 | 13 | Args: 14 | context: If you want to provide some custom string after ``test-`` instead of ``vm``. 15 | It is recommended to use a maximum of 5 characters with the default 15 character limit. 16 | Longer strings will be truncated 17 | 18 | Returns: 19 | A valid randomized VM name. 20 | """ 21 | template_str_length = 6 22 | random_chars = 4 23 | context_length = max_length - random_chars - template_str_length 24 | context = re.sub(r'[^a-z0-9-]', '', (context or 'vm').lower())[:context_length] 25 | return 'test-{}-{}'.format(context, fauxfactory.gen_alphanumeric(length=random_chars).lower()) 26 | -------------------------------------------------------------------------------- /cfme/utils/ports.py: -------------------------------------------------------------------------------- 1 | """Storage for ports. Set defaults here, then :py:mod:`fixtures.portset` will make overrides.""" 2 | import sys 3 | 4 | from cfme.utils import clear_property_cache 5 | from cfme.utils.log import logger 6 | 7 | 8 | class Ports: 9 | 10 | SSH = 22 11 | DB = 5432 12 | TOWER = 54322 13 | logger = logger 14 | 15 | @property 16 | def _top(self, m=sys.modules): 17 | mod = m.get('utils.appliance') 18 | 19 | return mod and mod.stack.top 20 | 21 | def __setattr__(self, attr, value): 22 | super(self.__class__, self).__setattr__(attr, value) 23 | if self._top is not None: 24 | self.logger.info("Invalidating lazy_cache ssh_client current_appliance object") 25 | clear_property_cache(self._top, 'ssh_client') 26 | 27 | 28 | sys.modules[__name__] = Ports() 29 | -------------------------------------------------------------------------------- /cfme/utils/pretty.py: -------------------------------------------------------------------------------- 1 | def _name(o): 2 | cls = o.__class__ 3 | return "{}.{}".format(getattr(cls, '__module__', "module"), 4 | getattr(cls, '__name__', "name")) 5 | 6 | 7 | def attr_repr(o, attr): 8 | """Return the string repr of the attribute attr on the object o""" 9 | try: 10 | return repr(getattr(o, attr, None)) 11 | except BaseException: 12 | return None 13 | 14 | 15 | def pretty_repr(attrs, o): 16 | pairs = list(zip(attrs, [attr_repr(o, attr) for attr in attrs])) 17 | return "<{} {}>".format(_name(o), 18 | ", ".join(["{}={}".format(i[0], i[1]) for i in pairs])) 19 | 20 | 21 | def pr_obj(attrs): 22 | def x(o): 23 | return pretty_repr(attrs, o) 24 | return x 25 | 26 | 27 | class Pretty: 28 | """A mixin that prints repr as . The 29 | fields that will be printed should be stored in the class's 30 | pretty_attrs attribute (none by default). 31 | 32 | """ 33 | pretty_attrs = [] 34 | 35 | def __repr__(self): 36 | return pretty_repr(self.pretty_attrs, self) 37 | -------------------------------------------------------------------------------- /cfme/utils/template/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/cfme/utils/template/__init__.py -------------------------------------------------------------------------------- /cfme/utils/tests/README: -------------------------------------------------------------------------------- 1 | Another tests dir... 2 | 3 | This one's just for testing utility functions and potentially demonstrating their usage 4 | -------------------------------------------------------------------------------- /cfme/utils/tests/test_datafile_fixture.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | pytestmark = [ 4 | pytest.mark.non_destructive, 5 | ] 6 | 7 | 8 | def test_datafile_fixture_read(datafile): 9 | with datafile('test_template') as myfile: 10 | assert myfile.read() == '$replaceme' 11 | 12 | 13 | def test_datafile_fixture_read_slash_path(datafile): 14 | with datafile('/cfme/utils/test_datafile_fixture/test_template') as myfile: 15 | assert myfile.read() == '$replaceme' 16 | 17 | 18 | def test_datafile_fixture_read_template(datafile): 19 | replacements = {'replaceme': 'test!'} 20 | 21 | with datafile('test_template', replacements=replacements) as myfile: 22 | assert myfile.read() == replacements['replaceme'] 23 | -------------------------------------------------------------------------------- /cfme/utils/tests/test_fixtureconf_fixture.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | pytestmark = [ 4 | pytest.mark.non_destructive, 5 | ] 6 | 7 | 8 | @pytest.mark.fixtureconf('positional argument', kwarg='keyword argument') 9 | def test_fixtureconf_fixture_with_mark(fixtureconf): 10 | # args and kwargs should be in fixtureconf 11 | assert fixtureconf['args'] == ('positional argument',) 12 | assert fixtureconf['kwarg'] == 'keyword argument' 13 | 14 | 15 | def test_fixtureconf_fixture_without_mark(fixtureconf): 16 | # no mark = no args stored in fixtureconf, but the fixture should still work 17 | assert fixtureconf == {'args': (), } 18 | -------------------------------------------------------------------------------- /cfme/utils/tests/test_instance_class_method.py: -------------------------------------------------------------------------------- 1 | from cfme.utils import InstanceClassMethod 2 | 3 | 4 | class ClassWithCompleteDefinition: 5 | @InstanceClassMethod 6 | def execute(self, x): 7 | return (self, x) 8 | 9 | @execute.classmethod 10 | def execute(cls): 11 | return cls 12 | 13 | 14 | class ClassWithIncompleteDefinition: 15 | @InstanceClassMethod 16 | def execute(self, x): 17 | return (self, x) 18 | 19 | 20 | def test_check_complete_definition(): 21 | inst = ClassWithCompleteDefinition() 22 | assert inst.execute(1) == (inst, 1) 23 | assert ClassWithCompleteDefinition.execute() is ClassWithCompleteDefinition 24 | 25 | 26 | def test_check_partial_definition(): 27 | inst = ClassWithCompleteDefinition() 28 | assert inst.execute(1) == (inst, 1) 29 | assert ClassWithIncompleteDefinition.execute(1) == (ClassWithIncompleteDefinition, 1) 30 | -------------------------------------------------------------------------------- /cfme/utils/tests/test_metadoc.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | pytestmark = pytest.mark.meta(from_pytest='yep') 4 | 5 | 6 | @pytest.mark.meta(from_decorator='seems to be') 7 | def test_metadoc(meta): 8 | """This test function has a docstring! 9 | 10 | Metadata: 11 | 12 | valid_yaml: True 13 | """ 14 | assert meta['from_docs']['valid_yaml'] 15 | assert meta['from_pytest'] == 'yep' 16 | assert meta['from_decorator'] == 'seems to be' 17 | -------------------------------------------------------------------------------- /cfme/utils/tests/test_process_pytest_path.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | from cfme.utils import process_pytest_path 4 | 5 | 6 | @pytest.mark.parametrize(("input_string", "expected_result"), [ 7 | ("", []), 8 | ("a/b/c", ["a", "b", "c"]), 9 | ("//a////b//////c////", ["a", "b", "c"]), 10 | ("abc[def]", ["abc[def]"]), 11 | ("abc[def/ghi]", ["abc[def/ghi]"]), 12 | ("a/b/c[d/e]/f/g", ["a", "b", "c[d/e]", "f", "g"]), 13 | ("a/b/c[d/e]/f/g/", ["a", "b", "c[d/e]", "f", "g"])], 14 | ids=[ 15 | "empty", "simple", "manyslashes", "simpleparam", "paramslash", "path-paramslash", 16 | "endslash"]) 17 | def test_process_pytest_path(input_string, expected_result): 18 | assert process_pytest_path(input_string) == expected_result 19 | -------------------------------------------------------------------------------- /cfme/utils/tests/test_providers.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | from cfme.cloud.provider.azure import AzureProvider 4 | from cfme.common.provider import BaseProvider 5 | from cfme.markers.env_markers.provider import ALL 6 | from cfme.markers.env_markers.provider import ONE_PER_VERSION 7 | 8 | 9 | @pytest.mark.provider([AzureProvider], selector=ONE_PER_VERSION) 10 | def test_provider_fixtures(provider, setup_provider): 11 | """Verify that clearing providers works correctly. 12 | 13 | Polarion: 14 | assignee: tpapaioa 15 | casecomponent: Appliance 16 | initialEstimate: 1/15h 17 | """ 18 | assert provider.exists, f"Provider {provider.name} not found on appliance." 19 | BaseProvider.clear_providers() 20 | assert not provider.exists, f"Provider {provider.name} not deleted from appliance." 21 | 22 | 23 | @pytest.mark.provider([BaseProvider], selector=ALL) 24 | def test_provider_all_selector(request, provider): 25 | """Verify that the 'all' selector works, and that the provider matches the parametrization.""" 26 | expected_id = f"test_provider_all_selector[{provider.type}-{provider.version}-{provider.key}]" 27 | test_id = request.node.name 28 | assert test_id == expected_id, f"Provider parametrization failed." 29 | -------------------------------------------------------------------------------- /cfme/utils/tests/test_pytest_shortcuts.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | from cfme.utils.pytest_shortcuts import fixture_filter 4 | 5 | 6 | class FakeMetaFunc: 7 | fixturenames = ['a'] 8 | 9 | 10 | def _values(val): 11 | return tuple(getattr(val, 'values', val)) 12 | 13 | 14 | @pytest.mark.parametrize('structure', [ 15 | pytest.param(pytest.param(1, 2), id='param'), 16 | pytest.param([1, 2], id='list'), 17 | pytest.param((1, 2), id='tuple'), 18 | ]) 19 | def test_fixture_filter(structure): 20 | argnames, argvalues = fixture_filter(FakeMetaFunc(), ['a', 'b'], [structure]) 21 | argvalues = [_values(x) for x in argvalues] 22 | assert argvalues == [(1,)] 23 | -------------------------------------------------------------------------------- /cfme/utils/tests/test_safe_string.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | from cfme.utils import safe_string 4 | 5 | 6 | @pytest.mark.parametrize("source, result", [ 7 | ('\u25cf', '●'), 8 | ('ěšč', 'ěšč'), 9 | ('взорваться', 'взорваться'), 10 | (4, '4')], 11 | ids=['ugly_nonunicode_character', 'latin_diacritics', 'cyrillic', 'non_string']) 12 | def test_safe_string(source, result): 13 | assert safe_string(source) == result 14 | -------------------------------------------------------------------------------- /cfme/utils/tests/test_ssh_client.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | from cfme.utils.appliance import DummyAppliance 4 | pytestmark = [ 5 | pytest.mark.non_destructive, 6 | ] 7 | 8 | 9 | @pytest.fixture(autouse=True) 10 | def check_appliance(appliance): 11 | if isinstance(appliance, DummyAppliance): 12 | pytest.skip('Dummy appliance not supported') 13 | 14 | 15 | def test_ssh_client_run_command(appliance): 16 | # Make sure the ssh command runner works 17 | result = appliance.ssh_client.run_command('echo Testing!') 18 | assert result.success 19 | assert 'Testing!' in result.output 20 | 21 | 22 | def test_scp_client_can_put_a_file(appliance, tmpdir): 23 | # Make sure we can put a file, get a file, and they all match 24 | tmpfile = tmpdir.mkdir("sub").join("temp.txt") 25 | tmpfile.write("content") 26 | appliance.ssh_client.put_file(str(tmpfile), '/tmp') 27 | result = appliance.ssh_client.run_command(f"ls /tmp/{tmpfile.basename}") 28 | assert result.success 29 | assert tmpfile.basename in result.output 30 | appliance.ssh_client.get_file(f"/tmp/{tmpfile.basename}", str(tmpdir)) 31 | assert "content" in tmpfile.read() 32 | # Clean up the server 33 | appliance.ssh_client.run_command(f"rm -f /tmp/{tmpfile.basename}") 34 | -------------------------------------------------------------------------------- /cfme/utils/tests/test_units.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | from cfme.utils.units import Unit 4 | 5 | 6 | @pytest.mark.parametrize( 7 | ('a', 'b'), [ 8 | ('1 KB', '1024 Bytes'), 9 | ('1 KB', '1024 B'), 10 | ('231 KB', 231 * 1024), 11 | ('1 TB', '1024 GB'), 12 | ]) 13 | def test_compare_equal(a, b): 14 | assert Unit.parse(a) == b 15 | 16 | 17 | @pytest.mark.parametrize( 18 | ('a', 'b'), [ 19 | ('1 KB', '1025 Bytes'), 20 | ('1 KB', '10000 B'), 21 | ('231 KB', 231 * 1024 * 1024), 22 | ('1 TB', '1500 GB'), 23 | ]) 24 | def test_compare_lt(a, b): 25 | assert Unit.parse(a) < b 26 | -------------------------------------------------------------------------------- /cfme/utils/tests/test_version.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | from cfme.utils.version import Version 4 | 5 | GT = '>' 6 | LT = '<' 7 | EQ = '==' 8 | 9 | 10 | @pytest.mark.parametrize(('v1', 'op', 'v2'), [ 11 | ('1', LT, '2'), 12 | ('1', EQ, '1'), 13 | ('1.2.3.4', LT, '1.2.3.4.1'), 14 | ('1.2.3.4.1', GT, '1.2.3.4'), 15 | # (1.1, EQ, '1.1'), 16 | # (1, EQ, '1'), 17 | ('1.2.3.4-beta', LT, '1.2.3.4'), 18 | ('1.2.3.4-beta1', GT, '1.2.3.4-beta'), 19 | ('1.2.3.4-beta1.1', GT, '1.2.3.4-beta1'), 20 | ('1.2.3.4-alpha-nightly', GT, '1.2.3.4-alpha'), # TODO: This one might be discussed 21 | ]) 22 | def test_version(v1, op, v2): 23 | v1 = Version(v1) 24 | v2 = Version(v2) 25 | if op == GT: 26 | assert v1 > v2 27 | elif op == LT: 28 | assert v1 < v2 29 | elif op == EQ: 30 | assert v1 == v2 31 | -------------------------------------------------------------------------------- /cfme/utils/wait.py: -------------------------------------------------------------------------------- 1 | from functools import partial 2 | 3 | from wait_for import RefreshTimer # noqa: F401 4 | from wait_for import TimedOutError # noqa: F401 5 | from wait_for import wait_for as wait_for_mod 6 | from wait_for import wait_for_decorator as wait_for_decorator_mod 7 | 8 | from cfme.utils.log import logger 9 | 10 | wait_for = partial(wait_for_mod, logger=logger) 11 | wait_for_decorator = partial(wait_for_decorator_mod, logger=logger) 12 | -------------------------------------------------------------------------------- /cfme/v2v/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/cfme/v2v/__init__.py -------------------------------------------------------------------------------- /conf/docker.yaml.template: -------------------------------------------------------------------------------- 1 | appliances: 2 | Downstream: https://xx.xx.xx.xx 3 | Upstream: https://xx.xx.xx.xx 4 | cfme_cred_repo: https://repo 5 | cfme_cred_repo_dir: /cfme-qe-yamls 6 | cfme_repo: https://github.com/RedHatQE/cfme_tests 7 | cfme_repo_dir: /cfme_tests_te 8 | pytest: -k test_bad_password 9 | branch: origin/master 10 | selff: cfmeqe/sel_ff_chrome 11 | pytest_con: py_test_base 12 | artifactor_dir: /log_report 13 | log_depot: /home/username/log_depot/ 14 | banner: True 15 | gh_token: AAAAAAA 16 | gh_owner: RedHatQE 17 | gh_repo: cfme_tests 18 | -------------------------------------------------------------------------------- /conf/env.yaml.template: -------------------------------------------------------------------------------- 1 | appliances: 2 | - hostname: 10.11.12.13 3 | browser: 4 | webdriver: Remote 5 | webdriver_options: 6 | desired_capabilities: 7 | platform: LINUX 8 | browserName: 'chrome' 9 | unexpectedAlertBehaviour: 'ignore' 10 | github: 11 | default_repo: foo/bar 12 | token: abcdef0123456789 13 | bugzilla: 14 | url: https://bugzilla.redhat.com/xmlrpc.cgi 15 | loose: # Params of BugzillaBug to be converted to LooseVersion at runtime 16 | - target_release 17 | - version 18 | - fixed_in 19 | upstream_version: "master" 20 | credentials: cred_file_key 21 | skip: # Bug states that are considered for skipping (not used now but will be incorporated later) 22 | - ON_DEV 23 | - NEW 24 | - ASSIGNED 25 | mail_collector: 26 | ports: 27 | smtp: 25 28 | -------------------------------------------------------------------------------- /conf/polarion_tools.local.yaml.template: -------------------------------------------------------------------------------- 1 | repo_address: https://github.com/ManageIQ/integration_tests 2 | polarion-project-id: 3 | xunit_import_properties: 4 | polarion-lookup-method: name 5 | polarion-testrun-status-id: inprogress 6 | polarion-testrun-template-id: 7 | polarion-group-id: 8 | polarion-testrun-title: 9 | polarion-testrun-id: 10 | testcase_import_properties: 11 | lookup-method: name 12 | polarion_url: 13 | 14 | username: 15 | password: 16 | 17 | blacklisted_tests: 18 | - 'test_import_own_module' 19 | 20 | whitelisted_tests: 21 | - 'cfme/tests/v2v' 22 | 23 | known_fields: 24 | assignee: "" 25 | initialEstimate: "" 26 | caseimportance: high 27 | caselevel: component 28 | caseposneg: positive 29 | caseautomation: automated 30 | testtype: functional 31 | casecomponent: "-" 32 | subtype1: "-" 33 | subtype2: "-" 34 | tags: "" 35 | setup: "" 36 | teardown: "" 37 | description: "" 38 | linkedWorkItems: "" 39 | testSteps: "" 40 | expectedResults: "" 41 | title: "" 42 | work_item_id: "" 43 | -------------------------------------------------------------------------------- /conf/polarion_tools.yaml.template: -------------------------------------------------------------------------------- 1 | polarion-project-id: PROJECTID 2 | xunit_import_properties: 3 | polarion-lookup-method: name 4 | polarion-testrun-status-id: inprogress 5 | testcase_import_properties: 6 | lookup-method: name 7 | polarion_url: https://polarion.example.com 8 | -------------------------------------------------------------------------------- /conf/supportability.yaml: -------------------------------------------------------------------------------- 1 | 'master': 2 | providers: 3 | infra: 4 | - virtualcenter: 5 | - 5.5 6 | - 6.0 7 | - 6.5 8 | - 6.7 9 | - rhevm: 10 | - 4.1 11 | - 4.2 12 | - 4.3 13 | - 4.4 14 | - scvmm: 15 | - 2012 16 | - 2016 17 | cloud: 18 | - openstack: 19 | - 11 20 | - 12 21 | - 13 22 | - 14 23 | - ec2 24 | - gce 25 | - azure: 26 | - common 27 | - msdn 28 | container: 29 | - openshift: 30 | - 3.5 31 | - 3.6 32 | - 3.7 33 | - 3.9 34 | - 3.11 35 | config_manager: 36 | - satellite: 37 | - 6.2 38 | - ansible_tower: 39 | - 3.10 40 | - 3.4 41 | - 3.5 42 | -------------------------------------------------------------------------------- /data/basiccloudinit.cfg: -------------------------------------------------------------------------------- 1 | #cloud-config 2 | password: $pass 3 | chpasswd: { expire: False } 4 | ssh_pwauth: True -------------------------------------------------------------------------------- /data/bugzilla-queries/fixed_in_query.yaml: -------------------------------------------------------------------------------- 1 | - query: 2 | product: 3 | - Red Hat CloudForms Management Engine 4 | include_fields: 5 | - id 6 | - summary 7 | - component 8 | - description 9 | - status 10 | - qa_contact 11 | - creator 12 | - assigned_to 13 | - version 14 | - fixed_in 15 | fixed_in: 16 | - "5.10.11.0" 17 | -------------------------------------------------------------------------------- /data/cert-auths/cmqe-tests-openshift-signer.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIC6jCCAdKgAwIBAgIBATANBgkqhkiG9w0BAQsFADAmMSQwIgYDVQQDDBtvcGVu 3 | c2hpZnQtc2lnbmVyQDE0OTY1NjE5NjgwHhcNMTcwNjA0MDczOTI4WhcNMjIwNjAz 4 | MDczOTI5WjAmMSQwIgYDVQQDDBtvcGVuc2hpZnQtc2lnbmVyQDE0OTY1NjE5Njgw 5 | ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDSZ0OmUSjRsS0r9AolBWs0 6 | 6T2GA/3mmY2UfoYzAUSY81xws12mdC47OdfH8jrovahsfNV28u9eTvf7j2FqRAYA 7 | uhdyINldNXes40ky8xQ2UsI/WrOWYkwWvUf/RU9QHpqcBnT4YbASR4/LKHW5xwgx 8 | QKWC7rrqxThfktF7nxePQjEWQDemxrJm1aoouFN27yJdnrt8koo3qrTHYGQa7AUF 9 | aeCz3ivhEBJbcQde8RncUyWu7UgkWtos5XRjBwujukbmF9HU0+R46Med38rq7zH5 10 | xM+unDjBUzSkugKAzT8lgpzYvWtiy8Mu/Sbq+aQKAcXCpflAOgWd8cTkh8opRu1N 11 | AgMBAAGjIzAhMA4GA1UdDwEB/wQEAwICpDAPBgNVHRMBAf8EBTADAQH/MA0GCSqG 12 | SIb3DQEBCwUAA4IBAQBDfsyzc5C5GGaxuTtkO3ilUkZOGYw6+5hHt/hXcJAt9v9l 13 | gmC2ZIEEqYcl0KPlbscSY2I/Zg3nCu0OTYZ5MBGI5eW+34I6M9vooia43A5c3F6b 14 | p3mG47GsfYjmAeAbenXnCYnu4OrzRU6V93IZuUDg0ICHWGwBwLhlnNSvmTBkw5Pr 15 | bRmyp3sfUe83Hn3AxG9HKAesoHv8ux269QD23gVCTo5A0YhxDfamQJBL6pwpRxUp 16 | efQFDmj0boTzpvNxVKmz5rHHCFNZ0tbNV/Biwmjcul+AGSgTNSB9dlEZkrOjwQag 17 | 35ybxAYT0z6Rod6X0dvheKo4XKoPxO5RRlTYikQZ 18 | -----END CERTIFICATE----- -------------------------------------------------------------------------------- /data/cfme/utils/test_datafile_fixture/test_template: -------------------------------------------------------------------------------- 1 | $replaceme -------------------------------------------------------------------------------- /data/firefox_profile.js.template: -------------------------------------------------------------------------------- 1 | { 2 | "browser.download.folderList": 2, 3 | "browser.download.manager.showWhenStarting": false, 4 | "services.sync.prefs.sync.browser.download.manager.showWhenStarting": false, 5 | "browser.download.dir": "$profile_dir", 6 | "browser.helperApps.neverAsk.saveToDisk": "application/txt,application/csv,application/pdf,application/octet-stream,text/csv,text/plain", 7 | "network.http.max-persistent-connections-per-server": 20, 8 | "security.dialog_enable_delay": 0 9 | } 10 | -------------------------------------------------------------------------------- /data/orchestration/openstack_vm_template.data: -------------------------------------------------------------------------------- 1 | heat_template_version: 2013-05-23 2 | description: Simple template CFMETemplateName to deploy a single compute instance 3 | parameters: 4 | image: 5 | type: string 6 | label: Image name or ID 7 | description: Image to be used for compute instance 8 | default: cirros 9 | flavor: 10 | type: string 11 | label: Flavor 12 | description: Type of instance (flavor) to be used 13 | default: m1.small 14 | key: 15 | type: string 16 | label: Key name 17 | description: Name of key-pair to be used for compute instance 18 | default: psav 19 | private_network: 20 | type: string 21 | label: Private network name or ID 22 | description: Network to attach instance to. 23 | default: c0f0db9c-846f-4d4e-b058-0db5bfb2cb90 24 | resources: 25 | my_instance: 26 | type: OS::Nova::Server 27 | properties: 28 | image: { get_param: image } 29 | flavor: { get_param: flavor } 30 | key_name: { get_param: key } 31 | networks: 32 | - uuid: { get_param: private_network } 33 | outputs: 34 | instance_ip: 35 | description: IP address of the instance 36 | value: { get_attr: [my_instance, first_address]} 37 | -------------------------------------------------------------------------------- /data/orchestration/rhos13_vm_template.data: -------------------------------------------------------------------------------- 1 | heat_template_version: 2018-03-02 2 | description: Simple template CFMETemplateName to deploy a single compute instance 3 | parameters: 4 | image: 5 | type: string 6 | label: Image name or ID 7 | description: Image to be used for compute instance 8 | default: cirros 9 | flavor: 10 | type: string 11 | label: Flavor 12 | description: Type of instance (flavor) to be used 13 | default: m1.tiny 14 | key: 15 | type: string 16 | label: Key name 17 | description: Name of key-pair to be used for compute instance 18 | default: default_key 19 | private_network: 20 | type: string 21 | label: Private network name or ID 22 | description: Network to attach instance to. 23 | default: private 24 | resources: 25 | my_instance: 26 | type: OS::Nova::Server 27 | properties: 28 | image: { get_param: image } 29 | flavor: { get_param: flavor } 30 | key_name: { get_param: key } 31 | networks: 32 | - uuid: { get_param: private_network } 33 | outputs: 34 | instance_ip: 35 | description: IP address of the instance 36 | value: { get_attr: [my_instance, first_address]} 37 | -------------------------------------------------------------------------------- /data/patches/autofocus.js.diff: -------------------------------------------------------------------------------- 1 | --- autofocus.js 2016-05-09 07:15:14.333132210 -0400 2 | +++ autofocus.js.new 2016-05-09 07:09:10.016132210 -0400 3 | @@ -8,8 +8,10 @@ 4 | if(attr.autoFocus == "" || attr.autoFocus == "proactiveFocus") { 5 | angular.element(scope['form_focus_' + ctrl.$name]).focus(); 6 | if (!angular.element(scope['form_focus_' + ctrl.$name]).is(":focus")) { 7 | + MiqQE['autofocus'] += 1; 8 | $timeout(function () { 9 | angular.element(scope['form_focus_' + ctrl.$name]).focus(); 10 | + MiqQE['autofocus'] -= 1; 11 | }, 1000); 12 | } 13 | } 14 | @@ -17,8 +19,10 @@ 15 | 16 | scope.$on('reactiveFocus', function(e) {; 17 | if (!angular.element(scope['form_focus_' + ctrl.$name]).is(":focus")) { 18 | + MiqQE['autofocus'] += 1; 19 | $timeout(function(){ 20 | angular.element(scope['form_focus_' + ctrl.$name]).focus(); 21 | + MiqQE['autofocus'] -= 1; 22 | }, 0); 23 | }; 24 | }); 25 | -------------------------------------------------------------------------------- /data/patches/autofocus_57.js.diff: -------------------------------------------------------------------------------- 1 | --- autofocus.js 2016-05-09 07:15:14.333132210 -0400 2 | +++ autofocus.js.new 2016-05-09 07:09:10.016132210 -0400 3 | @@ -8,8 +8,10 @@ 4 | if (attr.autoFocus == "" || attr.autoFocus == "proactiveFocus") { 5 | angular.element(scope['form_focus_' + ctrl.$name]).focus(); 6 | if (!angular.element(scope['form_focus_' + ctrl.$name]).is(":focus")) { 7 | + MiqQE['autofocus'] += 1; 8 | $timeout(function () { 9 | angular.element(scope['form_focus_' + ctrl.$name]).focus(); 10 | + MiqQE['autofocus'] -= 1; 11 | }, 1000); 12 | } 13 | } 14 | @@ -17,8 +19,10 @@ 15 | 16 | scope.$on('reactiveFocus', function(_e) { 17 | if (!angular.element(scope['form_focus_' + ctrl.$name]).is(":focus")) { 18 | + MiqQE['autofocus'] += 1; 19 | $timeout(function() { 20 | angular.element(scope['form_focus_' + ctrl.$name]).focus(); 21 | + MiqQE['autofocus'] -= 1; 22 | }, 0); 23 | }; 24 | }); 25 | -------------------------------------------------------------------------------- /data/patches/ovirt_gem.patch: -------------------------------------------------------------------------------- 1 | --- ovirt_metrics.rb 2016-11-01 18:42:06.000000000 -0400 2 | +++ patched_ovirt_metrics.rb 2016-11-03 17:13:39.352793586 -0400 3 | @@ -43,7 +43,9 @@ 4 | end 5 | 6 | def self.disconnect 7 | - OvirtHistory.connection.disconnect! 8 | + # Patched pending change to help automation 9 | + # OvirtHistory.connection.disconnect! 10 | + OvirtHistory.remove_connection 11 | end 12 | 13 | def self.vm_realtime(vm_id, start_time = nil, end_time = nil) 14 | -------------------------------------------------------------------------------- /data/reports_crud/basic01.yaml: -------------------------------------------------------------------------------- 1 | menu_name: testing report 2 | title: Testing report 3 | base_report_on: VMs and Instances 4 | report_fields: 5 | - Archived 6 | - Autostart 7 | - Boot Time 8 | - Busy 9 | - CPU - % Overallocated 10 | - Name 11 | cancel_after: 1 Hour 12 | consolidation: 13 | group_records: 14 | - Busy 15 | - Archived 16 | calculations_grouped: CPU - % Overallocated 17 | formatting: 18 | page_size: A4 - 210mm x 297mm (default) -------------------------------------------------------------------------------- /data/resources/middleware/cfme_test_ear_middleware.ear: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/data/resources/middleware/cfme_test_ear_middleware.ear -------------------------------------------------------------------------------- /data/resources/middleware/cfme_test_jar_middleware.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/data/resources/middleware/cfme_test_jar_middleware.jar -------------------------------------------------------------------------------- /data/resources/middleware/cfme_test_war_middleware.war: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/data/resources/middleware/cfme_test_war_middleware.war -------------------------------------------------------------------------------- /data/resources/middleware/new_cfme_test_war_middleware.war: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/data/resources/middleware/new_cfme_test_war_middleware.war -------------------------------------------------------------------------------- /data/rootpass.cfg: -------------------------------------------------------------------------------- 1 | #cloud-config 2 | chpasswd: 3 | list: | 4 | root:$pass 5 | expire: False 6 | ssh_pwauth: True -------------------------------------------------------------------------------- /data/schedules_crud/basic01.yaml: -------------------------------------------------------------------------------- 1 | name: testing schedule 1 2 | description: description of testing schedule 1 3 | report_filter: 4 | filter_type: Events 5 | subfilter_type: Policy 6 | report_type: Policy Events for Last Week 7 | active: True 8 | timer: 9 | run: Hourly 10 | timer_hour: 2 Hours 11 | hour: '12' 12 | minute: '5' 13 | time_zone: (GMT+10:00) Melbourne 14 | email: 15 | to_emails: 16 | - test1@example.test 17 | - test2@example.test 18 | from_email: sender@example.test 19 | email_options: 20 | send_if_empty: True 21 | send_txt: True 22 | send_csv: True 23 | send_pdf: True 24 | -------------------------------------------------------------------------------- /data/suite.yaml: -------------------------------------------------------------------------------- 1 | provider_keys: 2 | - ec2 3 | - rhos 4 | - vsphere 5 | - rhevm 6 | - scvmm 7 | infra_provisioning: 8 | name: Infrastructure Provisioning 9 | description: | 10 | This is the infra provisioning suite information -------------------------------------------------------------------------------- /data/templates/base.html: -------------------------------------------------------------------------------- 1 | {%- set bootstrap_version = '3.0.3' -%} 2 | 3 | 4 | 5 | 6 | 7 | {% block title %}{% endblock %} 8 | 9 | 10 | 11 | 12 | {% block scripts %}{% endblock %} 13 | {% block content %}{% endblock %} 14 | 15 | 16 | -------------------------------------------------------------------------------- /data/templates/dist/fonts/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/data/templates/dist/fonts/FontAwesome.otf -------------------------------------------------------------------------------- /data/templates/dist/fonts/OpenSans-Bold-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/data/templates/dist/fonts/OpenSans-Bold-webfont.ttf -------------------------------------------------------------------------------- /data/templates/dist/fonts/OpenSans-Bold-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/data/templates/dist/fonts/OpenSans-Bold-webfont.woff -------------------------------------------------------------------------------- /data/templates/dist/fonts/OpenSans-Light-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/data/templates/dist/fonts/OpenSans-Light-webfont.ttf -------------------------------------------------------------------------------- /data/templates/dist/fonts/OpenSans-Light-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/data/templates/dist/fonts/OpenSans-Light-webfont.woff -------------------------------------------------------------------------------- /data/templates/dist/fonts/OpenSans-Regular-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/data/templates/dist/fonts/OpenSans-Regular-webfont.ttf -------------------------------------------------------------------------------- /data/templates/dist/fonts/OpenSans-Regular-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/data/templates/dist/fonts/OpenSans-Regular-webfont.woff -------------------------------------------------------------------------------- /data/templates/dist/fonts/OpenSans-Semibold-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/data/templates/dist/fonts/OpenSans-Semibold-webfont.ttf -------------------------------------------------------------------------------- /data/templates/dist/fonts/OpenSans-Semibold-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/data/templates/dist/fonts/OpenSans-Semibold-webfont.woff -------------------------------------------------------------------------------- /data/templates/dist/fonts/PatternFlyIcons-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/data/templates/dist/fonts/PatternFlyIcons-webfont.eot -------------------------------------------------------------------------------- /data/templates/dist/fonts/PatternFlyIcons-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/data/templates/dist/fonts/PatternFlyIcons-webfont.ttf -------------------------------------------------------------------------------- /data/templates/dist/fonts/PatternFlyIcons-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/data/templates/dist/fonts/PatternFlyIcons-webfont.woff -------------------------------------------------------------------------------- /data/templates/dist/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/data/templates/dist/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /data/templates/dist/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/data/templates/dist/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /data/templates/dist/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/data/templates/dist/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /data/templates/dist/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/data/templates/dist/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /data/templates/dist/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/data/templates/dist/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /data/templates/dist/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/data/templates/dist/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /data/templates/dist/img/console.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/data/templates/dist/img/console.png -------------------------------------------------------------------------------- /data/templates/dist/img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/data/templates/dist/img/favicon.ico -------------------------------------------------------------------------------- /data/templates/dist/img/spinner-lg.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/data/templates/dist/img/spinner-lg.gif -------------------------------------------------------------------------------- /data/templates/dist/img/spinner-sm.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/data/templates/dist/img/spinner-sm.gif -------------------------------------------------------------------------------- /data/templates/dist/img/spinner-xs.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/data/templates/dist/img/spinner-xs.gif -------------------------------------------------------------------------------- /data/templates/dist/img/spinner.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/data/templates/dist/img/spinner.gif -------------------------------------------------------------------------------- /data/templates/dist/themes/default/32px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/data/templates/dist/themes/default/32px.png -------------------------------------------------------------------------------- /data/templates/dist/themes/default/40px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/data/templates/dist/themes/default/40px.png -------------------------------------------------------------------------------- /data/templates/dist/themes/default/throbber.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/data/templates/dist/themes/default/throbber.gif -------------------------------------------------------------------------------- /data/templates/pattern_base.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | {% block title %}{% endblock %} 7 | 8 | 9 | 10 | {% block scripts %}{% endblock %} 11 | {% block extrahead %}{% endblock %} 12 | 13 | 14 | {% block nav %} 15 | 24 | {% endblock %} 25 |

26 | {% block content %}{% endblock %} 27 | 28 | 29 | -------------------------------------------------------------------------------- /data/templates/usage_report.html: -------------------------------------------------------------------------------- 1 | {%- set bootstrap_version = '3.0.3' -%} 2 | 3 | 4 | 5 | 6 | 7 | Usage Report 8 | 9 | 10 | 11 |

Provider Usage Report

12 | {{data}} 13 | 14 | 15 | -------------------------------------------------------------------------------- /data/ui/automate/ds2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | //system/evm/discover/${//workspace/aevent/type} 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | this should be a method to get the OS if it is not in the inbound object 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /data/ui/control/invalid.yaml: -------------------------------------------------------------------------------- 1 | Invalid yaml -------------------------------------------------------------------------------- /data/ui/infrastructure/test_host_provisioning/vmware_esx_55.cfg: -------------------------------------------------------------------------------- 1 | # 2 | # Sample scripted installation file 3 | # 4 | # Accept the VMware End User License Agreement 5 | vmaccepteula 6 | # Set the root password for the DCUI and Tech Support Mode 7 | rootpw --iscrypted <%= MiqPassword.md5crypt(evm[:root_password]) %> 8 | # The install media is in the CD-ROM drive 9 | clearpart --firstdisk=local --overwritevmfs 10 | install --firstdisk --overwritevmfs 11 | # Set the network to DHCP on the first network adapater 12 | <%= 13 | network_string = "network --bootproto=static --device=vmnic0" 14 | ["ip", :ip_addr, "netmask", :subnet_mask, "gateway", :gateway, "hostname", :hostname, "nameserver", :dns_servers].each_slice(2) do |ks_key, evm_key| 15 | network_string << " --#{ks_key}=#{evm[evm_key]}" unless evm[evm_key].blank? 16 | end 17 | network_string 18 | %> 19 | 20 | reboot --noeject 21 | 22 | # A sample post-install script 23 | #%post --interpreter=python --ignorefailure=true 24 | %firstboot --interpreter=python 25 | print "rediculous" 26 | import urllib 27 | import sys 28 | 29 | try: 30 | urllib.urlretrieve("<%= evm[:post_install_callback_url] %>") 31 | except: 32 | print sys.exc_info() 33 | 34 | 35 | -------------------------------------------------------------------------------- /data/utils/cfmedb_load_config.rbt: -------------------------------------------------------------------------------- 1 | new_conf = YAML::load(File.open('$config_file')) 2 | Configuration.create_or_update(MiqServer.my_server, new_conf, '$config_name') -------------------------------------------------------------------------------- /data/utils/cfmedb_set_config.rbt: -------------------------------------------------------------------------------- 1 | new_conf = YAML::load(File.open('$config_file')) 2 | new_conf_symbol = new_conf.deep_symbolize_keys.to_yaml 3 | result = VMDB::Config.save_file(new_conf_symbol) # Save the config file 4 | if result != true 5 | exit 255 6 | end 7 | -------------------------------------------------------------------------------- /data/utils/test_simple_locators/elements.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |

Test!

5 |

Test!

6 | 7 | 8 | -------------------------------------------------------------------------------- /data/vmware_esx_55_remote.cfg: -------------------------------------------------------------------------------- 1 | # 2 | # Sample scripted installation file 3 | # 4 | # Accept the VMware End User License Agreement 5 | vmaccepteula 6 | # Set the root password for the DCUI and Tech Support Mode 7 | rootpw --iscrypted <%= MiqPassword.md5crypt(evm[:root_password]) %> 8 | # The install media is in the CD-ROM drive 9 | clearpart --firstdisk=remote --overwritevmfs 10 | install --firstdisk --overwritevmfs 11 | # Set the network to DHCP on the first network adapater 12 | <%= 13 | network_string = "network --bootproto=static --device=vmnic0" 14 | ["ip", :ip_addr, "netmask", :subnet_mask, "gateway", :gateway, "hostname", :hostname, "nameserver", :dns_servers].each_slice(2) do |ks_key, evm_key| 15 | network_string << " --#{ks_key}=#{evm[evm_key]}" unless evm[evm_key].blank? 16 | end 17 | network_string 18 | %> 19 | 20 | reboot --noeject 21 | 22 | # A sample post-install script 23 | #%post --interpreter=python --ignorefailure=true 24 | %firstboot --interpreter=python 25 | print "rediculous" 26 | import urllib 27 | import sys 28 | 29 | try: 30 | urllib.urlretrieve("<%= evm[:post_install_callback_url] %>") 31 | except: 32 | print sys.exc_info() 33 | 34 | 35 | -------------------------------------------------------------------------------- /dockerfiles/cfme_tests_base/Dockerfile: -------------------------------------------------------------------------------- 1 | # Our custom docker image with app 2 | FROM fedora:23 3 | MAINTAINER 4 | 5 | LABEL company="Redhat" product="CFME" environment="dev" tier="test" 6 | 7 | # mandatory packages 8 | RUN dnf -y install git python-pip gcc postgresql-devel libxml2-devel libxslt-devel zeromq3-devel libcurl-devel python-devel redhat-rpm-config libffi-devel openssl-devel \ 9 | tigervnc-server fluxbox xterm java-1.8.0-openjdk.x86_64 \ 10 | ftp://rpmfind.net/linux/fedora/linux/releases/22/Everything/x86_64/os/Packages/f/firefox-38.0.1-1.fc22.x86_64.rpm \ 11 | python-setuptools sshpass findutils \ 12 | && dnf clean all 13 | -------------------------------------------------------------------------------- /dockerfiles/cfme_tests_img/xstartup: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Set up the environment so selenium can find everything it might want 4 | # (namely chrome and chromedriver) 5 | #export PATH="/path/to/google/chrome/directory/:/path/to/chromdriver/directory:$PATH" 6 | 7 | # Start the window manager 8 | fluxbox & 9 | 10 | # Start the selenium server 11 | xterm -maximized -e java -jar $CFME_ENV/selenium/selenium_latest.jar -ensureCleanSession -trustAllSSLCertificates & 12 | -------------------------------------------------------------------------------- /docs/_static/.placeholder: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/docs/_static/.placeholder -------------------------------------------------------------------------------- /docs/_static/framework.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/docs/_static/framework.png -------------------------------------------------------------------------------- /docs/guides.rst: -------------------------------------------------------------------------------- 1 | Guides 2 | ====== 3 | 4 | .. toctree:: 5 | :glob: 6 | 7 | guides/* 8 | -------------------------------------------------------------------------------- /docs/guides/abbrev.rst: -------------------------------------------------------------------------------- 1 | Abbreviations and Naming Conventions 2 | ==================================== 3 | 4 | Abbreviations 5 | ------------- 6 | 7 | In order to save line space and aid in quick pass reading, we have defined some abbreviations 8 | which we propose to be used throughout the code base. 9 | 10 | Common Terms 11 | ^^^^^^^^^^^^ 12 | 13 | ============ ================================ 14 | Abbreviation Meaning 15 | ============ ================================ 16 | cfg, config Configuration 17 | prov Provider 18 | pg Page 19 | db Database 20 | img Image 21 | vm Virtual Machine 22 | creds Credentials 23 | ============ ================================ 24 | 25 | Locator Terms 26 | ^^^^^^^^^^^^^ 27 | 28 | ============ ================================ 29 | Abbreviation Meaning 30 | ============ ================================ 31 | btn button 32 | sel select 33 | txt text 34 | pwd password 35 | chk checkbox 36 | tarea textarea 37 | ============ ================================ 38 | -------------------------------------------------------------------------------- /docs/guides/debugging.rst: -------------------------------------------------------------------------------- 1 | Debugging 2 | ========= 3 | 4 | Pytest has a cool feature to enable a debugger on failures. Just provide an additional 5 | command line option:: 6 | 7 | pytest --pdb 8 | 9 | By default only python builtin debugger is supported. It's not much convinient to 10 | use. There is another python debugger called pudb. It requires only two packages 11 | to be installed:: 12 | 13 | pip install pytest-pudb pudb 14 | 15 | Then you can use it in such way:: 16 | 17 | pytest some_test --pudb 18 | 19 | Links 20 | ^^^^^ 21 | 22 | https://github.com/inducer/pudb 23 | 24 | https://github.com/wronglink/pytest-pudb 25 | -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | Welcome to cfme_tests's documentation! 2 | ====================================== 3 | 4 | Contents: 5 | 6 | .. toctree:: 7 | :titlesonly: 8 | :maxdepth: 2 9 | 10 | getting_started 11 | guides 12 | modules 13 | 14 | Indices and tables 15 | ================== 16 | 17 | * :ref:`genindex` 18 | * :ref:`modindex` 19 | * :ref:`search` 20 | -------------------------------------------------------------------------------- /docs/inventory.py: -------------------------------------------------------------------------------- 1 | """Dumps intersphinx inventorys to stdout to easily find intersphinx refs 2 | 3 | You probably want to pipe this to a pager. 4 | 5 | """ 6 | import os 7 | import sys 8 | 9 | from sphinx.ext import intersphinx 10 | 11 | from conf import intersphinx_mapping 12 | 13 | 14 | class App: 15 | # Fake app for passing to fetch_inventory 16 | srcdir = "." 17 | 18 | def __init__(self, package_name): 19 | self.name = package_name 20 | 21 | def warn(self, msg): 22 | print(msg) 23 | 24 | 25 | def main(): 26 | for package_name, (uri, inv) in intersphinx_mapping.items(): 27 | if inv is None: 28 | inv = "objects.inv" 29 | inv_uri = os.path.join(uri, inv) 30 | app = App(package_name) 31 | inventory = intersphinx.fetch_inventory(app, "", inv_uri) 32 | for k in inventory.keys(): 33 | print(f"{app.name} {k}") 34 | for name, value in inventory[k].items(): 35 | print("{} {} is <{}:{}>".format(k, value[2], app.name, name)) 36 | 37 | 38 | if __name__ == "__main__": 39 | sys.exit(main()) 40 | -------------------------------------------------------------------------------- /docs/modules.rst: -------------------------------------------------------------------------------- 1 | Modules 2 | ======= 3 | 4 | .. toctree:: 5 | :glob: 6 | 7 | modules/cfme/cfme 8 | -------------------------------------------------------------------------------- /docs/pr_process.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/docs/pr_process.png -------------------------------------------------------------------------------- /docs/requirements.txt: -------------------------------------------------------------------------------- 1 | # temporary backward compat 2 | -r ../requirements/docs.txt 3 | -------------------------------------------------------------------------------- /eng.user-words: -------------------------------------------------------------------------------- 1 | root@photon-machine 2 | touch 3 | blather 4 | Welcome 5 | to 6 | Photon 7 | 1.0 8 | (x86_64) 9 | - 10 | Kernel 11 | 4.4.71-1.ph1-esx 12 | tty1 13 | $ touch blather 14 | cubswin:) 15 | -------------------------------------------------------------------------------- /log/.placeholder: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/log/.placeholder -------------------------------------------------------------------------------- /pytest.ini: -------------------------------------------------------------------------------- 1 | [pytest] 2 | filterwarnings = 3 | ignore::urllib3.exceptions.InsecureRequestWarning 4 | ignore:.*unclosed =0.32.0 4 | -------------------------------------------------------------------------------- /requirements/dev.txt: -------------------------------------------------------------------------------- 1 | -r frozen.txt 2 | # do editable self-install to avoid need for pythonpath changes 3 | -e . 4 | -------------------------------------------------------------------------------- /requirements/docs.txt: -------------------------------------------------------------------------------- 1 | -r frozen_docs.py3.txt 2 | # do editable self-install to avoid need for pythonpath changes 3 | -e . 4 | -------------------------------------------------------------------------------- /requirements/docs/positional-1.1.1-py2.py3-none-any.whl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/requirements/docs/positional-1.1.1-py2.py3-none-any.whl -------------------------------------------------------------------------------- /requirements/docs/readme.txt: -------------------------------------------------------------------------------- 1 | these wheels are used to ensure a working build on readthedocs 2 | 3 | for some reason pbr broke the build there 4 | -------------------------------------------------------------------------------- /requirements/docs/yaycl-0.2.0-cp27-none-any.whl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/requirements/docs/yaycl-0.2.0-cp27-none-any.whl -------------------------------------------------------------------------------- /requirements/docs/yaycl_crypt-0.2.0-cp27-none-any.whl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/requirements/docs/yaycl_crypt-0.2.0-cp27-none-any.whl -------------------------------------------------------------------------------- /requirements/on_rtd.txt: -------------------------------------------------------------------------------- 1 | # enable the usage of the wheels we add for pbr-broken packages 2 | --find-links ./docs/ 3 | -r frozen_docs.py3.txt 4 | -------------------------------------------------------------------------------- /requirements/package_map.yaml: -------------------------------------------------------------------------------- 1 | # this file is for mapping import names to library/package names so that 2 | # importlib_metadata can properly fetch them 3 | packages: 4 | bugzilla: python-bugzilla 5 | Crypto: pycryptodome 6 | docker: docker-py 7 | git: GitPython 8 | github: PyGithub 9 | widgetastic: widgetastic.core 10 | widgetastic_patternfly: widgetastic.patternfly 11 | zmq: pyzmq 12 | keycloak: python-keycloak 13 | -------------------------------------------------------------------------------- /requirements/perf.txt: -------------------------------------------------------------------------------- 1 | # include what we need for performance testing 2 | -r frozen.txt 3 | 4 | matplotlib==1.5.1 5 | -------------------------------------------------------------------------------- /requirements/quickstart/needs.txt: -------------------------------------------------------------------------------- 1 | distro==1.0.4 2 | -------------------------------------------------------------------------------- /requirements/template_non_imported.txt: -------------------------------------------------------------------------------- 1 | -c constraints.txt 2 | ansible 3 | bugzilla-docstrings 4 | cfme-testcases 5 | distro 6 | dump2polarion 7 | flake8 8 | pdfminer.six 9 | polarion-docstrings 10 | polarion-tools-common 11 | pre-commit 12 | pytest-mock 13 | pytest-polarion-collect 14 | pytest-report-parameters 15 | -------------------------------------------------------------------------------- /requirements/template_scanned_imports.txt: -------------------------------------------------------------------------------- 1 | -c constraints.txt 2 | GitPython 3 | Jinja2 4 | PyGithub 5 | SQLAlchemy 6 | Sphinx 7 | Werkzeug 8 | aenum 9 | bottle 10 | bugzilla-data 11 | cached-property 12 | click 13 | cycler 14 | dateparser 15 | debtcollector 16 | deepdiff 17 | diaper 18 | docker 19 | fauxfactory 20 | gevent 21 | humanfriendly 22 | importlib-metadata 23 | importscan 24 | ipython 25 | iso8601 26 | jira 27 | jsmin 28 | keystoneauth1 29 | kwargify 30 | lxml 31 | manageiq-client 32 | miq-version 33 | navmazing 34 | paramiko 35 | paramiko-expect 36 | pika 37 | pip-module-scanner 38 | py 39 | pycryptodome 40 | pygal 41 | pytesseract 42 | pytest 43 | pytest-polarion-collect 44 | python-bugzilla 45 | python-keycloak 46 | pytz 47 | pyzmq 48 | requests 49 | riggerlib 50 | scp 51 | selenium 52 | sentaku 53 | setuptools 54 | slumber 55 | sphinx-rtd-theme 56 | tabulate 57 | tzlocal 58 | urllib3 59 | varmeth 60 | wait-for 61 | widgetastic.core 62 | widgetastic.patternfly 63 | wrapanapi 64 | xmltodict 65 | yaycl 66 | yaycl-crypt 67 | -------------------------------------------------------------------------------- /scripts/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/scripts/__init__.py -------------------------------------------------------------------------------- /scripts/browser.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | from IPython import embed 3 | 4 | from cfme.utils.appliance import current_appliance 5 | from cfme.utils.appliance.implementations.ui import navigate_to 6 | 7 | navigate_to(current_appliance.server, 'Dashboard') 8 | embed() 9 | -------------------------------------------------------------------------------- /scripts/cleanup_openstack_fips.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """Cleanup unassigned floating ips 3 | 4 | Usage: scripts/cleanup_openstack_fips.py [optional list of provider keys] 5 | 6 | If no providers specified, it will cleanup all of them. 7 | 8 | """ 9 | import sys 10 | from traceback import format_exc 11 | 12 | from cfme.utils.providers import get_mgmt 13 | from cfme.utils.providers import list_provider_keys 14 | 15 | 16 | def main(*providers): 17 | for provider_key in list_provider_keys('openstack'): 18 | print(f'Checking {provider_key}') 19 | api = get_mgmt(provider_key).api 20 | try: 21 | fips = api.floating_ips.findall(fixed_ip=None) 22 | except Exception: 23 | print(f'Unable to get fips for {provider_key}:') 24 | print(format_exc().splitlines()[-1]) 25 | continue 26 | 27 | for fip in fips: 28 | print(f'Deleting {fip.ip} on {provider_key}') 29 | fip.delete() 30 | print(f'{fip.ip} deleted') 31 | 32 | 33 | if __name__ == "__main__": 34 | provs = sys.argv[1:] 35 | if provs: 36 | main(*provs) 37 | else: 38 | main(*list_provider_keys("openstack")) 39 | -------------------------------------------------------------------------------- /scripts/clone_domain.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """Clone an Automate Domain 3 | 4 | eg, clone_domain.py xx.xx.xx.xx ManageIQ Default 5 | 6 | This can take several minutes to run. 7 | 8 | """ 9 | import argparse 10 | import sys 11 | 12 | from cfme.utils.appliance import IPAppliance 13 | 14 | 15 | def main(): 16 | parser = argparse.ArgumentParser(epilog=__doc__, 17 | formatter_class=argparse.RawDescriptionHelpFormatter) 18 | parser.add_argument('hostname', nargs='?', default=None, 19 | help='hostname or ip address of target appliance') 20 | parser.add_argument('source', nargs='?', default='ManageIQ', 21 | help='Source Domain name') 22 | parser.add_argument('dest', nargs='?', default='Default', 23 | help='Destination Domain name') 24 | args = parser.parse_args() 25 | 26 | ip_a = IPAppliance(hostname=args.hostname) 27 | status, out = ip_a.clone_domain(args.source, args.dest) 28 | return status 29 | 30 | 31 | if __name__ == '__main__': 32 | sys.exit(main()) 33 | -------------------------------------------------------------------------------- /scripts/data/coverage/coverage_gem.rb: -------------------------------------------------------------------------------- 1 | # goes into vmdb/bundler.d/ 2 | gem 'simplecov' 3 | -------------------------------------------------------------------------------- /scripts/data/coverage/coverage_hook.rb: -------------------------------------------------------------------------------- 1 | # set up simplecov, broken out by process for recombining later 2 | require 'fileutils' 3 | require 'yaml' 4 | require 'linux_admin' 5 | require 'simplecov' 6 | 7 | rails_root = '/var/www/miq/vmdb' 8 | 9 | class NullFormatter 10 | # Takes a SimpleCov::Result and does nothing with it 11 | # This ensures we only get the .resultset.json files that get manually merged later 12 | def format(result) 13 | "" 14 | end 15 | end 16 | 17 | SimpleCov.start 'rails' do 18 | root '/' 19 | filters.clear 20 | add_filter do |src| 21 | include_file = src.filename =~ /^#{rails_root}/ 22 | unless include_file 23 | include_file = src.filename =~ /gems\/manageiq-/ 24 | end 25 | unless include_file 26 | include_file = src.filename =~ /gems\/cfme-/ 27 | end 28 | ! include_file 29 | end 30 | # Set the coverage dir for this process to "RAILS_ROOT/coverage/[ipaddress]/[pid]/" 31 | eth0 = LinuxAdmin::NetworkInterface.new("eth0") 32 | coverage_dir File.join(rails_root, "coverage", eth0.address, Process.pid.to_s) 33 | # make sure coverage_dir exists 34 | FileUtils.mkdir_p(SimpleCov.coverage_dir) 35 | # This needs to be unique per simplecov runner 36 | command_name "%s-%s" % [eth0.address, Process.pid] 37 | formatter NullFormatter 38 | end 39 | -------------------------------------------------------------------------------- /scripts/fetch_jenkins_artifacts.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """Collect artifacts after jenkins run 3 | """ 4 | import argparse 5 | import sys 6 | 7 | from cfme.utils.conf import credentials 8 | from cfme.utils.ssh import SSHClient 9 | 10 | 11 | def main(): 12 | parser = argparse.ArgumentParser(epilog=__doc__, 13 | formatter_class=argparse.RawDescriptionHelpFormatter) 14 | parser.add_argument('address', help='hostname or ip address of target appliance') 15 | 16 | args = parser.parse_args() 17 | 18 | ssh_kwargs = { 19 | 'username': credentials['ssh']['username'], 20 | 'password': credentials['ssh']['password'], 21 | 'hostname': args.address 22 | } 23 | 24 | # Init SSH client 25 | with SSHClient(**ssh_kwargs) as ssh_client: 26 | # generate installed rpm list 27 | ssh_client.run_command('rpm -qa | sort > /tmp/installed_rpms.txt') 28 | ssh_client.get_file('/tmp/installed_rpms.txt', 'installed_rpms.txt') 29 | 30 | # compress logs dir 31 | ssh_client.run_command('cd /var/www/miq/vmdb; tar zcf /tmp/appliance_logs.tgz log') 32 | ssh_client.get_file('/tmp/appliance_logs.tgz', 'appliance_logs.tgz') 33 | 34 | 35 | if __name__ == '__main__': 36 | sys.exit(main()) 37 | -------------------------------------------------------------------------------- /scripts/jenkins_failure_analysis.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | from collections import defaultdict 3 | 4 | import requests 5 | from jinja2 import Environment 6 | from jinja2 import FileSystemLoader 7 | 8 | from cfme.utils.conf import jenkins 9 | from cfme.utils.path import log_path 10 | from cfme.utils.path import template_path 11 | 12 | 13 | def get_json(run): 14 | r = requests.get(jenkins['url'].format(run)) 15 | json = r.json() 16 | return json 17 | 18 | 19 | template_env = Environment( 20 | loader=FileSystemLoader(template_path.strpath) 21 | ) 22 | 23 | tests = defaultdict(dict) 24 | 25 | runs = [(run['name'], run['ver']) for run in jenkins['runs']] 26 | 27 | for run, ver in sorted(runs): 28 | 29 | json = get_json(run[0]) 30 | 31 | for case in json['suites'][0]['cases']: 32 | test_name = "{}/{}".format(case['className'], case['name']) 33 | tests[test_name][ver] = { 34 | 'status': case['status'], 35 | 'age': case['age']} 36 | 37 | test_index = sorted(tests) 38 | 39 | data = template_env.get_template('jenkins_report.html').render(tests=tests, 40 | runs=runs, test_index=test_index) 41 | 42 | f = open(log_path.strpath + '/jenkins.html', "w") 43 | f.write(data) 44 | f.close() 45 | -------------------------------------------------------------------------------- /scripts/jsongut.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import json 3 | import sys 4 | 5 | if len(sys.argv) == 1: 6 | print( 7 | """Usage: {} arg1 arg2 ... argN\narg is either a string or int, depending on whether """ 8 | """digging in dict or a list""".format(sys.argv[0])) 9 | exit(0) 10 | 11 | result = json.loads(sys.stdin.read()) 12 | 13 | try: 14 | for arg in sys.argv[1:]: 15 | if isinstance(result, dict): 16 | result = result[arg] 17 | elif isinstance(result, list): 18 | result = result[int(arg)] 19 | else: 20 | print("Cannot apply {} to {}".format(str(arg), str(result))) 21 | exit(1) 22 | except Exception as e: 23 | print("{}\t{}".format(type(e).__name__, str(e))) 24 | exit(2) 25 | 26 | print(result) 27 | -------------------------------------------------------------------------------- /scripts/list_tests.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import os.path 3 | import re 4 | import sys 5 | 6 | if len(sys.argv) == 1: 7 | print(""" 8 | Invoke either by supplying a path or a file and optionally a string to find in a test name 9 | 10 | e.g. list_test . provision 11 | e.g. list_test file.py 12 | """) 13 | sys.exit(1) 14 | 15 | 16 | def parser(filename, exp=None): 17 | try: 18 | with open(filename) as f: 19 | data = f.read() 20 | except OSError: 21 | data = "" 22 | 23 | if not exp: 24 | exp = "" 25 | 26 | p = re.findall(fr'\s*def\s*[a-zA-Z0-9_]*?(test_.*?{exp}.*?)\(', data) 27 | for test in p: 28 | if isinstance(test, str): 29 | print(f"{filename} :: {test}") 30 | else: 31 | print("{} :: {}".format(filename, test[0])) 32 | 33 | 34 | exp = None 35 | if len(sys.argv) == 3: 36 | exp = sys.argv[2] 37 | 38 | if sys.argv[1].endswith('.py'): 39 | parser(sys.argv[1], exp) 40 | else: 41 | files = [os.path.join(d, fn) for d, dn, fns in os.walk(sys.argv[1]) for fn in fns] 42 | 43 | for filename in files: 44 | if filename.endswith('.py'): 45 | parser(filename, exp) 46 | -------------------------------------------------------------------------------- /scripts/loosen_pgssl_connections.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """SSH into a running appliance and loosen postgres connections""" 3 | import argparse 4 | import sys 5 | 6 | from cfme.utils.appliance import IPAppliance 7 | 8 | 9 | def main(): 10 | parser = argparse.ArgumentParser(epilog=__doc__, 11 | formatter_class=argparse.RawDescriptionHelpFormatter) 12 | parser.add_argument('address', help='hostname or ip address of target appliance', 13 | nargs='?', default=None) 14 | parser.add_argument('--with_ssl', help='update for ssl connections', action="store_true") 15 | 16 | args = parser.parse_args() 17 | ip_a = IPAppliance(hostname=args.address) 18 | return ip_a.loosen_pgssl() 19 | 20 | 21 | if __name__ == '__main__': 22 | sys.exit(main()) 23 | -------------------------------------------------------------------------------- /scripts/openshift/change_metrics_collection_threshold.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | 3 | require "pp" 4 | 5 | puts "Welcome to metrics threshold setter" 6 | 7 | threshold = (ARGV[0] or "5.minutes") 8 | 9 | config_changes = {:performance => {:capture_threshold => {:container => threshold, 10 | :ems_cluster => threshold, 11 | :container_group => threshold, 12 | :container_node => threshold}}} 13 | puts "Applying config changes:" 14 | pp config_changes 15 | MiqServer.my_server.set_config(config_changes) 16 | 17 | puts "Saving configuration\n" 18 | MiqServer.my_server.save() 19 | 20 | puts "Done!" 21 | -------------------------------------------------------------------------------- /scripts/openshift/create_ip_aliases.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | start_ip=10.8.218.$1 3 | end_ip=10.8.218.$2 4 | submask='27' 5 | 6 | ip_alias=0 7 | for ip in {${start_ip}..${end_ip}} 8 | do 9 | ip_alias=$((++ip_alias)) 10 | cmd="/sbin/ifconfig enp3s0f0:${ip_alias} ${ip}/${submask}"; 11 | echo "Running cmd ${cmd}"; 12 | eval ${cmd}; 13 | done 14 | -------------------------------------------------------------------------------- /scripts/perf_collect_logs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | if [ ! $# == 2 ]; then 3 | echo "Usage: ./perf_collect_logs.sh " 4 | exit 5 | fi 6 | logdir=$1 7 | prefix=$2 8 | 9 | rm -rf ${logdir}${prefix}.perf.log.gz 10 | 11 | cd $logdir || exit 12 | for file in `ls ${prefix}.log-* | sort -V` 13 | do 14 | echo "Processing $file" 15 | cp ${file} ${file}-2.gz 16 | gunzip ${file}-2.gz 17 | cat ${file}-2 >> ${logdir}${prefix}.perf.log 18 | rm -rf ${file}-2 19 | done 20 | 21 | cat ${logdir}${prefix}.log >> ${logdir}${prefix}.perf.log 22 | gzip ${logdir}${prefix}.perf.log 23 | -------------------------------------------------------------------------------- /scripts/precompile_assets.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """SSH into a running appliance and compile ui assets. 3 | """ 4 | import argparse 5 | import sys 6 | 7 | from cfme.utils.appliance import IPAppliance 8 | 9 | 10 | def main(): 11 | parser = argparse.ArgumentParser(epilog=__doc__, 12 | formatter_class=argparse.RawDescriptionHelpFormatter) 13 | parser.add_argument('address', nargs='?', default=None, 14 | help='hostname or ip address of target appliance') 15 | 16 | args = parser.parse_args() 17 | ip_a = IPAppliance(hostname=args.address) 18 | 19 | status = ip_a.precompile_assets() 20 | if status == 0: 21 | ip_a.evmserverd.restart() 22 | print("EVM service restarted, UI should be available shortly") 23 | return status 24 | 25 | 26 | if __name__ == '__main__': 27 | sys.exit(main()) 28 | -------------------------------------------------------------------------------- /scripts/print_tables.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | from cfme.utils.appliance import current_appliance 3 | 4 | for table_name in current_appliance.db.client: 5 | print(table_name) 6 | -------------------------------------------------------------------------------- /scripts/record.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """Video recording script. 3 | 4 | Use when you want to record something separately 5 | """ 6 | import time 7 | from argparse import ArgumentParser 8 | from argparse import RawDescriptionHelpFormatter 9 | 10 | from cfme.utils.video import Recorder 11 | 12 | 13 | parser = ArgumentParser( 14 | epilog=__doc__, 15 | formatter_class=RawDescriptionHelpFormatter 16 | ) 17 | 18 | parser.add_argument("filename", help="File name to save the recording in") 19 | parser.add_argument("--display", default=None, type=str, help="Display to record") 20 | parser.add_argument("--quality", default=None, type=int, help="Recording quality") 21 | args = parser.parse_args() 22 | 23 | with Recorder(args.filename, args.display, args.quality): 24 | alive = True 25 | while alive: 26 | try: 27 | time.sleep(1) 28 | except KeyboardInterrupt: 29 | alive = False 30 | except Exception: 31 | pass 32 | -------------------------------------------------------------------------------- /scripts/refactoring/checkallimports.py: -------------------------------------------------------------------------------- 1 | import importscan 2 | 3 | to_check = 'cfme artifactor fixtures markers utils' 4 | 5 | if __name__ == '__main__': 6 | for name in to_check.split(): 7 | base = __import__(name) 8 | 9 | def handle_error(name, error): 10 | print(name, error) 11 | importscan.scan(base, handle_error=handle_error) 12 | -------------------------------------------------------------------------------- /scripts/refactoring/provider_move.py: -------------------------------------------------------------------------------- 1 | from rope.base import project 2 | from rope.refactor.move import MoveModule 3 | from rope.refactor.rename import Rename 4 | 5 | my_project = project.Project('.') 6 | 7 | providers_dest = my_project.get_folder('cfme/providers') 8 | if not providers_dest.exists(): 9 | providers_dest.create() 10 | 11 | if not providers_dest.get_children(): 12 | providers_dest.create_file('__init__.py') 13 | 14 | 15 | folders_to_process = ['infrastructure', 'cloud', 'containers'] 16 | 17 | for folder in folders_to_process: 18 | def find(fmt): 19 | return my_project.find_module(fmt.format(folder=folder)) 20 | 21 | print(folder) 22 | print(" append name") 23 | res = find('cfme.{folder}.provider') 24 | Rename(my_project, res).get_changes('provider_' + folder).do() 25 | print(" move") 26 | res = find('cfme.{folder}.provider_{folder}') 27 | MoveModule(my_project, res).get_changes(providers_dest).do() 28 | print(" fix_name") 29 | res = find('cfme.providers.provider_{folder}') 30 | Rename(my_project, res).get_changes(folder).do() 31 | -------------------------------------------------------------------------------- /scripts/refactoring/utils_move.py: -------------------------------------------------------------------------------- 1 | from rope.base.project import Project 2 | from rope.refactor.move import MoveModule 3 | 4 | project = Project('.') 5 | 6 | utils = project.find_module('utils') 7 | move = MoveModule(project, utils) 8 | cfme = project.find_module('cfme') 9 | print(cfme) 10 | changes = move.get_changes(cfme) 11 | changes.do() 12 | -------------------------------------------------------------------------------- /scripts/templates/cfme-run.smem: -------------------------------------------------------------------------------- 1 | {"mappings": {"processes": {"properties": {"cfme_run_md5": {"type": "text", "fields": {"keyword": {"ignore_above": 256, "type": "keyword"}}}, "VSS": {"type": "float"}, "TimeStamp": {"type": "date", "format": "yyyy-MM-dd HH:mm:ss"}, "pid": {"type": "integer"}, "name": {"type": "text", "fields": {"keyword": {"ignore_above": 256, "type": "keyword"}}}, "RSS": {"type": "float"}, "PSS": {"type": "float"}, "scenario": {"type": "text", "fields": {"keyword": {"ignore_above": 256, "type": "keyword"}}}, "USS": {"type": "float"}, "SWAP": {"type": "float"}}}, "appliance_memory": {"properties": {"Used": {"type": "float"}, "cfme_run_md5": {"type": "text", "fields": {"keyword": {"ignore_above": 256, "type": "keyword"}}}, "Slab": {"type": "float"}, "Total": {"type": "float"}, "TimeStamp": {"type": "date", "format": "yyyy-MM-dd HH:mm:ss"}, "Cached": {"type": "float"}, "Free": {"type": "float"}, "scenario": {"type": "text", "fields": {"keyword": {"ignore_above": 256, "type": "keyword"}}}, "Buffers": {"type": "float"}, "Swap_Total": {"type": "float"}, "Swap_Free": {"type": "float"}}}}, "template": "cfme-run.smem-*", "settings": {}} 2 | -------------------------------------------------------------------------------- /scripts/utility-vm/README: -------------------------------------------------------------------------------- 1 | usage 2 | ===== 3 | 4 | SHARE_PASSWORD=changeme \ 5 | RHEL_REPO_BASE=http://download...redhat.com/rel-eng \ 6 | DOWNLOAD_LINK=http://download...redhat.com/brewroot/packages/rhel-guest-image \ 7 | /8.1/68/images/rhel-guest-image-8.1-68.x86_64.qcow2 \ 8 | make 9 | 10 | After the make finishes, you should have utility_vm.qcow2 file in the current 11 | directory which you can upload to the provider. 12 | 13 | To check the created image you may build an iso which will enable you to log-in 14 | using password "changeme" as user "root" or "cloud-user" 15 | 16 | $ make cloud_init.iso 17 | 18 | $ qemu-kvm -nographic -m 1G \ 19 | -drive file=utility_vm.qcow2 \ 20 | -cdrom cloud_init.iso \ 21 | -net nic,model=virtio \ 22 | -net user,hostfwd=tcp::2222-:22 23 | 24 | Note that this act will modify the image. 25 | -------------------------------------------------------------------------------- /scripts/utility-vm/meta-data: -------------------------------------------------------------------------------- 1 | instance-id: Utility-vm-test 2 | local-hostname: utility-vm-test 3 | -------------------------------------------------------------------------------- /scripts/utility-vm/rhel7.repo.template: -------------------------------------------------------------------------------- 1 | [rhel] 2 | name=RHEL 7.0 3 | baseurl=RHEL_REPO_BASE/latest-RHEL-7/compose/Server/x86_64/os/ 4 | enabled=1 5 | gpgcheck=0 6 | skip_if_unavailable=False 7 | -------------------------------------------------------------------------------- /scripts/utility-vm/rhel8.repo.template: -------------------------------------------------------------------------------- 1 | [rhel-BaseOS] 2 | name=RHEL 8.0 3 | baseurl=RHEL_REPO_BASE/latest-RHEL-8/compose/BaseOS/x86_64/os/ 4 | enabled=1 5 | gpgcheck=0 6 | skip_if_unavailable=False 7 | 8 | [rhel-AppStream] 9 | name=RHEL 8.0 AppStream 10 | baseurl=RHEL_REPO_BASE/latest-RHEL-8/compose/AppStream/x86_64/os/ 11 | enabled=1 12 | gpgcheck=0 13 | skip_if_unavailable=False 14 | -------------------------------------------------------------------------------- /scripts/utility-vm/user-data.yaml: -------------------------------------------------------------------------------- 1 | #cloud-config 2 | 3 | debug: True 4 | ssh_pwauth: True 5 | disable_root: false 6 | chpasswd: 7 | list: | 8 | root:changeme 9 | cloud-user:changeme 10 | expire: false 11 | -------------------------------------------------------------------------------- /scripts/wait_for_appliance_ui.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """ 3 | Wait for an appliance UI to be usable 4 | 5 | Specifically, it will block until the specified URL returns status code 200. 6 | """ 7 | import argparse 8 | import sys 9 | 10 | from cfme.utils.appliance import IPAppliance 11 | 12 | 13 | def main(): 14 | parser = argparse.ArgumentParser(epilog=__doc__, 15 | formatter_class=argparse.RawDescriptionHelpFormatter) 16 | parser.add_argument('url', help='URL of target appliance, e.g. "https://ip_or_host/"') 17 | parser.add_argument('--num-sec', default=600, type=int, dest='num_sec', 18 | help='Maximum number of seconds to wait before giving up, default 600 (10 minutes)') 19 | 20 | args = parser.parse_args() 21 | ip_a = IPAppliance.from_url(args.url) 22 | result = ip_a.wait_for_miq_ready(num_sec=args.num_sec) 23 | 24 | if not result: 25 | return 1 26 | 27 | 28 | if __name__ == '__main__': 29 | sys.exit(main()) 30 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [metadata] 2 | name = manageiq-integration-tests 3 | [options] 4 | zip_safe = False 5 | include_package_data = True 6 | packages = find: 7 | entry_points = file:entry_points.txt 8 | 9 | [options.package_data] 10 | * = *.txt, *.rst 11 | 12 | [options.packages.find] 13 | exclude = cfme.tests 14 | 15 | [flake8] 16 | # P663 is bad indentation 17 | # https://gitlab.com/mkourim/polarion_docstrings/issues/1 18 | # erroneous failures, ignore it for now 19 | ignore = E128,E811,W503,W504,P663 20 | max-line-length = 100 21 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | # dummy for editable installs 2 | import os 3 | import sys 4 | 5 | from setuptools import setup 6 | 7 | ALLOWED_COMMANDS = {"develop", "egg_info", "bdist_wheel", "sdist"} 8 | 9 | # just cleanly exit on readthedocs 10 | if os.environ.get("READTHEDOCS") == "True": 11 | sys.exit() 12 | elif ALLOWED_COMMANDS.intersection(sys.argv): 13 | pass 14 | else: 15 | sys.exit("this is a hack, use pip install -e") 16 | 17 | setup(setup_requires=["setuptools_scm>=3.0.0"], use_scm_version=True, python_requires="~=3.7") 18 | -------------------------------------------------------------------------------- /sprout/.gitignore: -------------------------------------------------------------------------------- 1 | access.log 2 | celerybeat-schedule 3 | db.sqlite3 4 | dump.rdb 5 | error.log 6 | log/* 7 | sprout-manager.log 8 | sprout/local_settings.py 9 | 10 | -------------------------------------------------------------------------------- /sprout/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/sprout/__init__.py -------------------------------------------------------------------------------- /sprout/appliances/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/sprout/appliances/__init__.py -------------------------------------------------------------------------------- /sprout/appliances/context_processors.py: -------------------------------------------------------------------------------- 1 | from sprout import redis, settings 2 | 3 | 4 | def hubber_url(request): 5 | return {'hubber_url': settings.HUBBER_URL} 6 | 7 | 8 | def sprout_needs_update(request): 9 | return {"sprout_needs_update": redis._get("sprout-needs-update", default=False)} 10 | -------------------------------------------------------------------------------- /sprout/appliances/migrations/0002_delayedprovisiontask.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | from django.db import models, migrations 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('appliances', '0001_initial'), 10 | ] 11 | 12 | operations = [ 13 | migrations.CreateModel( 14 | name='DelayedProvisionTask', 15 | fields=[ 16 | ( 17 | 'id', 18 | models.AutoField( 19 | verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), 20 | ( 21 | 'lease_time', 22 | models.IntegerField()), 23 | ( 24 | 'pool', 25 | models.ForeignKey(to='appliances.AppliancePool', on_delete=models.CASCADE)), 26 | ], 27 | options={ 28 | }, 29 | bases=(models.Model,), 30 | ), 31 | ] 32 | -------------------------------------------------------------------------------- /sprout/appliances/migrations/0003_auto_20141218_1534.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | from django.db import models, migrations 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('appliances', '0002_delayedprovisiontask'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='delayedprovisiontask', 15 | name='provider_to_avoid', 16 | field=models.ForeignKey(to='appliances.Provider', null=True, on_delete=models.CASCADE), 17 | preserve_default=True, 18 | ), 19 | migrations.AlterField( 20 | model_name='delayedprovisiontask', 21 | name='lease_time', 22 | field=models.IntegerField(null=True), 23 | preserve_default=True, 24 | ), 25 | ] 26 | -------------------------------------------------------------------------------- /sprout/appliances/migrations/0004_provider_appliance_limit.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | from django.db import models, migrations 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('appliances', '0003_auto_20141218_1534'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='provider', 15 | name='appliance_limit', 16 | field=models.IntegerField( 17 | help_text=b'Hard limit of how many appliances can run on this provider', null=True), 18 | preserve_default=True, 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /sprout/appliances/migrations/0005_template_usable.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | from django.db import models, migrations 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('appliances', '0004_provider_appliance_limit'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='template', 15 | name='usable', 16 | field=models.BooleanField(default=False, help_text=b'Template is marked as usable'), 17 | preserve_default=True, 18 | ), 19 | ] 20 | -------------------------------------------------------------------------------- /sprout/appliances/migrations/0007_provider_num_simultaneous_configuring.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | from django.db import models, migrations 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('appliances', '0006_auto_20150122_1256'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='provider', 15 | name='num_simultaneous_configuring', 16 | field=models.IntegerField( 17 | default=1, 18 | help_text=b'How many simultaneous template configuring tasks can run on this' 19 | b' provider.'), 20 | preserve_default=True, 21 | ), 22 | ] 23 | -------------------------------------------------------------------------------- /sprout/appliances/migrations/0008_appliance_uuid.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | from django.db import models, migrations 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('appliances', '0007_provider_num_simultaneous_configuring'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='appliance', 15 | name='uuid', 16 | field=models.CharField( 17 | help_text=b'UUID of the machine', max_length=36, null=True, blank=True), 18 | preserve_default=True, 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /sprout/appliances/migrations/0009_appliancepool_provider.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | from django.db import models, migrations 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('appliances', '0008_appliance_uuid'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='appliancepool', 15 | name='provider', 16 | field=models.ForeignKey( 17 | blank=True, to='appliances.Provider', 18 | help_text=b'If requested, appliances can be on single provider.', null=True, 19 | on_delete=models.CASCADE), 20 | preserve_default=True, 21 | ), 22 | ] 23 | -------------------------------------------------------------------------------- /sprout/appliances/migrations/0010_appliance_power_state_changed.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | from django.db import models, migrations 4 | import django.utils.timezone 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('appliances', '0009_appliancepool_provider'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AddField( 15 | model_name='appliance', 16 | name='power_state_changed', 17 | field=models.DateTimeField(default=django.utils.timezone.now), 18 | preserve_default=True, 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /sprout/appliances/migrations/0011_auto_20150212_0945.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | from django.db import models, migrations 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('appliances', '0010_appliance_power_state_changed'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='delayedprovisiontask', 15 | name='lease_time', 16 | field=models.IntegerField(null=True, blank=True), 17 | preserve_default=True, 18 | ), 19 | migrations.AlterField( 20 | model_name='delayedprovisiontask', 21 | name='provider_to_avoid', 22 | field=models.ForeignKey( 23 | blank=True, to='appliances.Provider', null=True, on_delete=models.CASCADE), 24 | preserve_default=True, 25 | ), 26 | ] 27 | -------------------------------------------------------------------------------- /sprout/appliances/migrations/0012_template_preconfigured.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | from django.db import models, migrations 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('appliances', '0011_auto_20150212_0945'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='template', 15 | name='preconfigured', 16 | field=models.BooleanField(default=True, help_text=b'Is prepared for immediate use?'), 17 | preserve_default=True, 18 | ), 19 | ] 20 | -------------------------------------------------------------------------------- /sprout/appliances/migrations/0013_appliancepool_preconfigured.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | from django.db import models, migrations 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('appliances', '0012_template_preconfigured'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='appliancepool', 15 | name='preconfigured', 16 | field=models.BooleanField( 17 | default=True, help_text=b'Whether to provision preconfigured appliances'), 18 | preserve_default=True, 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /sprout/appliances/migrations/0014_group_unconfigured_template_pool_size.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | from django.db import models, migrations 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('appliances', '0013_appliancepool_preconfigured'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='group', 15 | name='unconfigured_template_pool_size', 16 | field=models.IntegerField( 17 | default=0, 18 | help_text=( 19 | b'How many appliances to keep spinned for quick taking - unconfigured ones.')), 20 | preserve_default=True, 21 | ), 22 | ] 23 | -------------------------------------------------------------------------------- /sprout/appliances/migrations/0015_auto_20150324_1528.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | from django.db import models, migrations 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('appliances', '0014_group_unconfigured_template_pool_size'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='appliance', 15 | name='description', 16 | field=models.TextField(blank=True), 17 | preserve_default=True, 18 | ), 19 | migrations.AddField( 20 | model_name='appliancepool', 21 | name='description', 22 | field=models.TextField(blank=True), 23 | preserve_default=True, 24 | ), 25 | ] 26 | -------------------------------------------------------------------------------- /sprout/appliances/migrations/0016_appliancepool_not_needed_anymore.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | from django.db import models, migrations 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('appliances', '0015_auto_20150324_1528'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='appliancepool', 15 | name='not_needed_anymore', 16 | field=models.BooleanField( 17 | default=False, help_text=b'Used for marking the appliance pool as being deleted'), 18 | preserve_default=True, 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /sprout/appliances/migrations/0017_appliancepool_finished.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | from django.db import models, migrations 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('appliances', '0016_appliancepool_not_needed_anymore'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='appliancepool', 15 | name='finished', 16 | field=models.BooleanField( 17 | default=False, help_text=b'Whether fulfillment has been met.'), 18 | ), 19 | ] 20 | -------------------------------------------------------------------------------- /sprout/appliances/migrations/0018_mismatchversionmailer.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | from django.db import models, migrations 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('appliances', '0017_appliancepool_finished'), 10 | ] 11 | 12 | operations = [ 13 | migrations.CreateModel( 14 | name='MismatchVersionMailer', 15 | fields=[ 16 | ('id', models.AutoField( 17 | verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), 18 | ('template_name', models.CharField(max_length=64)), 19 | ('supposed_version', models.CharField(max_length=32)), 20 | ('actual_version', models.CharField(max_length=32)), 21 | ('sent', models.BooleanField(default=False)), 22 | ('provider', models.ForeignKey(to='appliances.Provider', on_delete=models.CASCADE)), 23 | ], 24 | ), 25 | ] 26 | -------------------------------------------------------------------------------- /sprout/appliances/migrations/0019_auto_20150430_1546.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | from django.db import models, migrations 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('appliances', '0018_mismatchversionmailer'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='group', 15 | name='template_obsolete_days', 16 | field=models.IntegerField( 17 | help_text=b"Templates older than X days won't be loaded into sprout", 18 | null=True, blank=True), 19 | ), 20 | migrations.AddField( 21 | model_name='group', 22 | name='template_obsolete_days_delete', 23 | field=models.BooleanField( 24 | default=False, 25 | help_text=b'If template_obsolete_days set, this will enable deletion of obsolete ' 26 | b'templates using that metric. WARNING! Use with care. Best use for upstream ' 27 | b'templates.'), 28 | ), 29 | ] 30 | -------------------------------------------------------------------------------- /sprout/appliances/migrations/0020_appliance_lun_disk_connected.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | from django.db import models, migrations 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('appliances', '0019_auto_20150430_1546'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='appliance', 15 | name='lun_disk_connected', 16 | field=models.BooleanField( 17 | default=False, help_text=b'Whether the Direct LUN disk is connected. (RHEV Only)'), 18 | ), 19 | ] 20 | -------------------------------------------------------------------------------- /sprout/appliances/migrations/0021_userappliancequota.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | from django.db import models, migrations 4 | from django.conf import settings 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | migrations.swappable_dependency(settings.AUTH_USER_MODEL), 11 | ('appliances', '0020_appliance_lun_disk_connected'), 12 | ] 13 | 14 | operations = [ 15 | migrations.CreateModel( 16 | name='UserApplianceQuota', 17 | fields=[ 18 | ('id', models.AutoField( 19 | verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), 20 | ('per_pool_quota', models.IntegerField(null=True, blank=True)), 21 | ('total_pool_quota', models.IntegerField(null=True, blank=True)), 22 | ('total_vm_quota', models.IntegerField(null=True, blank=True)), 23 | ('user', models.OneToOneField( 24 | related_name='quotas', to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE)), 25 | ], 26 | ), 27 | ] 28 | -------------------------------------------------------------------------------- /sprout/appliances/migrations/0022_appliancepool_yum_update.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | from django.db import models, migrations 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('appliances', '0021_userappliancequota'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='appliancepool', 15 | name='yum_update', 16 | field=models.BooleanField(default=False, help_text=b'Whether to update appliances.'), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /sprout/appliances/migrations/0023_provider_disabled.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('appliances', '0022_appliancepool_yum_update'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='provider', 15 | name='disabled', 16 | field=models.BooleanField( 17 | default=False, help_text=b'We can disable providers if we want.'), 18 | ), 19 | ] 20 | -------------------------------------------------------------------------------- /sprout/appliances/migrations/0024_template_suggested_delete.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 1.9.1 on 2016-01-06 12:38 2 | 3 | 4 | from django.db import migrations, models 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('appliances', '0023_provider_disabled'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AddField( 15 | model_name='template', 16 | name='suggested_delete', 17 | field=models.BooleanField( 18 | default=False, help_text=b'Whether Sprout suggests deleting this template.'), 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /sprout/appliances/migrations/0025_auto_20160106_1446.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 1.9.1 on 2016-01-06 14:46 2 | 3 | 4 | from django.db import migrations, models 5 | import django.db.models.deletion 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('appliances', '0024_template_suggested_delete'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AlterField( 16 | model_name='template', 17 | name='provider', 18 | field=models.ForeignKey( 19 | help_text=b'Where does this template reside', 20 | on_delete=django.db.models.deletion.CASCADE, 21 | related_name='provider_templates', 22 | to='appliances.Provider'), 23 | ), 24 | ] 25 | -------------------------------------------------------------------------------- /sprout/appliances/migrations/0026_template_parent_template.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 1.9.1 on 2016-01-06 16:52 2 | 3 | 4 | from django.db import migrations, models 5 | import django.db.models.deletion 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('appliances', '0025_auto_20160106_1446'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AddField( 16 | model_name='template', 17 | name='parent_template', 18 | field=models.ForeignKey( 19 | blank=True, 20 | help_text=b'What was source of this template?', 21 | null=True, 22 | on_delete=django.db.models.deletion.CASCADE, 23 | related_name='child_templates', 24 | to='appliances.Template'), 25 | ), 26 | ] 27 | -------------------------------------------------------------------------------- /sprout/appliances/migrations/0027_auto_20160310_1637.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 1.9.4 on 2016-03-10 16:37 2 | 3 | 4 | from django.db import migrations, models 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('appliances', '0026_template_parent_template'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AlterField( 15 | model_name='template', 16 | name='version', 17 | field=models.CharField(help_text=b'Downstream version.', max_length=32, null=True), 18 | ), 19 | ] 20 | -------------------------------------------------------------------------------- /sprout/appliances/migrations/0028_auto_20160311_0918.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 1.9.4 on 2016-03-11 09:18 2 | 3 | 4 | from django.db import migrations, models 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('appliances', '0027_auto_20160310_1637'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AlterField( 15 | model_name='appliancepool', 16 | name='version', 17 | field=models.CharField(help_text=b'Appliance version', max_length=32, null=True), 18 | ), 19 | ] 20 | -------------------------------------------------------------------------------- /sprout/appliances/migrations/0029_provider_hidden.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 1.9.4 on 2016-03-14 09:41 2 | 3 | 4 | from django.db import migrations, models 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('appliances', '0028_auto_20160311_0918'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AddField( 15 | model_name='provider', 16 | name='hidden', 17 | field=models.BooleanField( 18 | default=False, help_text=b'We can hide providers if that is required.'), 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /sprout/appliances/migrations/0029_provider_user_groups.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 1.9.4 on 2016-03-14 10:11 2 | 3 | 4 | from django.db import migrations, models 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('auth', '0007_alter_validators_add_error_messages'), 11 | ('appliances', '0028_auto_20160311_0918'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AddField( 16 | model_name='provider', 17 | name='user_groups', 18 | field=models.ManyToManyField( 19 | blank=True, to='auth.Group', 20 | help_text=b'We can specify the providers that are tied to a specific user group.'), 21 | ), 22 | ] 23 | -------------------------------------------------------------------------------- /sprout/appliances/migrations/0030_bugquery.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 1.9.6 on 2016-05-05 07:33 2 | 3 | 4 | from django.conf import settings 5 | from django.db import migrations, models 6 | import django.db.models.deletion 7 | 8 | 9 | class Migration(migrations.Migration): 10 | 11 | dependencies = [ 12 | migrations.swappable_dependency(settings.AUTH_USER_MODEL), 13 | ('appliances', '0029_provider_hidden'), 14 | ] 15 | 16 | operations = [ 17 | migrations.CreateModel( 18 | name='BugQuery', 19 | fields=[ 20 | ('id', models.AutoField( 21 | auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 22 | ('name', models.CharField(max_length=64)), 23 | ('url', models.TextField()), 24 | ('owner', models.ForeignKey( 25 | blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, 26 | to=settings.AUTH_USER_MODEL)), 27 | ], 28 | ), 29 | ] 30 | -------------------------------------------------------------------------------- /sprout/appliances/migrations/0030_merge.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 1.9.4 on 2016-03-14 14:47 2 | 3 | 4 | from django.db import migrations 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('appliances', '0029_provider_user_groups'), 11 | ('appliances', '0029_provider_hidden'), 12 | ] 13 | 14 | operations = [ 15 | ] 16 | -------------------------------------------------------------------------------- /sprout/appliances/migrations/0031_auto_20160511_0826.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 1.9.6 on 2016-05-11 08:26 2 | 3 | 4 | from django.db import migrations, models 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('appliances', '0030_bugquery'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AddField( 15 | model_name='appliance', 16 | name='ssh_failed', 17 | field=models.BooleanField( 18 | default=False, help_text=b'If last swap check failed on SSH.'), 19 | ), 20 | migrations.AddField( 21 | model_name='appliance', 22 | name='swap', 23 | field=models.IntegerField( 24 | blank=True, help_text=b'How many MB is the appliance in swap.', null=True), 25 | ), 26 | ] 27 | -------------------------------------------------------------------------------- /sprout/appliances/migrations/0032_merge.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 1.9.6 on 2016-05-10 09:46 2 | 3 | 4 | from django.db import migrations 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('appliances', '0030_bugquery'), 11 | ('appliances', '0031_auto_20160506_0848'), 12 | ] 13 | 14 | operations = [ 15 | ] 16 | -------------------------------------------------------------------------------- /sprout/appliances/migrations/0033_merge.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 1.9.6 on 2016-05-12 14:38 2 | 3 | 4 | from django.db import migrations 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('appliances', '0031_auto_20160511_0826'), 11 | ('appliances', '0032_merge'), 12 | ] 13 | 14 | operations = [ 15 | ] 16 | -------------------------------------------------------------------------------- /sprout/appliances/migrations/0034_provider_allow_renaming.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 1.9.6 on 2016-05-12 14:40 2 | 3 | 4 | from django.db import migrations, models 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('appliances', '0033_merge'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AddField( 15 | model_name='provider', 16 | name='allow_renaming', 17 | field=models.BooleanField( 18 | default=False, help_text=b'Whether this provider can rename appliances.'), 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /sprout/appliances/migrations/0036_template_ga_released.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 1.9.10 on 2016-10-07 17:03 2 | 3 | 4 | from django.db import migrations, models 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('appliances', '0035_auto_20160922_1635'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AddField( 15 | model_name='template', 16 | name='ga_released', 17 | field=models.BooleanField(default=False), 18 | ), 19 | ] 20 | -------------------------------------------------------------------------------- /sprout/appliances/migrations/0038_auto_20170131_1512.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 1.9.12 on 2017-01-31 16:12 2 | 3 | 4 | from django.db import migrations 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('appliances', '0037_auto_20170131_1058'), 11 | ] 12 | 13 | operations = [ 14 | ] 15 | -------------------------------------------------------------------------------- /sprout/appliances/migrations/0039_auto_20170131_1512.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 1.9.12 on 2017-01-31 16:12 2 | 3 | 4 | from django.db import migrations 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('appliances', '0038_auto_20170131_1512'), 11 | ] 12 | 13 | operations = [ 14 | ] 15 | -------------------------------------------------------------------------------- /sprout/appliances/migrations/0040_provider_memory_limit.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 1.9.12 on 2017-01-31 16:12 2 | 3 | 4 | from django.db import migrations 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('appliances', '0039_auto_20170131_1512'), 11 | ] 12 | 13 | operations = [ 14 | ] 15 | -------------------------------------------------------------------------------- /sprout/appliances/migrations/0041_auto_20170131_1518.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 1.9.12 on 2017-01-31 16:12 2 | 3 | 4 | from django.db import migrations 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('appliances', '0040_provider_memory_limit'), 11 | ] 12 | 13 | operations = [ 14 | ] 15 | -------------------------------------------------------------------------------- /sprout/appliances/migrations/0042_auto_20170131_1526.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 1.9.12 on 2017-01-31 16:12 2 | 3 | 4 | from django.db import migrations 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('appliances', '0041_auto_20170131_1518'), 11 | ] 12 | 13 | operations = [ 14 | ] 15 | -------------------------------------------------------------------------------- /sprout/appliances/migrations/0043_auto_20170131_1609.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 1.9.12 on 2017-01-31 16:12 2 | 3 | 4 | from django.db import migrations 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('appliances', '0042_auto_20170131_1526'), 11 | ] 12 | 13 | operations = [ 14 | ] 15 | -------------------------------------------------------------------------------- /sprout/appliances/migrations/0047_auto_20180216_1634.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 1.9.13 on 2018-02-16 16:34 2 | 3 | 4 | from django.db import migrations, models 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('appliances', '0046_auto_20180201_1342'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AlterField( 15 | model_name='appliancepool', 16 | name='provider_type', 17 | field=models.CharField(blank=True, max_length=32, null=True), 18 | ), 19 | ] 20 | -------------------------------------------------------------------------------- /sprout/appliances/migrations/0048_openshift_appliances_support.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 1.9.13 on 2018-02-19 12:23 2 | 3 | 4 | from django.db import migrations, models 5 | from django.contrib.postgres.fields import JSONField 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | ('appliances', '0047_auto_20180216_1634'), 12 | ] 13 | 14 | operations = [ 15 | migrations.AddField( 16 | model_name='appliance', 17 | name='openshift_ext_ip', 18 | field=models.CharField(help_text=b"Openshift's project external ip", max_length=45, 19 | null=True), 20 | ), 21 | migrations.AddField( 22 | model_name='appliance', 23 | name='openshift_project', 24 | field=models.CharField(help_text=b"Openshift's project name", max_length=45, null=True), 25 | ), 26 | migrations.AddField( 27 | model_name='template', 28 | name='custom_data', 29 | field=JSONField(default={}, help_text=b'Some Templates ' 30 | b'require additional data ' 31 | b'for deployment'), 32 | ), 33 | ] 34 | -------------------------------------------------------------------------------- /sprout/appliances/migrations/0052_remove_appliancepool_is_container.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 1.9.13 on 2018-03-05 21:54 2 | 3 | 4 | from django.db import migrations 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('appliances', '0051_appliancepool_template_type'), 11 | ] 12 | 13 | operations = [ 14 | migrations.RemoveField( 15 | model_name='appliancepool', 16 | name='is_container', 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /sprout/appliances/migrations/0053_ipaddress_made_bigger.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 1.9.13 on 2018-03-06 17:34 2 | 3 | 4 | from django.db import migrations, models 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('appliances', '0052_remove_appliancepool_is_container'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AlterField( 15 | model_name='appliance', 16 | name='ip_address', 17 | field=models.CharField(help_text=b"Appliance's IP address", max_length=64, null=True), 18 | ), 19 | migrations.AlterField( 20 | model_name='appliance', 21 | name='openshift_ext_ip', 22 | field=models.CharField(help_text=b"Openshift's project external ip", max_length=64, 23 | null=True), 24 | ), 25 | ] 26 | -------------------------------------------------------------------------------- /sprout/appliances/migrations/0054_openshift_project_made_bigger.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 1.9.13 on 2018-03-07 10:19 2 | 3 | 4 | from django.db import migrations, models 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('appliances', '0053_ipaddress_made_bigger'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AlterField( 15 | model_name='appliance', 16 | name='openshift_project', 17 | field=models.CharField(help_text=b"Openshift's project name", max_length=64, null=True), 18 | ), 19 | ] 20 | -------------------------------------------------------------------------------- /sprout/appliances/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/sprout/appliances/migrations/__init__.py -------------------------------------------------------------------------------- /sprout/appliances/static/css: -------------------------------------------------------------------------------- 1 | ../../../data/templates/dist/css -------------------------------------------------------------------------------- /sprout/appliances/static/custom.css: -------------------------------------------------------------------------------- 1 | tr:target > td { 2 | font-style: italic; 3 | font-weight: bold; 4 | color: red; 5 | } 6 | 7 | [ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak { 8 | display: none !important; 9 | } 10 | 11 | h4 > a { 12 | color: white; 13 | } 14 | -------------------------------------------------------------------------------- /sprout/appliances/static/fonts: -------------------------------------------------------------------------------- 1 | ../../../data/templates/dist/fonts -------------------------------------------------------------------------------- /sprout/appliances/static/img: -------------------------------------------------------------------------------- 1 | ../../../data/templates/dist/img -------------------------------------------------------------------------------- /sprout/appliances/static/js: -------------------------------------------------------------------------------- 1 | ../../../data/templates/dist/js -------------------------------------------------------------------------------- /sprout/appliances/templates/appliances/_dates.html: -------------------------------------------------------------------------------- 1 | 2 | {% for date in dates %} 3 | 4 | {% endfor %} -------------------------------------------------------------------------------- /sprout/appliances/templates/appliances/_providers.html: -------------------------------------------------------------------------------- 1 | {% if render_providers %} 2 | 3 | {% for key, provider in render_providers.items %} 4 | 5 | {% endfor %} 6 | {% else %} 7 | 8 | {% endif %} -------------------------------------------------------------------------------- /sprout/appliances/templates/appliances/_versions.html: -------------------------------------------------------------------------------- 1 | 2 | {% for version, ga in versions %} 3 | 4 | {% endfor %} -------------------------------------------------------------------------------- /sprout/appliances/templates/appliances/provider_usage.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block title %}Provider usage{% endblock %} 3 | {% block body %} 4 |
5 |
6 | Complete usage statistics 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | {% for user, count in complete_usage %} 19 | 20 | 25 | 26 | 27 | {% endfor %} 28 | 29 |
User nameNumber of appliances
Total Assigned Appliance Count{{ total_usage }}
21 | {% if user.is_a_bot %}{% endif %} 22 | {% if request.user.is_superuser %}{{ user|user_repr }}{% else %}{{ user|user_repr }}{% endif %} 23 | {% if user.is_a_bot %}{% endif %} 24 | {{ count }}
30 |
31 | {% endblock %} -------------------------------------------------------------------------------- /sprout/appliances/templates/appliances/vms/_buttons.html: -------------------------------------------------------------------------------- 1 |
2 | {% if can_power_on %} 3 | 4 | {% endif %} 5 | {% if can_suspend %} 6 | 7 | {% endif %} 8 | {% if can_power_off %} 9 | 10 | {% endif %} 11 | {% if can_delete %} 12 | 13 | {% endif %} 14 |
-------------------------------------------------------------------------------- /sprout/appliances/templates/bugs/bugs_base.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block title %}Bugs{% endblock %} 3 | {% block body %} 4 | 10 | {% block bugs_body %}{% endblock %} 11 | {% endblock %} -------------------------------------------------------------------------------- /sprout/appliances/templates/login.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block body %} 4 | 5 | {% if form.errors %} 6 |
7 | 8 | Your username and password didn't match. Please try again 9 |
10 | {% endif %} 11 | 12 | 23 | 24 | {% endblock %} -------------------------------------------------------------------------------- /sprout/appliances/templatetags/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ManageIQ/integration_tests/5c9fea2b256a283700e664b31f586b2681d139b3/sprout/appliances/templatetags/__init__.py -------------------------------------------------------------------------------- /sprout/appliances/tests.py: -------------------------------------------------------------------------------- 1 | # from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /sprout/celery_runner: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import re 4 | import sys 5 | 6 | import os 7 | os.environ["RUNNING_UNDER_SPROUT"] = "true" # To prevent importing unnecessary UI stuff 8 | 9 | from celery.__main__ import main 10 | 11 | if __name__ == '__main__': 12 | sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) 13 | try: 14 | sys.exit(main()) 15 | finally: 16 | del os.environ["RUNNING_UNDER_SPROUT"] 17 | -------------------------------------------------------------------------------- /sprout/manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import os 3 | import sys 4 | 5 | if __name__ == "__main__": 6 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "sprout.settings") 7 | 8 | from django.core.management import execute_from_command_line 9 | 10 | execute_from_command_line(sys.argv) 11 | -------------------------------------------------------------------------------- /sprout/requirements.txt: -------------------------------------------------------------------------------- 1 | Command 2 | celery[redis]==4.3.0 3 | Django==2.2.5 4 | diaper 5 | django-object-actions 6 | django-ipware==2.1.0 #ipware.ip.get_ip removed in 3.0 7 | flower 8 | gunicorn 9 | kombu==4.5.0 10 | pika 11 | python-memcached 12 | redis==3.3.8 13 | miq-version==0.4.0 14 | yaycl 15 | werkzeug 16 | -------------------------------------------------------------------------------- /sprout/sprout/celery.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | import os 4 | from celery import Celery 5 | from django.conf import settings 6 | 7 | # set the default Django settings module for the 'celery' program. 8 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'sprout.settings') 9 | 10 | app = Celery('sprout') 11 | 12 | # Using a string here means the worker will not have to 13 | # pickle the object when using Windows. 14 | app.config_from_object('django.conf:settings') 15 | app.autodiscover_tasks(lambda: settings.INSTALLED_APPS) 16 | -------------------------------------------------------------------------------- /sprout/sprout/irc_bot.py: -------------------------------------------------------------------------------- 1 | from sprout import settings 2 | 3 | import json 4 | import pika 5 | 6 | REQUIRED = {'PIKA_USER', 'PIKA_PASS', 'PIKA_HOST', 'PIKA_CHANNEL', 'PIKA_ROUTING_KEY'} 7 | 8 | 9 | def send_message(message): 10 | if not any(hasattr(settings, item) for item in REQUIRED): 11 | return 12 | 13 | url = "amqp://" + settings.PIKA_USER + ":" + settings.PIKA_PASS + "@" + settings.PIKA_HOST 14 | params = pika.URLParameters(url) 15 | params.socket_timeout = 5 16 | 17 | try: 18 | connection = pika.BlockingConnection(params) # Connect to CloudAMQP 19 | channel = connection.channel() 20 | 21 | message = json.dumps({'channel': settings.PIKA_CHANNEL, 'body': message}) 22 | 23 | channel.basic_publish(exchange='', 24 | routing_key=settings.PIKA_ROUTING_KEY, 25 | body=message) 26 | connection.close() 27 | except Exception: 28 | # Don't bother if we cannot connect 29 | pass 30 | -------------------------------------------------------------------------------- /sprout/sprout/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import include, re_path 2 | from django.contrib import admin 3 | from django.views.generic.base import RedirectView 4 | 5 | 6 | urlpatterns = [ 7 | # Examples: 8 | re_path(r'^$', RedirectView.as_view(url="appliances/", permanent=False), 9 | name='home'), 10 | # url(r'^blog/', include('blog.urls')), 11 | re_path(r'^appliances/', include('appliances.urls')), 12 | re_path(r'^admin/', admin.site.urls), 13 | ] 14 | -------------------------------------------------------------------------------- /sprout/sprout/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for sprout project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/1.7/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "sprout.settings") 12 | 13 | from django.core.wsgi import get_wsgi_application 14 | application = get_wsgi_application() 15 | --------------------------------------------------------------------------------