def test_cannot_delete_more_than_once(single_provider):
    """When Delete button appars, it does not want to go away"""
    filter_name = fauxfactory.gen_alphanumeric()
    assert search.save_filter("fill_count(Infrastructure Provider.VMs, >, 0)", filter_name)

    assert search.load_filter(filter_name)  # circumvent the thing happening in previous test
    # Delete once
    if not search.delete_filter():
        pytest.fail("Could not delete the filter even first time!")
    assert_no_cfme_exception()
    # Try it second time
    if search.delete_filter():  # If the button is there, it says True
        # This should not happen
        msg = "Delete twice accepted!"
        if is_cfme_exception():
            msg += " CFME Exception text: `{}`".format(cfme_exception_text())
        pytest.fail(msg)
def test_cannot_delete_more_than_once():
    """When Delete button appars, it does not want to go away"""
    filter_name = fauxfactory.gen_alphanumeric()
    assert search.save_filter("fill_count(Infrastructure Provider.VMs, >, 0)", filter_name)

    assert search.load_filter(filter_name)  # circumvent the thing happening in previous test
    # Delete once
    if not search.delete_filter():
        pytest.fail("Could not delete the filter even first time!")
    assert_no_cfme_exception()
    # Try it second time
    if search.delete_filter():  # If the button is there, it says True
        # This should not happen
        msg = "Delete twice accepted!"
        if is_cfme_exception():
            msg += " CFME Exception text: `{}`".format(cfme_exception_text())
        pytest.fail(msg)
def test_cannot_delete_more_than_once(request, nuke_browser_after_test):
    """When Delete button appars, it does not want to go away"""
    pytest.sel.force_navigate("infrastructure_hosts")
    filter_name = fauxfactory.gen_alphanumeric()
    search.save_filter(get_expression(False).format(0), filter_name)

    search.load_filter(filter_name)  # circumvent the thing happening in previous test
    # Delete once
    if not search.delete_filter():
        pytest.fail("Could not delete the filter even first time!")
    assert_no_cfme_exception()
    # Try it second time
    if search.delete_filter():  # If the button is there, it says True
        # This should not happen
        msg = "Delete twice accepted!"
        if is_cfme_exception():
            msg += " CFME Exception text: `{}`".format(cfme_exception_text())
        pytest.fail(msg)
Exemple #4
0
def test_cannot_delete_more_than_once(request, nuke_browser_after_test):
    """When Delete button appars, it does not want to go away"""
    navigate_to(Host, 'All')
    filter_name = fauxfactory.gen_alphanumeric()
    search.save_filter(get_expression(False).format(0), filter_name)

    search.load_filter(filter_name)  # circumvent the thing happening in previous test
    # Delete once
    if not search.delete_filter():
        pytest.fail("Could not delete the filter even first time!")
    assert_no_cfme_exception()
    # Try it second time
    if search.delete_filter():  # If the button is there, it says True
        # This should not happen
        msg = "Delete twice accepted!"
        if is_cfme_exception():
            msg += " CFME Exception text: `{}`".format(cfme_exception_text())
        pytest.fail(msg)
def test_cannot_delete_more_than_once(request):
    """When Delete button appars, it does not want to go away"""
    sel.force_navigate("infra_vms")
    filter_name = fauxfactory.gen_alphanumeric()
    search.save_filter("fill_count(Virtual Machine.Files, >, 0)", filter_name)

    search.load_filter(filter_name)  # circumvent the thing happening in previous test
    # Delete once
    if not search.delete_filter():
        pytest.fail("Could not delete the filter even first time!")
    assert_no_cfme_exception()
    # Try it second time
    if search.delete_filter():  # If the button is there, it says True
        # This should not happen
        msg = "Delete twice accepted!"
        if is_cfme_exception():
            msg += " CFME Exception text: `{}`".format(cfme_exception_text())
        pytest.fail(msg)
def test_cannot_delete_more_than_once(vm_advanced_search, nuke_browser_after_test):
    """When Delete button appars, it does not want to go away"""
    filter_name = fauxfactory.gen_alphanumeric()
    vm_advanced_search.entities.search.save_filter(
        "fill_count(Virtual Machine.Files, >, 0)", filter_name)
    # circumvent the thing happening in previous test
    vm_advanced_search.entities.search.load_filter(filter_name)
    # Delete once
    if not vm_advanced_search.entities.search.delete_filter():
        pytest.fail("Could not delete the filter even first time!")
    vm_advanced_search.flash.assert_no_error()
    # Try it second time
    if vm_advanced_search.entities.search.delete_filter():  # If the button is there, it says True
        # This should not happen reduntant
        msg = "Delete twice accepted!"
        if is_cfme_exception():
            msg += " CFME Exception text: `{}`".format(cfme_exception_text())
        pytest.fail(msg)
Exemple #7
0
def test_cannot_delete_more_than_once(request):
    """When Delete button appars, it does not want to go away"""
    sel.force_navigate("infrastructure_hosts")
    filter_name = generate_random_string()
    search.save_filter("fill_count(Host.VMs, >, 0)", filter_name)

    search.load_filter(
        filter_name)  # circumvent the thing happening in previous test
    # Delete once
    if not search.delete_filter():
        pytest.fail("Could not delete the filter even first time!")
    assert_no_cfme_exception()
    # Try it second time
    if search.delete_filter():  # If the button is there, it says True
        # This should not happen
        msg = "Delete twice accepted!"
        if is_cfme_exception():
            msg += " CFME Exception text: `{}`".format(cfme_exception_text())
        pytest.fail(msg)
def test_cannot_delete_more_than_once(host_collection, hosts_advanced_search,
                                      nuke_browser_after_test):
    """When Delete button appars, it does not want to go away"""
    filter_name = fauxfactory.gen_alphanumeric()
    hosts_advanced_search.entities.search.save_filter(get_expression(False).format(0), filter_name)
    # circumvent the thing happening in previous test
    hosts_advanced_search.entities.search.load_filter(filter_name)
    # Delete once
    if not hosts_advanced_search.entities.search.delete_filter():
        pytest.fail("Could not delete the filter even first time!")
    hosts_advanced_search.flash.assert_no_error()
    # Try it second time
    # If the button is there, it says True
    if hosts_advanced_search.entities.search.delete_filter():
        # This should not happen
        msg = "Delete twice accepted!"
        if is_cfme_exception():
            msg += " CFME Exception text: `{}`".format(cfme_exception_text())
        pytest.fail(msg)
