Source code for cfme.base.ui

from __future__ import absolute_import
import time
from selenium.webdriver.common.keys import Keys

import re
from navmazing import NavigateToSibling, NavigateToAttribute

from widgetastic_manageiq import (ManageIQTree, Checkbox, AttributeValueForm, SummaryFormItem,
                                  TimelinesView)
from widgetastic_patternfly import (Accordion, Input, Button, Dropdown,
    FlashMessages, BootstrapSelect, Tab)
from widgetastic.utils import Version, VersionPick
from widgetastic.widget import View, Table, Text, Image, FileInput


from cfme.base.login import BaseLoggedInPage
from cfme.base.credential import Credential
from cfme.configure.about import AboutView
from cfme.configure.documentation import DocView
from cfme.configure.tasks import TasksView
from cfme.dashboard import DashboardView
from cfme.intelligence.rss import RSSView
from cfme.exceptions import ZoneNotFound, DestinationNotFound
from cfme.intelligence.chargeback import ChargebackView

from cfme.utils.appliance.implementations.ui import navigator, CFMENavigateStep, ViaUI, navigate_to
from . import Server, Region, Zone, ZoneCollection

from cfme.utils import conf
from cfme.utils.log import logger


@Server.address.external_implementation_for(ViaUI)
[docs]def address(self): logger.info("USING UI ADDRESS") return 'https://{}/'.format(self.appliance.address)
[docs]class LoginPage(View): flash = FlashMessages( VersionPick({ Version.lowest(): 'div#flash_text_div', '5.8': '//div[@class="flash_text_div"]' }) ) class details(View): # noqa region = Text('.//p[normalize-space(text())="Region:"]/span') zone = Text('.//p[normalize-space(text())="Zone:"]/span') appliance = Text('.//p[normalize-space(text())="Appliance:"]/span') change_password = Text('.//a[normalize-space(.)="Update password"]') back = Text('.//a[normalize-space(.)="Back"]') username = Input(name='user_name') password = Input(name='user_password') new_password = Input(name='user_new_password') verify_password = Input(name='user_verify_password') login = Button('Login')
[docs] def show_update_password(self): if not self.new_password.is_displayed: self.change_password.click()
[docs] def hide_update_password(self): if self.new_password.is_displayed: self.back.click()
[docs] def login_admin(self, **kwargs): username = conf.credentials['default']['username'] password = conf.credentials['default']['password'] cred = Credential(principal=username, secret=password) from cfme.configure.access_control import User user = User(credential=cred, name='Administrator') return self.log_in(user, **kwargs)
[docs] def submit_login(self, method='click_on_login'): if method == 'click_on_login': self.login.click() elif method == 'press_enter_after_password': self.browser.send_keys(Keys.ENTER, self.password) elif method == '_js_auth_fn': self.browser.execute_script('miqAjaxAuth();') else: raise ValueError('Unknown method {}'.format(method)) if self.flash.is_displayed: self.flash.assert_no_error()
[docs] def log_in(self, user, method='click_on_login'): self.fill({ 'username': user.credential.principal, 'password': user.credential.secret, }) self.submit_login(method) logged_in_view = self.browser.create_view(BaseLoggedInPage) if logged_in_view.logged_in: if user.name is None: name = logged_in_view.current_fullname self.logger.info( 'setting the appliance.user.name to %r because it was not specified', name) user.name = name self.extra.appliance.user = user
[docs] def update_password( self, username, password, new_password, verify_password=None, method='click_on_login'): self.show_update_password() self.fill({ 'username': username, 'password': password, 'new_password': new_password, 'verify_password': verify_password if verify_password is not None else new_password }) self.submit_login(method)
[docs] def logged_in_as_user(self, user): return False
@property def logged_in_as_current_user(self): return False @property def current_username(self): return None @property def current_fullname(self): return None @property def logged_in(self): return not self.logged_out @property def logged_out(self): return self.username.is_displayed and self.password.is_displayed and self.login.is_displayed @property def is_displayed(self): return self.logged_out
@Server.logged_in.external_implementation_for(ViaUI)
[docs]def logged_in(self): return self.appliance.browser.create_view(BaseLoggedInPage).logged_in
LOGIN_METHODS = ['click_on_login', 'press_enter_after_password', '_js_auth_fn'] @Server.login.external_implementation_for(ViaUI)
[docs]def login(self, user=None, method=LOGIN_METHODS[-1]): """ Login to CFME with the given username and password. Optionally, submit_method can be press_enter_after_password to use the enter key to login, rather than clicking the button. Args: user: The username to fill in the username field. password: The password to fill in the password field. submit_method: A function to call after the username and password have been input. Raises: RuntimeError: If the login fails, ie. if a flash message appears """ # Circular import if not user: username = conf.credentials['default']['username'] password = conf.credentials['default']['password'] cred = Credential(principal=username, secret=password) from cfme.configure.access_control import User user = User(credential=cred, name='Administrator') logged_in_view = self.appliance.browser.create_view(BaseLoggedInPage) if not logged_in_view.logged_in_as_user(user): if logged_in_view.logged_in: logged_in_view.logout() from cfme.utils.appliance.implementations.ui import navigate_to login_view = navigate_to(self.appliance.server, 'LoginScreen') time.sleep(1) logger.debug('Logging in as user %s', user.credential.principal) login_view.flush_widget_cache() login_view.log_in(user, method=method) logged_in_view.flush_widget_cache() user.name = logged_in_view.current_fullname try: assert logged_in_view.is_displayed assert logged_in_view.logged_in_as_user self.appliance.user = user except AssertionError: login_view.flash.assert_no_error() return logged_in_view
@Server.login_admin.external_implementation_for(ViaUI)
[docs]def login_admin(self, **kwargs): """ Convenience function to log into CFME using the admin credentials from the yamls. Args: kwargs: A dict of keyword arguments to supply to the :py:meth:`login` method. """ username = conf.credentials['default']['username'] password = conf.credentials['default']['password'] cred = Credential(principal=username, secret=password) from cfme.configure.access_control import User user = User(credential=cred) user.name = 'Administrator' logged_in_page = self.login(user, **kwargs) return logged_in_page
@Server.logout.external_implementation_for(ViaUI)
[docs]def logout(self): """ Logs out of CFME. """ logged_in_view = self.appliance.browser.create_view(BaseLoggedInPage) if logged_in_view.logged_in: logged_in_view.logout() self.appliance.user = None
@Server.current_full_name.external_implementation_for(ViaUI)
[docs]def current_full_name(self): """ Returns the current username. Returns: the current username. """ logged_in_view = self.appliance.browser.create_view(BaseLoggedInPage) if logged_in_view.logged_in: return logged_in_view.current_fullname else: return None
[docs]def automate_menu_name(appliance): if appliance.version < '5.8': return ['Automate'] else: return ['Automation', 'Automate']
# ######################## SERVER NAVS ################################ @navigator.register(Server)
[docs]class LoginScreen(CFMENavigateStep): VIEW = LoginPage
[docs] def prerequisite(self): from cfme.utils.browser import ensure_browser_open ensure_browser_open(self.obj.appliance.server.address())
[docs] def step(self): # Can be either blank or logged in from cfme.utils import browser logged_in_view = self.create_view(BaseLoggedInPage) if logged_in_view.logged_in: logged_in_view.logout() if not self.view.is_displayed: # Something is wrong del self.view # In order to unbind the browser browser.quit() browser.ensure_browser_open(self.obj.appliance.server.address()) if not self.view.is_displayed: raise Exception('Could not open the login screen')
@navigator.register(Server)
[docs]class LoggedIn(CFMENavigateStep): VIEW = BaseLoggedInPage prerequisite = NavigateToSibling('LoginScreen')
[docs] def step(self): user = self.obj.appliance.user self.prerequisite_view.log_in(user)
[docs]class ConfigurationView(BaseLoggedInPage): flash = FlashMessages( './/div[starts-with(@id, "flash_text_div") or starts-with(@class, "flash_text_div")]') title = Text('#explorer_title_text') @View.nested class accordions(View): # noqa @View.nested class settings(Accordion): # noqa ACCORDION_NAME = "Settings" INDIRECT = True tree = ManageIQTree() @View.nested class accesscontrol(Accordion): # noqa ACCORDION_NAME = "Access Control" tree = ManageIQTree() @View.nested class diagnostics(Accordion): # noqa ACCORDION_NAME = "Diagnostics" tree = ManageIQTree() @View.nested class database(Accordion): # noqa ACCORDION_NAME = "Database" tree = ManageIQTree() @property def in_configuration(self): return ( self.accordions.settings.is_displayed and self.accordions.accesscontrol.is_displayed and self.accordions.diagnostics.is_displayed and self.accordions.database.is_displayed) @property def is_displayed(self): # TODO: We will need a better ID of this location when we have user permissions in effect return self.in_configuration
@navigator.register(Server)
[docs]class Configuration(CFMENavigateStep): VIEW = ConfigurationView prerequisite = NavigateToSibling('LoggedIn')
[docs] def step(self): if self.obj.appliance.version > '5.7': self.prerequisite_view.settings.select_item('Configuration') self.prerequisite_view.browser.handle_alert(wait=2, cancel=False, squash=True) else: self.prerequisite_view.navigation.select('Settings', 'Configuration')
[docs]class MySettingsView(BaseLoggedInPage): @View.nested class tabs(View): # noqa @View.nested class visual_all(Tab): # noqa TAB_NAME = "Visual" @View.nested class default_views(Tab): # noqa TAB_NAME = "Default Views" @View.nested class default_filter(Tab): # noqa TAB_NAME = "Default Filters" @View.nested class time_profile(Tab): # noqa TAB_NAME = "Time Profiles" @property def is_displayed(self): return ( self.tabs.visual_all.is_displayed and self.tabs.default_views.is_displayed and self.tabs.default_filter.is_displayed and self.time_profile.is_displayed)
@navigator.register(Server)
[docs]class MySettings(CFMENavigateStep): prerequisite = NavigateToSibling('LoggedIn')
[docs] def step(self): if self.obj.appliance.version > '5.7': self.prerequisite_view.settings.select_item('My Settings') else: self.prerequisite_view.navigation.select('Settings', 'My Settings')
@navigator.register(Server)
[docs]class About(CFMENavigateStep): VIEW = AboutView prerequisite = NavigateToSibling('LoggedIn')
[docs] def step(self): self.prerequisite_view.help.select_item('About')
@navigator.register(Server)
[docs]class RSS(CFMENavigateStep): VIEW = RSSView prerequisite = NavigateToSibling('LoggedIn')
[docs] def step(self): self.view.navigation.select('Cloud Intel', 'RSS')
@navigator.register(Server)
[docs]class Documentation(CFMENavigateStep): VIEW = DocView prerequisite = NavigateToSibling('LoggedIn')
[docs] def step(self): self.prerequisite_view.help.select_item('Documentation')
@navigator.register(Server)
[docs]class Tasks(CFMENavigateStep): VIEW = TasksView prerequisite = NavigateToSibling('LoggedIn')
[docs] def step(self): if self.obj.appliance.version > '5.7': self.prerequisite_view.settings.select_item('Tasks') else: self.prerequisite_view.navigation.select('Settings', 'Tasks')
@navigator.register(Server)
[docs]class Dashboard(CFMENavigateStep): VIEW = DashboardView prerequisite = NavigateToSibling('LoggedIn')
[docs] def step(self): self.prerequisite_view.navigation.select('Cloud Intel', 'Dashboard')
@navigator.register(Server)
[docs]class Chargeback(CFMENavigateStep): VIEW = ChargebackView prerequisite = NavigateToSibling('LoggedIn')
[docs] def step(self, *args, **kwargs): self.prerequisite_view.navigation.select('Cloud Intel', 'Chargeback')
[docs]class ServerView(ConfigurationView): @View.nested class server(Tab): # noqa TAB_NAME = "Server" @View.nested class authentication(Tab): # noqa TAB_NAME = "Authentication" @View.nested class workers(Tab): # noqa TAB_NAME = "Workers" generic_worker_count = BootstrapSelect("generic_worker_count") generic_worker_threshold = BootstrapSelect("generic_worker_threshold") cu_data_collector_worker_count = BootstrapSelect("ems_metrics_collector_worker_count") cu_data_collector_worker_threshold = BootstrapSelect( "ems_metrics_collector_worker_threshold") event_monitor_worker_threshold = BootstrapSelect("event_catcher_threshold") connection_broker_worker_threshold = BootstrapSelect("vim_broker_worker_threshold") ui_worker_count = BootstrapSelect("ui_worker_count") reporting_worker_count = BootstrapSelect("reporting_worker_count") reporting_worker_threshold = BootstrapSelect("reporting_worker_threshold") web_service_worker_count = BootstrapSelect("web_service_worker_count") web_service_worker_threshold = BootstrapSelect("web_service_worker_threshold") priority_worker_count = BootstrapSelect("priority_worker_count") priority_worker_threshold = BootstrapSelect("priority_worker_threshold") cu_data_processor_worker_count = BootstrapSelect("ems_metrics_processor_worker_count") cu_data_processor_worker_threshold = BootstrapSelect( "ems_metrics_processor_worker_threshold") refresh_worker_threshold = BootstrapSelect("ems_refresh_worker_threshold") vm_analysis_collectors_worker_count = BootstrapSelect("proxy_worker_count") vm_analysis_collectors_worker_threshold = BootstrapSelect("proxy_worker_threshold") websocket_worker_count = BootstrapSelect("websocket_worker_count") save = Button('Save') reset = Button('Reset') @View.nested class customlogos(Tab): # noqa TAB_NAME = "Custom Logos" @View.nested class advanced(Tab): # noqa TAB_NAME = "Advanced" @property def is_displayed(self): if not self.in_configuration: return False if not self.view.accordions.settings.is_displayed: return False return self.view.accordions.settings.tree.currently_selected == [ self.context['object'].zone.region.settings_string, "Zones", "Zone: {} (current)".format(self.context['object'].zone.description), "Server: {} [{}] (current)".format(self.context['object'].name, self.context['object'].sid)]
@navigator.register(Server)
[docs]class Details(CFMENavigateStep): VIEW = ServerView prerequisite = NavigateToSibling('Configuration')
[docs] def step(self): self.prerequisite_view.accordions.settings.tree.click_path( self.obj.zone.region.settings_string, "Zones", "Zone: {} (current)".format(self.obj.appliance.zone_description), "Server: {} [{}] (current)".format(self.obj.appliance.server_name(), self.obj.sid))
@navigator.register(Server, 'Server')
[docs]class ServerDetails(CFMENavigateStep): VIEW = ServerView prerequisite = NavigateToSibling('Details')
[docs] def am_i_here(self): return ( self.view.is_displayed and self.view.server.is_displayed and self.view.server.is_active)
[docs] def step(self): self.prerequisite_view.server.select()
@navigator.register(Server)
[docs]class Authentication(CFMENavigateStep): VIEW = ServerView prerequisite = NavigateToSibling('Details')
[docs] def am_i_here(self): return ( self.view.is_displayed and self.view.authentication.is_displayed and self.view.authentication.is_active)
[docs] def step(self): self.prerequisite_view.authentication.select()
@navigator.register(Server)
[docs]class Workers(CFMENavigateStep): VIEW = ServerView prerequisite = NavigateToSibling('Details')
[docs] def am_i_here(self): return ( self.view.is_displayed and self.view.workers.is_displayed and self.view.workers.is_active)
[docs] def step(self): self.prerequisite_view.workers.select()
@navigator.register(Server)
[docs]class CustomLogos(CFMENavigateStep): VIEW = ServerView prerequisite = NavigateToSibling('Details')
[docs] def am_i_here(self): return ( self.view.is_displayed and self.view.custom_logos.is_displayed and self.view.custom_logos.is_active)
[docs] def step(self): self.prerequisite_view.customlogos.select()
@navigator.register(Server)
[docs]class Advanced(CFMENavigateStep): VIEW = ServerView prerequisite = NavigateToSibling('Details')
[docs] def am_i_here(self): return ( self.view.is_displayed and self.view.advanced.is_displayed and self.view.advanced.is_active)
[docs] def step(self): self.prerequisite_view.advanced.select()
[docs]class ServerDiagnosticsView(ConfigurationView): @View.nested class summary(Tab): # noqa TAB_NAME = "Summary" @View.nested class workers(Tab): # noqa TAB_NAME = "Workers" @View.nested class collectlogs(Tab): # noqa TAB_NAME = "Collect Logs" @View.nested class cfmelog(Tab): # noqa TAB_NAME = "CFME Log" @View.nested class auditlog(Tab): # noqa TAB_NAME = "Audit Log" @View.nested class productionlog(Tab): # noqa TAB_NAME = "Production Log" @View.nested class utilization(Tab): # noqa TAB_NAME = "Utilization" @View.nested class timelines(Tab, TimelinesView): # noqa TAB_NAME = "Timelines" configuration = Dropdown('Configuration') @property def is_displayed(self): return self.prerequisite_view.accordions.diagnostics.tree.currently_selected == [ self.context['object'].zone.region.settings_string, "Zone: {} (current)".format(self.context['object'].zone.description), "Server: {} [{}] (current)".format( self.context['object'].name, self.context['object'].sid)]
@navigator.register(Server)
[docs]class Diagnostics(CFMENavigateStep): VIEW = ServerDiagnosticsView prerequisite = NavigateToSibling('Configuration')
[docs] def step(self): self.prerequisite_view.accordions.diagnostics.tree.click_path( self.obj.zone.region.settings_string, "Zone: {} (current)".format(self.obj.zone.description), "Server: {} [{}] (current)".format( self.obj.name, self.obj.sid))
@navigator.register(Server)
[docs]class DiagnosticsDetails(CFMENavigateStep): VIEW = ServerDiagnosticsView prerequisite = NavigateToSibling('Diagnostics')
[docs] def am_i_here(self): return ( self.view.is_displayed and self.view.summary.is_displayed and self.view.summary.is_active)
[docs] def step(self): self.prerequisite_view.summary.select()
@navigator.register(Server)
[docs]class DiagnosticsWorkers(CFMENavigateStep): VIEW = ServerDiagnosticsView prerequisite = NavigateToSibling('Diagnostics')
[docs] def am_i_here(self): return ( self.view.is_displayed and self.view.workers.is_displayed and self.view.workers.is_active)
[docs] def step(self): self.prerequisite_view.workers.select()
[docs]class DiagnosticsCollectLogsView(ServerDiagnosticsView): title = Text('#explorer_title_text') edit = Button(title="Edit the Log Depot settings for the selected Server") collect = Dropdown(VersionPick({Version.lowest(): 'Collect Logs', '5.7': 'Collect'})) log_depot_uri = SummaryFormItem('Basic Info', 'Log Depot URI') last_log_collection = SummaryFormItem('Basic Info', 'Last Log Collection') last_log_message = SummaryFormItem('Basic Info', 'Last Message') @property def is_displayed(self): return ( super(DiagnosticsCollectLogsView, self).is_displayed and self.collectlogs.is_displayed and self.collectlogs.is_active and self.title.text == 'Diagnostics Server "{} [{}]" (current)'.format( self.context['object'].name, self.context['object'].sid))
[docs]class ZoneDiagnosticsCollectLogsView(DiagnosticsCollectLogsView): edit = Button(title="Edit the Log Depot settings for the selected Zone") @property def is_displayed(self): return ( self.collectlogs.is_displayed and self.collectlogs.is_active and self.title.text == 'Diagnostics Zone "{}" (current)'.format( self.context['object'].description))
@navigator.register(Server, "DiagnosticsCollectLogs")
[docs]class DiagnosticsCollectLogs(CFMENavigateStep): VIEW = DiagnosticsCollectLogsView prerequisite = NavigateToSibling('Diagnostics')
[docs] def step(self): self.prerequisite_view.collectlogs.select()
@navigator.register(Server, "DiagnosticsCollectLogsSlave")
[docs]class DiagnosticsCollectLogsSlave(CFMENavigateStep): VIEW = DiagnosticsCollectLogsView prerequisite = NavigateToSibling('Diagnostics')
[docs] def step(self): self.prerequisite_view.accordions.diagnostics.tree.click_path( self.appliance.server_region_string(), "Zone: {} (current)".format(self.appliance.zone_description), "Server: {} [{}]".format(self.appliance.slave_server_name(), self.appliance.slave_server_zone_id())) self.prerequisite_view.collectlogs.select()
[docs]class DiagnosticsCollectLogsEditView(DiagnosticsCollectLogsView): @property def is_displayed(self): return super(DiagnosticsCollectLogsView, self).is_displayed and self.protocol.is_displayed depot_type = BootstrapSelect('log_protocol') depot_name = Input('depot_name') uri = Input('uri') username = Input(name='log_userid') password = Input(name='log_password') confirm_password = Input(name='log_verify') validate = Button('Validate') save = Button('Save') reset = Button('Reset') cancel = Button('Cancel')
@navigator.register(Server, "DiagnosticsCollectLogsEdit")
[docs]class DiagnosticsCollectLogsEdit(CFMENavigateStep): VIEW = DiagnosticsCollectLogsEditView prerequisite = NavigateToSibling('DiagnosticsCollectLogs')
[docs] def step(self): self.prerequisite_view.edit.click()
@navigator.register(Server, "DiagnosticsCollectLogsEditSlave")
[docs]class DiagnosticsCollectLogsEditSlave(CFMENavigateStep): VIEW = DiagnosticsCollectLogsEditView prerequisite = NavigateToSibling('DiagnosticsCollectLogsSlave')
[docs] def step(self): self.prerequisite_view.edit.click()
@navigator.register(Server)
[docs]class CFMELog(CFMENavigateStep): VIEW = ServerDiagnosticsView prerequisite = NavigateToSibling('Diagnostics')
[docs] def am_i_here(self): return ( self.view.is_displayed and self.view.cfmelog.is_displayed and self.view.cfmelog.is_active)
[docs] def step(self): self.prerequisite_view.cfmelog.select()
@navigator.register(Server)
[docs]class AuditLog(CFMENavigateStep): VIEW = ServerDiagnosticsView prerequisite = NavigateToSibling('Diagnostics')
[docs] def am_i_here(self): return ( self.view.is_displayed and self.view.auditlog.is_displayed and self.view.auditlog.is_active)
[docs] def step(self): self.prerequisite_view.auditlog.select()
@navigator.register(Server)
[docs]class ProductionLog(CFMENavigateStep): VIEW = ServerDiagnosticsView prerequisite = NavigateToSibling('Diagnostics')
[docs] def am_i_here(self): return ( self.view.is_displayed and self.view.productionlog.is_displayed and self.view.productionlog.is_active)
[docs] def step(self): self.prerequisite_view.productionlog.select()
@navigator.register(Server)
[docs]class Utilization(CFMENavigateStep): VIEW = ServerDiagnosticsView prerequisite = NavigateToSibling('Diagnostics')
[docs] def am_i_here(self): return ( self.view.is_displayed and self.view.utilization.is_displayed and self.view.utilization.is_active)
[docs] def step(self): self.prerequisite_view.utilization.select()
@navigator.register(Server)
[docs]class Timelines(CFMENavigateStep): VIEW = ServerDiagnosticsView prerequisite = NavigateToSibling('Diagnostics')
[docs] def am_i_here(self): return ( self.view.is_displayed and self.view.timelines.is_displayed and self.view.timelines.is_active)
[docs] def step(self): self.prerequisite_view.timelines.select()
# ######################## REGION NAVS ################################
[docs]class RegionView(ConfigurationView): @View.nested class details(Tab): # noqa TAB_NAME = "Details" @View.nested class canducollection(Tab): # noqa TAB_NAME = "C & U Collection" @View.nested class companycategories(Tab): # noqa TAB_NAME = "My Company Categories" @View.nested class companytags(Tab): # noqa TAB_NAME = "My Company Tags" @View.nested class redhatupdates(Tab): # noqa TAB_NAME = "Red Hat Updates" @View.nested class imports(Tab): # noqa TAB_NAME = "Import" @View.nested class importtags(Tab): # noqa TAB_NAME = "Import Tags" @View.nested class maptags(Tab): # noqa TAB_NAME = "Map Tags" @View.nested class replication(Tab): # noqa TAB_NAME = "Replication" @property def is_displayed(self): return self.accordions.settings.tree.currently_selected == [self.obj.settings_string]
@navigator.register(Region, 'Details')
[docs]class RegionDetails(CFMENavigateStep): VIEW = RegionView prerequisite = NavigateToAttribute('appliance.server', 'Configuration')
[docs] def step(self): # TODO: This string can now probably be built up with the relevant server, zone, # region objects self.prerequisite_view.accordions.settings.tree.click_path(self.obj.settings_string) self.view.details.select()
@navigator.register(Region)
[docs]class ImportTags(CFMENavigateStep): VIEW = RegionView prerequisite = NavigateToSibling('Details')
[docs] def am_i_here(self): return False
[docs] def step(self): self.prerequisite_view.importtags.select()
@navigator.register(Region)
[docs]class Import(CFMENavigateStep): VIEW = RegionView prerequisite = NavigateToSibling('Details')
[docs] def am_i_here(self): return False
[docs] def step(self): self.prerequisite_view.imports.select()
[docs]class ZoneListView(ConfigurationView): configuration = Dropdown('Configuration') table = Table('//div[@id="settings_list"]/table') @property def is_displayed(self): return ( self.accordions.settings.is_opened and self.accordions.settings.tree.currently_selected == [ self.context['object'].settings_string, 'Zones'] and self.title.text == 'Settings Zones' and self.table.is_displayed)
@navigator.register(Region, 'Zones')
[docs]class RegionZones(CFMENavigateStep): VIEW = ZoneListView prerequisite = NavigateToAttribute('appliance.server', 'Configuration')
[docs] def step(self): self.prerequisite_view.accordions.settings.tree.click_path( self.obj.settings_string, 'Zones') if not self.view.is_displayed: # Zones is too smart and does not reload upon clicking, this helps self.prerequisite_view.accordions.accesscontrol.open() self.prerequisite_view.accordions.settings.tree.click_path( self.obj.settings_string, 'Zones')
[docs]class RegionDiagnosticsView(ConfigurationView): @View.nested class zones(Tab): # noqa TAB_NAME = "Zones" @View.nested class rolesbyservers(Tab): # noqa TAB_NAME = "Roles by Servers" @View.nested class replication(Tab): # noqa TAB_NAME = "Replication" @View.nested class serversbyroles(Tab): # noqa TAB_NAME = "Servers by Roles" @View.nested class servers(Tab): # noqa TAB_NAME = "Servers" @View.nested class database(Tab): # noqa TAB_NAME = "Database" @View.nested class orphaneddata(Tab): # noqa TAB_NAME = "Orphaned Data" @property def is_displayed(self): return ( self.accordions.diagnostics.is_opened and self.accordions.diagnostics.tree.currently_selected == [ self.context['object'].settings_string] and self.title.text.startswith('Diagnostics Region '))
@navigator.register(Region, 'Diagnostics')
[docs]class RegionDiagnostics(CFMENavigateStep): VIEW = RegionDiagnosticsView prerequisite = NavigateToAttribute('appliance.server', 'Configuration')
[docs] def step(self): self.prerequisite_view.accordions.diagnostics.tree.click_path(self.obj.settings_string)
@navigator.register(Region, 'DiagnosticsZones')
[docs]class RegionDiagnosticsZones(CFMENavigateStep): VIEW = RegionDiagnosticsView prerequisite = NavigateToSibling('Diagnostics')
[docs] def am_i_here(self): return False
[docs] def step(self): self.prerequisite_view.zones.select()
@navigator.register(Region, 'RolesByServers')
[docs]class RegionDiagnosticsRolesByServers(CFMENavigateStep): VIEW = RegionDiagnosticsView prerequisite = NavigateToSibling('Diagnostics')
[docs] def am_i_here(self): return False
[docs] def step(self): self.prerequisite_view.rolesbyservers.select()
@navigator.register(Region, 'Replication')
[docs]class RegionDiagnosticsReplication(CFMENavigateStep): VIEW = RegionDiagnosticsView prerequisite = NavigateToSibling('Diagnostics')
[docs] def am_i_here(self): return False
[docs] def step(self): if self.obj.appliance.version < '5.7': self.prerequisite_view.replication.select() else: raise DestinationNotFound('Replication destination is absent in 5.7')
@navigator.register(Region, 'ServersByRoles')
[docs]class RegionDiagnosticsServersByRoles(CFMENavigateStep): VIEW = RegionDiagnosticsView prerequisite = NavigateToSibling('Diagnostics')
[docs] def am_i_here(self): return False
[docs] def step(self): self.prerequisite_view.serversbyroles.select()
@navigator.register(Region, 'Servers')
[docs]class RegionDiagnosticsServers(CFMENavigateStep): VIEW = RegionDiagnosticsView prerequisite = NavigateToSibling('Diagnostics')
[docs] def am_i_here(self): return False
[docs] def step(self): self.prerequisite_view.servers.select()
@navigator.register(Region, 'Database')
[docs]class RegionDiagnosticsDatabase(CFMENavigateStep): VIEW = RegionDiagnosticsView prerequisite = NavigateToSibling('Diagnostics')
[docs] def am_i_here(self): return False
[docs] def step(self): self.prerequisite_view.database.select()
@navigator.register(Region, 'OrphanedData')
[docs]class RegionDiagnosticsOrphanedData(CFMENavigateStep): VIEW = RegionDiagnosticsView prerequisite = NavigateToSibling('Diagnostics')
[docs] def am_i_here(self): return False
[docs] def step(self): self.prerequisite_view.orphaneddata.select()
# ################################## ZONE NAVS ##############################
[docs]class ZoneForm(ConfigurationView): name = Input(name='name') description = Input(name='description') smartproxy_ip = Input(name='proxy_server_ip') ntp_server_1 = Input(name='ntp_server_1') ntp_server_2 = Input(name='ntp_server_2') ntp_server_3 = Input(name='ntp_server_3') max_scans = BootstrapSelect("max_scans") username = Input(name='userid') password = Input(name='password') verify = Input(name='verify') cancel_button = Button('Cancel')
# Zone Details #
[docs]class ZoneDetailsView(ConfigurationView): configuration = Dropdown('Configuration') @property def is_displayed(self): return self.title.text.startswith( 'Settings Zone "{}"'.format(self.context['object'].description))
@navigator.register(Zone, 'Details')
[docs]class ZoneDetails(CFMENavigateStep): VIEW = ZoneDetailsView prerequisite = NavigateToAttribute('appliance.server.zone.region', 'Zones')
[docs] def step(self): rows = self.prerequisite_view.table.rows((1, re.compile(r'Zone\s?\:\s?{}'.format( self.obj.description)))) for row in rows: row.click() break else: raise ZoneNotFound( "No unique Zones with the description '{}'".format(self.obj.description))
# Zone Add #
[docs]class ZoneAddView(ZoneForm): add_button = Button('Add') @property def is_displayed(self): return self.title.text == 'Adding a new Zone'
@navigator.register(ZoneCollection, 'Add')
[docs]class ZoneAdd(CFMENavigateStep): VIEW = ZoneAddView prerequisite = NavigateToAttribute('appliance.server.zone.region', 'Zones')
[docs] def step(self): self.prerequisite_view.configuration.item_select("Add a new Zone")
# Zone Edit #
[docs]class ZoneEditView(ZoneForm): save_button = Button('Save') @property def is_displayed(self): return self.title.text == 'Editing Zone "{}"'.format(self.context['object'].description)
@navigator.register(Zone, 'Edit')
[docs]class ZoneEdit(CFMENavigateStep): VIEW = ZoneEditView prerequisite = NavigateToSibling('Details')
[docs] def step(self): self.prerequisite_view.configuration.item_select("Edit this Zone")
# Zone Diags #
[docs]class ZoneDiagnosticsView(ConfigurationView): @View.nested class rolesbyservers(Tab): # noqa TAB_NAME = "Roles by Servers" @View.nested class serversbyroles(Tab): # noqa TAB_NAME = "Servers by Roles" @View.nested class servers(Tab): # noqa TAB_NAME = "Servers" @View.nested class collectlogs(Tab): # noqa TAB_NAME = "Collect Logs" @View.nested class candugapcollection(Tab): # noqa TAB_NAME = "C & U Gap Collection" @property def is_displayed(self): return ( self.title.text == 'Diagnostics Zone "{}" (current)'.format( self.context['object'].description))
@navigator.register(Zone, 'Diagnostics')
[docs]class ZoneDiagnostics(CFMENavigateStep): VIEW = ZoneDiagnosticsView prerequisite = NavigateToAttribute('appliance.server', 'Configuration')
[docs] def step(self): self.prerequisite_view.accordions.diagnostics.tree.click_path( self.obj.region.settings_string, "Zone: {} (current)".format(self.obj.description))
@navigator.register(Zone, 'RolesByServers')
[docs]class ZoneDiagnosticsRolesByServers(CFMENavigateStep): VIEW = ZoneDiagnosticsView prerequisite = NavigateToSibling('Diagnostics')
[docs] def step(self): self.prerequisite_view.rolesbyservers.select()
@navigator.register(Zone, 'ServersByRoles')
[docs]class ZoneDiagnosticsServersByRoles(CFMENavigateStep): VIEW = ZoneDiagnosticsView prerequisite = NavigateToSibling('Diagnostics')
[docs] def step(self): self.prerequisite_view.serversbyroles.select()
@navigator.register(Zone, 'Servers')
[docs]class ZoneDiagnosticsServers(CFMENavigateStep): VIEW = ZoneDiagnosticsView prerequisite = NavigateToSibling('Diagnostics')
[docs] def step(self): self.prerequisite_view.servers.select()
@navigator.register(Zone, 'DiagnosticsCollectLogs')
[docs]class ZoneDiagnosticsCollectLogs(CFMENavigateStep): VIEW = ZoneDiagnosticsCollectLogsView prerequisite = NavigateToSibling('Diagnostics')
[docs] def step(self): self.prerequisite_view.collectlogs.select()
@navigator.register(Zone, 'DiagnosticsCollectLogsEdit')
[docs]class ZoneDiagnosticsCollectLogsEdit(CFMENavigateStep): VIEW = DiagnosticsCollectLogsEditView prerequisite = NavigateToSibling('DiagnosticsCollectLogs')
[docs] def step(self): self.prerequisite_view.edit.click()
@navigator.register(Zone, 'CANDUGapCollection')
[docs]class ZoneCANDUGapCollection(CFMENavigateStep): VIEW = ZoneDiagnosticsView prerequisite = NavigateToSibling('Diagnostics')
[docs] def step(self): self.prerequisite_view.candugapcollection.select()
@Zone.exists.external_getter_implemented_for(ViaUI)
[docs]def exists(self): try: navigate_to(self, 'Details') return True except ZoneNotFound: return False
@Zone.update.external_implementation_for(ViaUI)
[docs]def update(self, updates): view = navigate_to(self, 'Edit') changed = view.fill(updates) if changed: view.save_button.click() else: view.cancel_button.click() view = self.create_view(ZoneDetailsView) # assert view.is_displayed view.flash.assert_no_error() if changed: view.flash.assert_message( 'Zone "{}" was saved'.format(updates.get('name', self.name))) else: view.flash.assert_message( 'Edit of Zone "{}" was cancelled by the user'.format(self.name))
@Zone.delete.external_implementation_for(ViaUI)
[docs]def delete(self, cancel=False): """ Delete the Zone represented by this object. Args: cancel: Whether to click on the cancel button in the pop-up. """ view = navigate_to(self, 'Details') view.configuration.item_select('Delete this Zone', handle_alert=not cancel) if not cancel: view.flash.assert_message('Zone "{}": Delete successful'.format(self.name))
@ZoneCollection.create.external_implementation_for(ViaUI)
[docs]def create(self, name=None, description=None, smartproxy_ip=None, ntp_servers=None, max_scans=None, user=None, cancel=False): add_page = navigate_to(self, 'Add') if not ntp_servers: ntp_servers = [] fill_dict = { k: v for k, v in { 'name': name, 'description': description, 'smartproxy_ip': smartproxy_ip, 'ntp_server_1': ntp_servers[0] if len(ntp_servers) > 0 else None, 'ntp_server_2': ntp_servers[1] if len(ntp_servers) > 1 else None, 'ntp_server_3': ntp_servers[2] if len(ntp_servers) > 2 else None, 'max_scans': max_scans, 'user': user.principal if user else None, 'password': user.secret if user else None, 'verify': user.secret if user else None }.items() if v is not None} add_page.fill(fill_dict) if cancel: add_page.cancel_button.click() add_page.flash.assert_no_error() add_page.flash.assert_message('Add of new Zone was cancelled by the user') return None else: add_page.add_button.click() add_page.flash.assert_no_error() add_page.flash.assert_message('Zone "{}" was added'.format(name)) return self.instantiate( region=self.region, name=name, description=description, smartproxy_ip=smartproxy_ip, ntp_servers=ntp_servers, max_scans=max_scans, user=user )
# AUTOMATE
[docs]class AutomateSimulationView(BaseLoggedInPage): @property def is_displayed(self): from cfme.automate import automate_menu_name return ( self.logged_in_as_current_user and self.navigation.currently_selected == automate_menu_name( self.context['object'].appliance) + ['Simulation']) instance = BootstrapSelect('instance_name') message = Input(name='object_message') request = Input(name='object_request') target_type = BootstrapSelect('target_class') target_object = BootstrapSelect('target_id') execute_methods = Checkbox(name='readonly') avp = AttributeValueForm('attribute_', 'value_') submit_button = Button(title='Submit Automation Simulation with the specified options') result_tree = ManageIQTree(tree_id='ae_simulation_treebox')
@navigator.register(Server)
[docs]class AutomateSimulation(CFMENavigateStep): VIEW = AutomateSimulationView prerequisite = NavigateToSibling('LoggedIn')
[docs] def step(self): from cfme.automate import automate_menu_name self.prerequisite_view.navigation.select( *automate_menu_name(self.obj.appliance) + ['Simulation'])
[docs]class AutomateImportExportBaseView(BaseLoggedInPage): flash = FlashMessages('div.import-flash-message') title = Text('.//div[@id="main-content"]//h1') @property def in_import_export(self): from cfme.automate import automate_menu_name return ( self.logged_in_as_current_user and self.navigation.currently_selected == automate_menu_name( self.context['object'].appliance) + ['Import / Export'] and self.title.text == 'Import / Export') @property def is_displayed(self): return self.in_import_export
[docs]class AutomateImportExportView(AutomateImportExportBaseView): class import_file(View): # noqa file = FileInput(name='upload_file') upload = Button('Upload') class import_git(View): # noqa ROOT = './/form[@id="retrieve-git-datastore-form"]' url = Input(name='git_url') username = Input(name='git_username') password = Input(name='git_password') verify_ssl = Checkbox(name='git_verify_ssl') submit = Button(id='git-url-import') export_all = Image('.//input[@title="Export all classes and instances"]') reset_all = Image('.//img[starts-with(@alt, "Reset all components in the following domains:")]') @property def is_displayed(self): return self.in_import_export and self.export_all.is_displayed
@navigator.register(Server)
[docs]class AutomateImportExport(CFMENavigateStep): VIEW = AutomateImportExportView prerequisite = NavigateToSibling('LoggedIn')
[docs] def step(self): from cfme.automate import automate_menu_name self.prerequisite_view.navigation.select( *automate_menu_name(self.obj.appliance) + ['Import / Export'])