def force_navigate(page_name, _tries=0, *args, **kwargs):
    """force_navigate(page_name)

    Given a page name, attempt to navigate to that page no matter what breaks.

    Args:
        page_name: Name a page from the current :py:data:`ui_navigate.nav_tree` tree to navigate to.

    """
    if _tries > 2:
        # Need at least three tries:
        # 1: login_admin handles an alert or CannotContinueWithNavigation appears.
        # 2: Everything should work. If not, NavigationError.
        raise exceptions.NavigationError(page_name)

    _tries += 1

    logger.debug('force_navigate to %s, try %d' % (page_name, _tries))
    # circular import prevention: cfme.login uses functions in this module
    from cfme import login
    # Import the top-level nav menus for convenience
    from cfme.web_ui import menu

    # browser fixture should do this, but it's needed for subsequent calls
    ensure_browser_open()

    # Clear any running "spinnies"
    try:
        execute_script('miqSparkleOff();')
    except:
        # miqSparkleOff undefined, so it's definitely off.
        pass

    # Set this to True in the handlers below to trigger a browser restart
    recycle = False

    # remember the current user, if any
    current_user = login.current_user()

    try:
        # What we'd like to happen...
        if not current_user:  # default to admin user
            login.login_admin()
        else:  # we recycled and want to log back in
            login.login(current_user.username, current_user.password)
        logger.info('Navigating to %s' % page_name)
        menu.nav.go_to(page_name, *args, **kwargs)
    except (KeyboardInterrupt, ValueError):
        # KeyboardInterrupt: Don't block this while navigating
        # ValueError: ui_navigate.go_to can't handle this page, give up
        raise
    except UnexpectedAlertPresentException:
        if _tries == 1:
            # There was an alert, accept it and try again
            handle_alert(wait=0)
            force_navigate(page_name, _tries, *args, **kwargs)
        else:
            # There was still an alert when we tried again, shoot the browser in the head
            logger.debug('Unxpected alert, recycling browser')
            recycle = True
    except (ErrorInResponseException, InvalidSwitchToTargetException):
        # Unable to switch to the browser at all, need to recycle
        logger.info('Invalid browser state, recycling browser')
        recycle = True
    except exceptions.CannotContinueWithNavigation as e:
        # The some of the navigation steps cannot succeed
        logger.info('Cannot continue with navigation due to: %s; Recycling browser' % str(e))
        recycle = True
    except (NoSuchElementException, InvalidElementStateException, WebDriverException):
        from cfme.web_ui import cfme_exception as cfme_exc  # To prevent circular imports
        # If the page is blocked, then recycle...
        if is_displayed("//div[@id='blocker_div']"):
            logger.warning("Page was blocked with blocker div, recycling.")
            recycle = True
        elif cfme_exc.is_cfme_exception():
            logger.exception("CFME Exception before force_navigate started!: `{}`".format(
                cfme_exc.cfme_exception_text()
            ))
            recycle = True
        elif is_displayed("//body/div[@class='dialog' and ./h1 and ./p]"):
            # Rails exception detection
            logger.exception("Rails exception before force_navigate started!: {}:{} at {}".format(
                text("//body/div[@class='dialog']/h1").encode("utf-8"),
                text("//body/div[@class='dialog']/p").encode("utf-8"),
                current_url()
            ))
            recycle = True
        elif elements("//ul[@id='maintab']/li[@class='inactive']") and not\
                elements("//ul[@id='maintab']/li[@class='active']/ul/li"):
            # If upstream and is the bottom part of menu is not displayed
            logger.exception("Detected glitch from BZ#1112574. HEADSHOT!")
            recycle = True
        else:
            logger.error("Could not determine the reason for failing the navigation. Reraising.")
            raise

    if recycle:
        browser().quit()  # login.current_user() will be retained for next login
        logger.debug('browser killed on try %d' % _tries)
        # If given a "start" nav destination, it won't be valid after quitting the browser
        kwargs.pop("start", None)
        force_navigate(page_name, _tries, *args, **kwargs)
Exemple #10
0
def force_navigate(page_name, _tries=0, *args, **kwargs):
    """force_navigate(page_name)

    Given a page name, attempt to navigate to that page no matter what breaks.

    Args:
        page_name: Name a page from the current :py:data:`ui_navigate.nav_tree` tree to navigate to.

    """
    if _tries > 2:
        # Need at least three tries:
        # 1: login_admin handles an alert or CannotContinueWithNavigation appears.
        # 2: Everything should work. If not, NavigationError.
        raise exceptions.NavigationError(page_name)

    _tries += 1

    logger.debug('force_navigate to %s, try %d' % (page_name, _tries))
    # circular import prevention: cfme.login uses functions in this module
    from cfme import login
    # Import the top-level nav menus for convenience
    from cfme.web_ui import menu

    # browser fixture should do this, but it's needed for subsequent calls
    ensure_browser_open()

    # Clear any running "spinnies"
    try:
        execute_script('miqSparkleOff();')
    except:
        # miqSparkleOff undefined, so it's definitely off.
        pass

    # Set this to True in the handlers below to trigger a browser restart
    recycle = False

    # remember the current user, if any
    current_user = login.current_user()

    try:
        # What we'd like to happen...
        if not current_user:  # default to admin user
            login.login_admin()
        else:  # we recycled and want to log back in
            login.login(current_user.username, current_user.password)
        logger.info('Navigating to %s' % page_name)
        menu.nav.go_to(page_name, *args, **kwargs)
    except (KeyboardInterrupt, ValueError):
        # KeyboardInterrupt: Don't block this while navigating
        # ValueError: ui_navigate.go_to can't handle this page, give up
        raise
    except UnexpectedAlertPresentException:
        if _tries == 1:
            # There was an alert, accept it and try again
            handle_alert(wait=0)
            force_navigate(page_name, _tries, *args, **kwargs)
        else:
            # There was still an alert when we tried again, shoot the browser in the head
            logger.debug('Unxpected alert, recycling browser')
            recycle = True
    except (ErrorInResponseException, InvalidSwitchToTargetException):
        # Unable to switch to the browser at all, need to recycle
        logger.info('Invalid browser state, recycling browser')
        recycle = True
    except exceptions.CannotContinueWithNavigation as e:
        # The some of the navigation steps cannot succeed
        logger.info(
            'Cannot continue with navigation due to: %s; Recycling browser' %
            str(e))
        recycle = True
    except (NoSuchElementException, InvalidElementStateException,
            WebDriverException):
        from cfme.web_ui import cfme_exception as cfme_exc  # To prevent circular imports
        # If the page is blocked, then recycle...
        if is_displayed("//div[@id='blocker_div']"):
            logger.warning("Page was blocked with blocker div, recycling.")
            recycle = True
        elif cfme_exc.is_cfme_exception():
            logger.exception(
                "CFME Exception before force_navigate started!: `{}`".format(
                    cfme_exc.cfme_exception_text()))
            recycle = True
        elif is_displayed("//body/div[@class='dialog' and ./h1 and ./p]"):
            # Rails exception detection
            logger.exception(
                "Rails exception before force_navigate started!: {}:{} at {}".
                format(
                    text("//body/div[@class='dialog']/h1").encode("utf-8"),
                    text("//body/div[@class='dialog']/p").encode("utf-8"),
                    current_url()))
            recycle = True
        elif elements("//ul[@id='maintab']/li[@class='inactive']") and not\
                elements("//ul[@id='maintab']/li[@class='active']/ul/li"):
            # If upstream and is the bottom part of menu is not displayed
            logger.exception("Detected glitch from BZ#1112574. HEADSHOT!")
            recycle = True
        else:
            logger.error(
                "Could not determine the reason for failing the navigation. Reraising."
            )
            raise

    if recycle:
        browser().quit(
        )  # login.current_user() will be retained for next login
        logger.debug('browser killed on try %d' % _tries)
        # If given a "start" nav destination, it won't be valid after quitting the browser
        kwargs.pop("start", None)
        force_navigate(page_name, _tries, *args, **kwargs)
Exemple #11
0
    def check_for_badness(self, fn, _tries, nav_args, *args, **kwargs):
        if getattr(fn, '_can_skip_badness_test', False):
            # self.log_message('Op is a Nop! ({})'.format(fn.__name__))
            return

        if self.VIEW:
            self.view.flush_widget_cache()
        go_kwargs = kwargs.copy()
        go_kwargs.update(nav_args)
        self.appliance.browser.open_browser(url_key=self.obj.appliance.server.address())

        # check for MiqQE javascript patch on first try and patch the appliance if necessary
        if self.appliance.is_miqqe_patch_candidate and not self.appliance.miqqe_patch_applied:
            self.appliance.patch_with_miqqe()
            self.appliance.browser.quit_browser()
            _tries -= 1
            self.go(_tries, *args, **go_kwargs)

        br = self.appliance.browser

        try:
            br.widgetastic.execute_script('miqSparkleOff();', silent=True)
        except:  # noqa
            # miqSparkleOff undefined, so it's definitely off.
            # Or maybe it is alerts? Let's only do this when we get an exception.
            self.appliance.browser.widgetastic.dismiss_any_alerts()
            # If we went so far, let's put diapers on one more miqSparkleOff just to be sure
            # It can be spinning in the back
            try:
                br.widgetastic.execute_script('miqSparkleOff();', silent=True)
            except:  # noqa
                pass

        # Check if the page is blocked with blocker_div. If yes, let's headshot the browser right
        # here
        if (
                br.widgetastic.is_displayed("//div[@id='blocker_div' or @id='notification']") or
                br.widgetastic.is_displayed(".modal-backdrop.fade.in")):
            logger.warning("Page was blocked with blocker div on start of navigation, recycling.")
            self.appliance.browser.quit_browser()
            self.go(_tries, *args, **go_kwargs)

        # Check if modal window is displayed
        if (br.widgetastic.is_displayed(
                "//div[contains(@class, 'modal-dialog') and contains(@class, 'modal-lg')]")):
            logger.warning("Modal window was open; closing the window")
            br.widgetastic.click(
                "//button[contains(@class, 'close') and contains(@data-dismiss, 'modal')]")

        # Check if jQuery present
        try:
            br.widgetastic.execute_script("jQuery", silent=True)
        except Exception as e:
            if "jQuery" not in str(e):
                logger.error("Checked for jQuery but got something different.")
                logger.exception(e)
            # Restart some workers
            logger.warning("Restarting UI and VimBroker workers!")
            with self.appliance.ssh_client as ssh:
                # Blow off the Vim brokers and UI workers
                ssh.run_rails_command("\"(MiqVimBrokerWorker.all + MiqUiWorker.all).each &:kill\"")
            logger.info("Waiting for web UI to come back alive.")
            sleep(10)   # Give it some rest
            self.appliance.wait_for_web_ui()
            self.appliance.browser.quit_browser()
            self.appliance.browser.open_browser(url_key=self.obj.appliance.server.address())
            self.go(_tries, *args, **go_kwargs)

        # Same with rails errors
        view = br.widgetastic.create_view(ErrorView)
        rails_e = view.get_rails_error()

        if rails_e is not None:
            logger.warning("Page was blocked by rails error, renavigating.")
            logger.error(rails_e)
            # RHEL7 top does not know -M and -a
            logger.debug('Top CPU consumers:')
            logger.debug(store.current_appliance.ssh_client.run_command(
                'top -c -b -n1 | head -30').output)
            logger.debug('Top Memory consumers:')
            logger.debug(store.current_appliance.ssh_client.run_command(
                'top -c -b -n1 -o "%MEM" | head -30').output)  # noqa
            logger.debug('Managed known Providers:')
            logger.debug(
                '%r', [prov.key for prov in store.current_appliance.managed_known_providers])
            self.appliance.browser.quit_browser()
            self.appliance.browser.open_browser()
            self.go(_tries, *args, **go_kwargs)
            # If there is a rails error past this point, something is really awful

        # Set this to True in the handlers below to trigger a browser restart
        recycle = False

        # Set this to True in handlers to restart evmserverd on the appliance
        # Includes recycling so you don't need to specify recycle = False
        restart_evmserverd = False

        try:
            self.log_message(
                "Invoking {}, with {} and {}".format(fn.func_name, args, kwargs), level="debug")
            return fn(*args, **kwargs)
        except (KeyboardInterrupt, ValueError):
            # KeyboardInterrupt: Don't block this while navigating
            raise
        except UnexpectedAlertPresentException:
            if _tries == 1:
                # There was an alert, accept it and try again
                br.widgetastic.handle_alert(wait=0)
                self.go(_tries, *args, **go_kwargs)
            else:
                # There was still an alert when we tried again, shoot the browser in the head
                logger.debug('Unxpected alert, recycling browser')
                recycle = True
        except (ErrorInResponseException, InvalidSwitchToTargetException):
            # Unable to switch to the browser at all, need to recycle
            logger.info('Invalid browser state, recycling browser')
            recycle = True
        except exceptions.CFMEExceptionOccured as e:
            # We hit a Rails exception
            logger.info('CFME Exception occured')
            logger.exception(e)
            recycle = True
        except exceptions.CannotContinueWithNavigation as e:
            # The some of the navigation steps cannot succeed
            logger.info('Cannot continue with navigation due to: {}; '
                'Recycling browser'.format(str(e)))
            recycle = True
        except (NoSuchElementException, InvalidElementStateException, WebDriverException,
                StaleElementReferenceException) as e:
            from cfme.web_ui import cfme_exception as cfme_exc  # To prevent circular imports
            # First check - if jquery is not found, there can be also another
            # reason why this happened so do not put the next branches in elif
            if isinstance(e, WebDriverException) and "jQuery" in str(e):
                # UI failed in some way, try recycling the browser
                logger.exception(
                    "UI failed in some way, jQuery not found, (probably) recycling the browser.")
                recycle = True
            # If the page is blocked, then recycle...
            # TODO .modal-backdrop.fade.in catches the 'About' modal resulting in nav loop
            if (
                    br.widgetastic.is_displayed("//div[@id='blocker_div' or @id='notification']") or
                    br.widgetastic.is_displayed(".modal-backdrop.fade.in")):
                logger.warning("Page was blocked with blocker div, recycling.")
                recycle = True
            elif cfme_exc.is_cfme_exception():
                logger.exception("CFME Exception before force navigate started!: {}".format(
                    cfme_exc.cfme_exception_text()))
                recycle = True
            elif br.widgetastic.is_displayed("//body/h1[normalize-space(.)='Proxy Error']"):
                # 502
                logger.exception("Proxy error detected. Killing browser and restarting evmserverd.")
                req = br.widgetastic.elements("/html/body/p[1]//a")
                req = br.widgetastic.text(req[0]) if req else "No request stated"
                reason = br.widgetastic.elements("/html/body/p[2]/strong")
                reason = br.widgetastic.text(reason[0]) if reason else "No reason stated"
                logger.info("Proxy error: {} / {}".format(req, reason))
                restart_evmserverd = True
            elif br.widgetastic.is_displayed("//body[./h1 and ./p and ./hr and ./address]"):
                # 503 and similar sort of errors
                title = br.widgetastic.text("//body/h1")
                body = br.widgetastic.text("//body/p")
                logger.exception("Application error {}: {}".format(title, body))
                sleep(5)  # Give it a little bit of rest
                recycle = True
            elif br.widgetastic.is_displayed("//body/div[@class='dialog' and ./h1 and ./p]"):
                # Rails exception detection
                logger.exception("Rails exception before force navigate started!: %r:%r at %r",
                    br.widgetastic.text("//body/div[@class='dialog']/h1"),
                    br.widgetastic.text("//body/div[@class='dialog']/p"),
                    getattr(manager.browser, 'current_url', "error://dead-browser")
                )
                recycle = True
            elif br.widgetastic.elements("//ul[@id='maintab']/li[@class='inactive']") and not\
                    br.widgetastic.elements("//ul[@id='maintab']/li[@class='active']/ul/li"):
                # If upstream and is the bottom part of menu is not displayed
                logger.exception("Detected glitch from BZ#1112574. HEADSHOT!")
                recycle = True
            elif not self.obj.appliance.server.logged_in():
                # Session timeout or whatever like that, login screen appears.
                logger.exception("Looks like we are logged out. Try again.")
                recycle = True
            else:
                logger.error("Could not determine the reason for failing the navigation. " +
                    " Reraising.  Exception: {}".format(str(e)))
                logger.debug(store.current_appliance.ssh_client.run_command(
                    'systemctl status evmserverd').output)
                raise

        if restart_evmserverd:
            logger.info("evmserverd restart requested")
            self.appliance.restart_evm_service()
            self.appliance.wait_for_web_ui()
            self.go(_tries, *args, **go_kwargs)

        if recycle or restart_evmserverd:
            self.appliance.browser.quit_browser()
            logger.debug('browser killed on try {}'.format(_tries))
            # If given a "start" nav destination, it won't be valid after quitting the browser
            self.go(_tries, *args, **go_kwargs)
Exemple #12
0
    def check_for_badness(self, fn, _tries, nav_args, *args, **kwargs):
        if getattr(fn, '_can_skip_badness_test', False):
            # self.log_message('Op is a Nop! ({})'.format(fn.__name__))
            return

        if self.VIEW:
            self.view.flush_widget_cache()
        go_kwargs = kwargs.copy()
        go_kwargs.update(nav_args)
        self.appliance.browser.open_browser()
        self.appliance.browser.widgetastic.dismiss_any_alerts()

        # check for MiqQE javascript patch on first try and patch the appliance if necessary
        if self.appliance.is_miqqe_patch_candidate and not self.appliance.miqqe_patch_applied:
            self.appliance.patch_with_miqqe()
            self.appliance.browser.quit_browser()
            _tries -= 1
            self.go(_tries, *args, **go_kwargs)

        br = self.appliance.browser

        try:
            br.widgetastic.execute_script('miqSparkleOff();', silent=True)
        except:  # Diaper OK (mfalesni)
            # miqSparkleOff undefined, so it's definitely off.
            pass

        # Check if the page is blocked with blocker_div. If yes, let's headshot the browser right
        # here
        if (
                br.widgetastic.is_displayed("//div[@id='blocker_div' or @id='notification']") or
                br.widgetastic.is_displayed(".modal-backdrop.fade.in")):
            logger.warning("Page was blocked with blocker div on start of navigation, recycling.")
            self.appliance.browser.quit_browser()
            self.go(_tries, *args, **go_kwargs)

        # Check if modal window is displayed
        if (br.widgetastic.is_displayed(
                "//div[contains(@class, 'modal-dialog') and contains(@class, 'modal-lg')]")):
            logger.warning("Modal window was open; closing the window")
            br.widgetastic.click(
                "//button[contains(@class, 'close') and contains(@data-dismiss, 'modal')]")

        # Check if jQuery present
        try:
            br.widgetastic.execute_script("jQuery", silent=True)
        except Exception as e:
            if "jQuery" not in str(e):
                logger.error("Checked for jQuery but got something different.")
                logger.exception(e)
            # Restart some workers
            logger.warning("Restarting UI and VimBroker workers!")
            with self.appliance.ssh_client as ssh:
                # Blow off the Vim brokers and UI workers
                ssh.run_rails_command("\"(MiqVimBrokerWorker.all + MiqUiWorker.all).each &:kill\"")
            logger.info("Waiting for web UI to come back alive.")
            sleep(10)   # Give it some rest
            self.appliance.wait_for_web_ui()
            self.appliance.browser.quit_browser()
            self.appliance.browser.open_browser()
            self.go(_tries, *args, **go_kwargs)

        # Same with rails errors
        rails_e = get_rails_error()
        if rails_e is not None:
            logger.warning("Page was blocked by rails error, renavigating.")
            logger.error(rails_e)
            # RHEL7 top does not know -M and -a
            logger.debug('Top CPU consumers:')
            logger.debug(store.current_appliance.ssh_client.run_command(
                'top -c -b -n1 | head -30').output)
            logger.debug('Top Memory consumers:')
            logger.debug(store.current_appliance.ssh_client.run_command(
                'top -c -b -n1 -o "%MEM" | head -30').output)  # noqa
            logger.debug('Managed known Providers:')
            logger.debug(
                '%r', [prov.key for prov in store.current_appliance.managed_known_providers])
            self.appliance.browser.quit_browser()
            self.appliance.browser.open_browser()
            self.go(_tries, *args, **go_kwargs)
            # If there is a rails error past this point, something is really awful

        # Set this to True in the handlers below to trigger a browser restart
        recycle = False

        # Set this to True in handlers to restart evmserverd on the appliance
        # Includes recycling so you don't need to specify recycle = False
        restart_evmserverd = False

        from cfme import login

        try:
            self.log_message(
                "Invoking {}, with {} and {}".format(fn.func_name, args, kwargs), level="debug")
            return fn(*args, **kwargs)
        except (KeyboardInterrupt, ValueError):
            # KeyboardInterrupt: Don't block this while navigating
            raise
        except UnexpectedAlertPresentException:
            if _tries == 1:
                # There was an alert, accept it and try again
                br.widgetastic.handle_alert(wait=0)
                self.go(_tries, *args, **go_kwargs)
            else:
                # There was still an alert when we tried again, shoot the browser in the head
                logger.debug('Unxpected alert, recycling browser')
                recycle = True
        except (ErrorInResponseException, InvalidSwitchToTargetException):
            # Unable to switch to the browser at all, need to recycle
            logger.info('Invalid browser state, recycling browser')
            recycle = True
        except exceptions.CFMEExceptionOccured as e:
            # We hit a Rails exception
            logger.info('CFME Exception occured')
            logger.exception(e)
            recycle = True
        except exceptions.CannotContinueWithNavigation as e:
            # The some of the navigation steps cannot succeed
            logger.info('Cannot continue with navigation due to: {}; '
                'Recycling browser'.format(str(e)))
            recycle = True
        except (NoSuchElementException, InvalidElementStateException, WebDriverException,
                StaleElementReferenceException) as e:
            from cfme.web_ui import cfme_exception as cfme_exc  # To prevent circular imports
            # First check - if jquery is not found, there can be also another
            # reason why this happened so do not put the next branches in elif
            if isinstance(e, WebDriverException) and "jQuery" in str(e):
                # UI failed in some way, try recycling the browser
                logger.exception(
                    "UI failed in some way, jQuery not found, (probably) recycling the browser.")
                recycle = True
            # If the page is blocked, then recycle...
            if (
                    br.widgetastic.is_displayed("//div[@id='blocker_div' or @id='notification']") or
                    br.widgetastic.is_displayed(".modal-backdrop.fade.in")):
                logger.warning("Page was blocked with blocker div, recycling.")
                recycle = True
            elif cfme_exc.is_cfme_exception():
                logger.exception("CFME Exception before force navigate started!: {}".format(
                    cfme_exc.cfme_exception_text()))
                recycle = True
            elif br.widgetastic.is_displayed("//body/h1[normalize-space(.)='Proxy Error']"):
                # 502
                logger.exception("Proxy error detected. Killing browser and restarting evmserverd.")
                req = br.widgetastic.elements("/html/body/p[1]//a")
                req = br.widgetastic.text(req[0]) if req else "No request stated"
                reason = br.widgetastic.elements("/html/body/p[2]/strong")
                reason = br.widgetastic.text(reason[0]) if reason else "No reason stated"
                logger.info("Proxy error: {} / {}".format(req, reason))
                restart_evmserverd = True
            elif br.widgetastic.is_displayed("//body[./h1 and ./p and ./hr and ./address]"):
                # 503 and similar sort of errors
                title = br.widgetastic.text("//body/h1")
                body = br.widgetastic.text("//body/p")
                logger.exception("Application error {}: {}".format(title, body))
                sleep(5)  # Give it a little bit of rest
                recycle = True
            elif br.widgetastic.is_displayed("//body/div[@class='dialog' and ./h1 and ./p]"):
                # Rails exception detection
                logger.exception("Rails exception before force navigate started!: %r:%r at %r",
                    br.widgetastic.text("//body/div[@class='dialog']/h1"),
                    br.widgetastic.text("//body/div[@class='dialog']/p"),
                    getattr(manager.browser, 'current_url', "error://dead-browser")
                )
                recycle = True
            elif br.widgetastic.elements("//ul[@id='maintab']/li[@class='inactive']") and not\
                    br.widgetastic.elements("//ul[@id='maintab']/li[@class='active']/ul/li"):
                # If upstream and is the bottom part of menu is not displayed
                logger.exception("Detected glitch from BZ#1112574. HEADSHOT!")
                recycle = True
            elif not login.logged_in():
                # Session timeout or whatever like that, login screen appears.
                logger.exception("Looks like we are logged out. Try again.")
                recycle = True
            else:
                logger.error("Could not determine the reason for failing the navigation. " +
                    " Reraising.  Exception: {}".format(str(e)))
                logger.debug(store.current_appliance.ssh_client.run_command(
                    'systemctl status evmserverd').output)
                raise

        if restart_evmserverd:
            logger.info("evmserverd restart requested")
            self.appliance.restart_evm_service()
            self.appliance.wait_for_web_ui()
            self.go(_tries, *args, **go_kwargs)

        if recycle or restart_evmserverd:
            self.appliance.browser.quit_browser()
            logger.debug('browser killed on try {}'.format(_tries))
            # If given a "start" nav destination, it won't be valid after quitting the browser
            self.go(_tries, *args, **go_kwargs)
def force_navigate(page_name, _tries=0, *args, **kwargs):
    """force_navigate(page_name)

    Given a page name, attempt to navigate to that page no matter what breaks.

    Args:
        page_name: Name a page from the current :py:data:`ui_navigate.nav_tree` tree to navigate to.

    """
    if _tries > 2:
        # Need at least three tries:
        # 1: login_admin handles an alert or CannotContinueWithNavigation appears.
        # 2: Everything should work. If not, NavigationError.
        raise exceptions.NavigationError(page_name)

    if "context" in kwargs:
        if not isinstance(kwargs["context"], ContextWrapper) and isinstance(
                kwargs["context"], dict):
            kwargs["context"] = ContextWrapper(kwargs["context"])

    _tries += 1

    logger.debug('force_navigate to %s, try %d' % (page_name, _tries))
    # circular import prevention: cfme.login uses functions in this module
    from cfme import login
    # Import the top-level nav menus for convenience
    from cfme.web_ui import menu

    # browser fixture should do this, but it's needed for subsequent calls
    ensure_browser_open()

    # Clear any running "spinnies"
    try:
        execute_script('miqSparkleOff();')
    except:  # Diaper OK (mfalesni)
        # miqSparkleOff undefined, so it's definitely off.
        pass

    # Set this to True in the handlers below to trigger a browser restart
    recycle = False

    # remember the current user, if any
    current_user = login.current_user()

    # Check if the page is blocked with blocker_div. If yes, let's headshot the browser right here
    if (
            is_displayed("//div[@id='blocker_div' or @id='notification']", _no_deeper=True)
            or is_displayed(".modal-backdrop.fade.in", _no_deeper=True)):
        logger.warning("Page was blocked with blocker div on start of navigation, recycling.")
        quit()
        kwargs.pop("start", None)
        force_navigate("dashboard")  # Start fresh

    # Check if jQuery present
    try:
        execute_script("jQuery")
    except Exception as e:
        if "jQuery" not in str(e):
            logger.error("Checked for jQuery but got something different.")
            logger.exception(e)
        # Restart some workers
        logger.warning("Restarting UI and VimBroker workers!")
        with store.current_appliance.ssh_client() as ssh:
            # Blow off the Vim brokers and UI workers
            ssh.run_rails_command("\"(MiqVimBrokerWorker.all + MiqUiWorker.all).each &:kill\"")
        logger.info("Waiting for web UI to come back alive.")
        sleep(10)   # Give it some rest
        store.current_appliance.wait_for_web_ui()
        quit()
        ensure_browser_open()
        kwargs.pop("start", None)
        force_navigate("dashboard")  # And start fresh

    # Same with rails errors
    rails_e = get_rails_error()
    if rails_e is not None:
        logger.warning("Page was blocked by rails error, renavigating.")
        logger.error(rails_e)
        logger.debug('Top CPU consumers:')
        logger.debug(store.current_appliance.ssh_client().run_command(
            'top -c -b -n1 -M | head -30').output)
        logger.debug('Top Memory consumers:')
        logger.debug(store.current_appliance.ssh_client().run_command(
            'top -c -b -n1 -M -a | head -30').output)
        logger.debug('Managed Providers:')
        logger.debug(store.current_appliance.managed_providers)
        quit()  # Refresh the session, forget loaded summaries, ...
        kwargs.pop("start", None)
        ensure_browser_open()
        menu.nav.go_to("dashboard")
        # If there is a rails error past this point, something is really awful

    def _login_func():
        if not current_user:  # default to admin user
            login.login_admin()
        else:  # we recycled and want to log back in
            login.login(current_user.username, current_user.password)

    try:
        try:
            # What we'd like to happen...
            _login_func()
        except WebDriverException as e:
            if "jquery" not in str(e).lower():
                raise  # Something unknown happened
            logger.info("Seems we got a non-CFME page (blank or screwed up) so killing the browser")
            quit()
            ensure_browser_open()
            # And try it again
            _login_func()
            # If this failed, no help with that :/

        logger.info('Navigating to %s' % page_name)
        menu.nav.go_to(page_name, *args, **kwargs)
    except (KeyboardInterrupt, ValueError):
        # KeyboardInterrupt: Don't block this while navigating
        # ValueError: ui_navigate.go_to can't handle this page, give up
        raise
    except UnexpectedAlertPresentException:
        if _tries == 1:
            # There was an alert, accept it and try again
            handle_alert(wait=0)
            force_navigate(page_name, _tries, *args, **kwargs)
        else:
            # There was still an alert when we tried again, shoot the browser in the head
            logger.debug('Unxpected alert, recycling browser')
            recycle = True
    except (ErrorInResponseException, InvalidSwitchToTargetException):
        # Unable to switch to the browser at all, need to recycle
        logger.info('Invalid browser state, recycling browser')
        recycle = True
    except exceptions.CFMEExceptionOccured as e:
        # We hit a Rails exception
        logger.info('CFME Exception occured')
        logger.exception(e)
        recycle = True
    except exceptions.CannotContinueWithNavigation as e:
        # The some of the navigation steps cannot succeed
        logger.info('Cannot continue with navigation due to: %s; Recycling browser' % str(e))
        recycle = True
    except (NoSuchElementException, InvalidElementStateException, WebDriverException) as e:
        from cfme.web_ui import cfme_exception as cfme_exc  # To prevent circular imports
        # First check - if jquery is not found, there can be also another reason why this happened
        # so do not put the next branches in elif
        if isinstance(e, WebDriverException) and "jQuery" in str(e):
            # UI failed in some way, try recycling the browser
            logger.exception(
                "UI failed in some way, jQuery not found, (probably) recycling the browser.")
            recycle = True
        # If the page is blocked, then recycle...
        if (
                is_displayed("//div[@id='blocker_div' or @id='notification']", _no_deeper=True)
                or is_displayed(".modal-backdrop.fade.in", _no_deeper=True)):
            logger.warning("Page was blocked with blocker div, recycling.")
            recycle = True
        elif cfme_exc.is_cfme_exception():
            logger.exception("CFME Exception before force_navigate started!: `{}`".format(
                cfme_exc.cfme_exception_text()
            ))
            recycle = True
        elif is_displayed("//body[./h1 and ./p and ./hr and ./address]", _no_deeper=True):
            # 503 and similar sort of errors
            title = text("//body/h1")
            body = text("//body/p")
            logger.exception("Application error '{}': {}".format(title, body))
            sleep(5)  # Give it a little bit of rest
            recycle = True
        elif is_displayed("//body/div[@class='dialog' and ./h1 and ./p]", _no_deeper=True):
            # Rails exception detection
            logger.exception("Rails exception before force_navigate started!: {}:{} at {}".format(
                text("//body/div[@class='dialog']/h1").encode("utf-8"),
                text("//body/div[@class='dialog']/p").encode("utf-8"),
                current_url()
            ))
            recycle = True
        elif elements("//ul[@id='maintab']/li[@class='inactive']") and not\
                elements("//ul[@id='maintab']/li[@class='active']/ul/li"):
            # If upstream and is the bottom part of menu is not displayed
            logger.exception("Detected glitch from BZ#1112574. HEADSHOT!")
            recycle = True
        else:
            logger.error("Could not determine the reason for failing the navigation. " +
                " Reraising.  Exception: %s" % str(e))
            logger.debug(store.current_appliance.ssh_client().run_command(
                'service evmserverd status').output)
            raise

    if recycle:
        browser().quit()  # login.current_user() will be retained for next login
        logger.debug('browser killed on try %d' % _tries)
        # If given a "start" nav destination, it won't be valid after quitting the browser
        kwargs.pop("start", None)
        force_navigate(page_name, _tries, *args, **kwargs)
def force_navigate(page_name, _tries=0, *args, **kwargs):
    """force_navigate(page_name)

    Given a page name, attempt to navigate to that page no matter what breaks.

    Args:
        page_name: Name a page from the current :py:data:`ui_navigate.nav_tree` tree to navigate to.

    """
    if _tries > 2:
        # Need at least three tries:
        # 1: login_admin handles an alert or CannotContinueWithNavigation appears.
        # 2: Everything should work. If not, NavigationError.
        raise exceptions.NavigationError(page_name)

    if "context" in kwargs:
        if not isinstance(kwargs["context"], ContextWrapper) and isinstance(
                kwargs["context"], dict):
            kwargs["context"] = ContextWrapper(kwargs["context"])

    _tries += 1

    logger.debug('force_navigate to %s, try %d' % (page_name, _tries))
    # circular import prevention: cfme.login uses functions in this module
    from cfme import login
    # Import the top-level nav menus for convenience
    from cfme.web_ui import menu

    # browser fixture should do this, but it's needed for subsequent calls
    ensure_browser_open()

    # Clear any running "spinnies"
    try:
        execute_script('miqSparkleOff();')
    except:  # Diaper OK (mfalesni)
        # miqSparkleOff undefined, so it's definitely off.
        pass

    # Set this to True in the handlers below to trigger a browser restart
    recycle = False

    # remember the current user, if any
    current_user = login.current_user()

    # Check if the page is blocked with blocker_div. If yes, let's headshot the browser right here
    if (
            is_displayed("//div[@id='blocker_div' or @id='notification']", _no_deeper=True)
            or is_displayed(".modal-backdrop.fade.in", _no_deeper=True)):
        logger.warning("Page was blocked with blocker div on start of navigation, recycling.")
        quit()
        kwargs.pop("start", None)
        force_navigate("dashboard")  # Start fresh

    # Check if modal window is displayed
    if (is_displayed(
            "//div[contains(@class, 'modal-dialog') and contains(@class, 'modal-lg')]",
            _no_deeper=True)):
        logger.warning("Modal window was open; closing the window")
        click("//button[contains(@class, 'close') and contains(@data-dismiss, 'modal')]")

    # Check if jQuery present
    try:
        execute_script("jQuery")
    except Exception as e:
        if "jQuery" not in str(e):
            logger.error("Checked for jQuery but got something different.")
            logger.exception(e)
        # Restart some workers
        logger.warning("Restarting UI and VimBroker workers!")
        with store.current_appliance.ssh_client as ssh:
            # Blow off the Vim brokers and UI workers
            ssh.run_rails_command("\"(MiqVimBrokerWorker.all + MiqUiWorker.all).each &:kill\"")
        logger.info("Waiting for web UI to come back alive.")
        sleep(10)   # Give it some rest
        store.current_appliance.wait_for_web_ui()
        quit()
        ensure_browser_open()
        kwargs.pop("start", None)
        force_navigate("dashboard")  # And start fresh

    # Same with rails errors
    rails_e = get_rails_error()
    if rails_e is not None:
        logger.warning("Page was blocked by rails error, renavigating.")
        logger.error(rails_e)
        logger.debug('Top CPU consumers:')
        logger.debug(store.current_appliance.ssh_client.run_command(
            'top -c -b -n1 -M | head -30').output)
        logger.debug('Top Memory consumers:')
        logger.debug(store.current_appliance.ssh_client.run_command(
            'top -c -b -n1 -M -a | head -30').output)
        logger.debug('Managed Providers:')
        logger.debug(store.current_appliance.managed_providers)
        quit()  # Refresh the session, forget loaded summaries, ...
        kwargs.pop("start", None)
        ensure_browser_open()
        menu.nav.go_to("dashboard")
        # If there is a rails error past this point, something is really awful

    def _login_func():
        if not current_user:  # default to admin user
            login.login_admin()
        else:  # we recycled and want to log back in
            login.login(current_user.username, current_user.password)

    try:
        try:
            # What we'd like to happen...
            _login_func()
        except WebDriverException as e:
            if "jquery" not in str(e).lower():
                raise  # Something unknown happened
            logger.info("Seems we got a non-CFME page (blank or screwed up) so killing the browser")
            quit()
            ensure_browser_open()
            # And try it again
            _login_func()
            # If this failed, no help with that :/

        logger.info('Navigating to %s' % page_name)
        menu.nav.go_to(page_name, *args, **kwargs)
    except (KeyboardInterrupt, ValueError):
        # KeyboardInterrupt: Don't block this while navigating
        # ValueError: ui_navigate.go_to can't handle this page, give up
        raise
    except UnexpectedAlertPresentException:
        if _tries == 1:
            # There was an alert, accept it and try again
            handle_alert(wait=0)
            force_navigate(page_name, _tries, *args, **kwargs)
        else:
            # There was still an alert when we tried again, shoot the browser in the head
            logger.debug('Unxpected alert, recycling browser')
            recycle = True
    except (ErrorInResponseException, InvalidSwitchToTargetException):
        # Unable to switch to the browser at all, need to recycle
        logger.info('Invalid browser state, recycling browser')
        recycle = True
    except exceptions.CFMEExceptionOccured as e:
        # We hit a Rails exception
        logger.info('CFME Exception occured')
        logger.exception(e)
        recycle = True
    except exceptions.CannotContinueWithNavigation as e:
        # The some of the navigation steps cannot succeed
        logger.info('Cannot continue with navigation due to: %s; Recycling browser' % str(e))
        recycle = True
    except (NoSuchElementException, InvalidElementStateException, WebDriverException) as e:
        from cfme.web_ui import cfme_exception as cfme_exc  # To prevent circular imports
        # First check - if jquery is not found, there can be also another reason why this happened
        # so do not put the next branches in elif
        if isinstance(e, WebDriverException) and "jQuery" in str(e):
            # UI failed in some way, try recycling the browser
            logger.exception(
                "UI failed in some way, jQuery not found, (probably) recycling the browser.")
            recycle = True
        # If the page is blocked, then recycle...
        if (
                is_displayed("//div[@id='blocker_div' or @id='notification']", _no_deeper=True)
                or is_displayed(".modal-backdrop.fade.in", _no_deeper=True)):
            logger.warning("Page was blocked with blocker div, recycling.")
            recycle = True
        elif cfme_exc.is_cfme_exception():
            logger.exception("CFME Exception before force_navigate started!: `{}`".format(
                cfme_exc.cfme_exception_text()
            ))
            recycle = True
        elif is_displayed("//body[./h1 and ./p and ./hr and ./address]", _no_deeper=True):
            # 503 and similar sort of errors
            title = text("//body/h1")
            body = text("//body/p")
            logger.exception("Application error '{}': {}".format(title, body))
            sleep(5)  # Give it a little bit of rest
            recycle = True
        elif is_displayed("//body/div[@class='dialog' and ./h1 and ./p]", _no_deeper=True):
            # Rails exception detection
            logger.exception("Rails exception before force_navigate started!: {}:{} at {}".format(
                text("//body/div[@class='dialog']/h1").encode("utf-8"),
                text("//body/div[@class='dialog']/p").encode("utf-8"),
                current_url()
            ))
            recycle = True
        elif elements("//ul[@id='maintab']/li[@class='inactive']") and not\
                elements("//ul[@id='maintab']/li[@class='active']/ul/li"):
            # If upstream and is the bottom part of menu is not displayed
            logger.exception("Detected glitch from BZ#1112574. HEADSHOT!")
            recycle = True
        else:
            logger.error("Could not determine the reason for failing the navigation. " +
                " Reraising.  Exception: %s" % str(e))
            logger.debug(store.current_appliance.ssh_client.run_command(
                'service evmserverd status').output)
            raise

    if recycle:
        browser().quit()  # login.current_user() will be retained for next login
        logger.debug('browser killed on try %d' % _tries)
        # If given a "start" nav destination, it won't be valid after quitting the browser
        kwargs.pop("start", None)
        force_navigate(page_name, _tries, *args, **kwargs)
Exemple #15
0
    def do_nav(self, _tries=0):
        # Set this to True in the handlers below to trigger a browser restart
        recycle = False

        # Set this to True in handlers to restart evmserverd on the appliance
        # Includes recycling so you don't need to specify recycle = False
        restart_evmserverd = False

        current_user = store.user
        from cfme import login

        def _login_func():
            if not current_user:  # default to admin user
                login.login_admin()
            else:  # we recycled and want to log back in
                login.login(store.user)

        try:
            try:
                # What we'd like to happen...
                _login_func()
            except WebDriverException as e:
                if "jquery" not in str(e).lower():
                    raise  # Something unknown happened
                logger.info("Seems we got a non-CFME page (blank "
                    "or screwed up) so killing the browser")
                quit()
                ensure_browser_open()
                # And try it again
                _login_func()
                # If this failed, no help with that :/

            self.step()
        except (KeyboardInterrupt, ValueError):
            # KeyboardInterrupt: Don't block this while navigating
            # ValueError: ui_navigate.go_to can't handle this page, give up
            raise
        except UnexpectedAlertPresentException:
            if _tries == 1:
                # There was an alert, accept it and try again
                handle_alert(wait=0)
                self.go(_tries)
            else:
                # There was still an alert when we tried again, shoot the browser in the head
                logger.debug('Unxpected alert, recycling browser')
                recycle = True
        except (ErrorInResponseException, InvalidSwitchToTargetException):
            # Unable to switch to the browser at all, need to recycle
            logger.info('Invalid browser state, recycling browser')
            recycle = True
        except exceptions.CFMEExceptionOccured as e:
            # We hit a Rails exception
            logger.info('CFME Exception occured')
            logger.exception(e)
            recycle = True
        except exceptions.CannotContinueWithNavigation as e:
            # The some of the navigation steps cannot succeed
            logger.info('Cannot continue with navigation due to: {}; '
                'Recycling browser'.format(str(e)))
            recycle = True
        except (NoSuchElementException, InvalidElementStateException, WebDriverException,
                StaleElementReferenceException) as e:
            from cfme.web_ui import cfme_exception as cfme_exc  # To prevent circular imports
            # First check - if jquery is not found, there can be also another
            # reason why this happened so do not put the next branches in elif
            if isinstance(e, WebDriverException) and "jQuery" in str(e):
                # UI failed in some way, try recycling the browser
                logger.exception(
                    "UI failed in some way, jQuery not found, (probably) recycling the browser.")
                recycle = True
            # If the page is blocked, then recycle...
            if (
                    is_displayed("//div[@id='blocker_div' or @id='notification']", _no_deeper=True)
                    or is_displayed(".modal-backdrop.fade.in", _no_deeper=True)):
                logger.warning("Page was blocked with blocker div, recycling.")
                recycle = True
            elif cfme_exc.is_cfme_exception():
                logger.exception("CFME Exception before force_navigate started!: {}".format(
                    cfme_exc.cfme_exception_text()))
                recycle = True
            elif is_displayed("//body/h1[normalize-space(.)='Proxy Error']"):
                # 502
                logger.exception("Proxy error detected. Killing browser and restarting evmserverd.")
                req = elements("/html/body/p[1]//a")
                req = text(req[0]) if req else "No request stated"
                reason = elements("/html/body/p[2]/strong")
                reason = text(reason[0]) if reason else "No reason stated"
                logger.info("Proxy error: {} / {}".format(req, reason))
                restart_evmserverd = True
            elif is_displayed("//body[./h1 and ./p and ./hr and ./address]", _no_deeper=True):
                # 503 and similar sort of errors
                title = text("//body/h1")
                body = text("//body/p")
                logger.exception("Application error {}: {}".format(title, body))
                sleep(5)  # Give it a little bit of rest
                recycle = True
            elif is_displayed("//body/div[@class='dialog' and ./h1 and ./p]", _no_deeper=True):
                # Rails exception detection
                logger.exception("Rails exception before force_navigate started!: %s:%s at %s",
                    text("//body/div[@class='dialog']/h1").encode("utf-8"),
                    text("//body/div[@class='dialog']/p").encode("utf-8"),
                    browser().current_url
                )
                recycle = True
            elif elements("//ul[@id='maintab']/li[@class='inactive']") and not\
                    elements("//ul[@id='maintab']/li[@class='active']/ul/li"):
                # If upstream and is the bottom part of menu is not displayed
                logger.exception("Detected glitch from BZ#1112574. HEADSHOT!")
                recycle = True
            elif not login.logged_in():
                # Session timeout or whatever like that, login screen appears.
                logger.exception("Looks like we are logged out. Try again.")
                recycle = True
            else:
                logger.error("Could not determine the reason for failing the navigation. " +
                    " Reraising.  Exception: {}".format(str(e)))
                logger.debug(store.current_appliance.ssh_client.run_command(
                    'service evmserverd status').output)
                raise

        if restart_evmserverd:
            logger.info("evmserverd restart requested")
            store.current_appliance.restart_evm_service()
            store.current_appliance.wait_for_web_ui()

        if recycle or restart_evmserverd:
            browser().quit()  # login.current_user() will be retained for next login
            logger.debug('browser killed on try {}'.format(_tries))
            # If given a "start" nav destination, it won't be valid after quitting the browser
            self.go(_tries)
Exemple #16
0
    def do_nav(self, _tries=0, *args, **kwargs):
        # Set this to True in the handlers below to trigger a browser restart
        recycle = False

        # Set this to True in handlers to restart evmserverd on the appliance
        # Includes recycling so you don't need to specify recycle = False
        restart_evmserverd = False

        from cfme import login

        br = self.appliance.browser

        try:
            self.step(*args, **kwargs)
        except (KeyboardInterrupt, ValueError):
            # KeyboardInterrupt: Don't block this while navigating
            raise
        except UnexpectedAlertPresentException:
            if _tries == 1:
                # There was an alert, accept it and try again
                br.widgetastic.handle_alert(wait=0)
                self.go(_tries)
            else:
                # There was still an alert when we tried again, shoot the browser in the head
                logger.debug('Unxpected alert, recycling browser')
                recycle = True
        except (ErrorInResponseException, InvalidSwitchToTargetException):
            # Unable to switch to the browser at all, need to recycle
            logger.info('Invalid browser state, recycling browser')
            recycle = True
        except exceptions.CFMEExceptionOccured as e:
            # We hit a Rails exception
            logger.info('CFME Exception occured')
            logger.exception(e)
            recycle = True
        except exceptions.CannotContinueWithNavigation as e:
            # The some of the navigation steps cannot succeed
            logger.info('Cannot continue with navigation due to: {}; '
                'Recycling browser'.format(str(e)))
            recycle = True
        except (NoSuchElementException, InvalidElementStateException, WebDriverException,
                StaleElementReferenceException) as e:
            from cfme.web_ui import cfme_exception as cfme_exc  # To prevent circular imports
            # First check - if jquery is not found, there can be also another
            # reason why this happened so do not put the next branches in elif
            if isinstance(e, WebDriverException) and "jQuery" in str(e):
                # UI failed in some way, try recycling the browser
                logger.exception(
                    "UI failed in some way, jQuery not found, (probably) recycling the browser.")
                recycle = True
            # If the page is blocked, then recycle...
            if (
                    br.widgetastic.is_displayed("//div[@id='blocker_div' or @id='notification']") or
                    br.widgetastic.is_displayed(".modal-backdrop.fade.in")):
                logger.warning("Page was blocked with blocker div, recycling.")
                recycle = True
            elif cfme_exc.is_cfme_exception():
                logger.exception("CFME Exception before force navigate started!: {}".format(
                    cfme_exc.cfme_exception_text()))
                recycle = True
            elif br.widgetastic.is_displayed("//body/h1[normalize-space(.)='Proxy Error']"):
                # 502
                logger.exception("Proxy error detected. Killing browser and restarting evmserverd.")
                req = br.widgetastic.elements("/html/body/p[1]//a")
                req = br.widgetastic.text(req[0]) if req else "No request stated"
                reason = br.widgetastic.elements("/html/body/p[2]/strong")
                reason = br.widgetastic.text(reason[0]) if reason else "No reason stated"
                logger.info("Proxy error: {} / {}".format(req, reason))
                restart_evmserverd = True
            elif br.widgetastic.is_displayed("//body[./h1 and ./p and ./hr and ./address]"):
                # 503 and similar sort of errors
                title = br.widgetastic.text("//body/h1")
                body = br.widgetastic.text("//body/p")
                logger.exception("Application error {}: {}".format(title, body))
                sleep(5)  # Give it a little bit of rest
                recycle = True
            elif br.widgetastic.is_displayed("//body/div[@class='dialog' and ./h1 and ./p]"):
                # Rails exception detection
                logger.exception("Rails exception before force navigate started!: %r:%r at %r",
                    br.widgetastic.text("//body/div[@class='dialog']/h1"),
                    br.widgetastic.text("//body/div[@class='dialog']/p"),
                    getattr(manager.browser, 'current_url', "error://dead-browser")
                )
                recycle = True
            elif br.widgetastic.elements("//ul[@id='maintab']/li[@class='inactive']") and not\
                    br.widgetastic.elements("//ul[@id='maintab']/li[@class='active']/ul/li"):
                # If upstream and is the bottom part of menu is not displayed
                logger.exception("Detected glitch from BZ#1112574. HEADSHOT!")
                recycle = True
            elif not login.logged_in():
                # Session timeout or whatever like that, login screen appears.
                logger.exception("Looks like we are logged out. Try again.")
                recycle = True
            else:
                logger.error("Could not determine the reason for failing the navigation. " +
                    " Reraising.  Exception: {}".format(str(e)))
                logger.debug(store.current_appliance.ssh_client.run_command(
                    'service evmserverd status').output)
                raise

        if restart_evmserverd:
            logger.info("evmserverd restart requested")
            self.appliance.restart_evm_service()
            self.appliance.wait_for_web_ui()

        if recycle or restart_evmserverd:
            self.appliance.browser.quit_browser()
            logger.debug('browser killed on try {}'.format(_tries))
            # If given a "start" nav destination, it won't be valid after quitting the browser
            self.go(_tries)