Merge "Add Grafana dashboards UI test"
This commit is contained in:
commit
6011c5560f
@ -24,7 +24,11 @@ for the detailed procedure).
|
||||
|
||||
. $VENV_PATH/bin/activate
|
||||
|
||||
4. Run the tests:
|
||||
4. If you want to run UI test in headless mode, install these packages:
|
||||
|
||||
sudo apt-get install xvfb firefox -y
|
||||
|
||||
5. Run the tests:
|
||||
|
||||
./utils/jenkins/system_tests.sh -k -K -j fuelweb_test -t test -w $(pwd) -o --group=<your_test_group_to_run>
|
||||
|
||||
|
@ -18,3 +18,9 @@ Destructive
|
||||
|
||||
.. automodule:: stacklight_tests.influxdb_grafana.test_destructive
|
||||
:members:
|
||||
|
||||
Functional
|
||||
==========
|
||||
|
||||
.. automodule:: stacklight_tests.influxdb_grafana.test_functional
|
||||
:members:
|
||||
|
@ -16,3 +16,9 @@ export LMA_COLLECTOR_PLUGIN_PATH=$HOME/plugins/lma_collector-0.9-0.9.0-1.noarch.
|
||||
export LMA_INFRA_ALERTING_PLUGIN_PATH=$HOME/plugins/lma_infrastructure_alerting-0.9-0.9.0-1.noarch.rpm
|
||||
export ELASTICSEARCH_KIBANA_PLUGIN_PATH=$HOME/plugins/elasticsearch_kibana-0.9-0.9.0-1.noarch.rpm
|
||||
export INFLUXDB_GRAFANA_PLUGIN_PATH=$HOME/plugins/influxdb_grafana-0.9-0.9.0-1.noarch.rpm
|
||||
|
||||
# UI Tests settings
|
||||
export SELENIUM_HEADLESS=True
|
||||
export SELENIUM_MAXIMIZE=True
|
||||
export IMPLICIT_WAIT=5
|
||||
# export DRIVER_PROXY=localhost:8080
|
||||
|
@ -3,3 +3,4 @@ requests
|
||||
selenium
|
||||
six
|
||||
tox
|
||||
xvfbwrapper
|
||||
|
0
stacklight_tests/helpers/ui/__init__.py
Normal file
0
stacklight_tests/helpers/ui/__init__.py
Normal file
163
stacklight_tests/helpers/ui/base_pages.py
Normal file
163
stacklight_tests/helpers/ui/base_pages.py
Normal file
@ -0,0 +1,163 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import contextlib
|
||||
|
||||
from proboscis import asserts
|
||||
import selenium.common.exceptions as Exceptions
|
||||
from selenium.webdriver.remote import webelement
|
||||
import selenium.webdriver.support.ui as Support
|
||||
|
||||
|
||||
class BaseWebObject(object):
|
||||
def __init__(self, driver, timeout=5):
|
||||
self.driver = driver
|
||||
self.timeout = timeout
|
||||
|
||||
def _turn_off_implicit_wait(self):
|
||||
self.driver.implicitly_wait(0)
|
||||
|
||||
def _turn_on_implicit_wait(self):
|
||||
self.driver.implicitly_wait(self.timeout)
|
||||
|
||||
@contextlib.contextmanager
|
||||
def waits_disabled(self):
|
||||
try:
|
||||
self._turn_off_implicit_wait()
|
||||
yield
|
||||
finally:
|
||||
self._turn_on_implicit_wait()
|
||||
|
||||
def _is_element_present(self, *locator):
|
||||
with self.waits_disabled():
|
||||
try:
|
||||
self._get_element(*locator)
|
||||
return True
|
||||
except Exceptions.NoSuchElementException:
|
||||
return False
|
||||
|
||||
def _is_element_visible(self, *locator):
|
||||
try:
|
||||
return self._get_element(*locator).is_displayed()
|
||||
except (Exceptions.NoSuchElementException,
|
||||
Exceptions.ElementNotVisibleException):
|
||||
return False
|
||||
|
||||
def _is_element_displayed(self, element):
|
||||
if element is None:
|
||||
return False
|
||||
try:
|
||||
if isinstance(element, webelement.WebElement):
|
||||
return element.is_displayed()
|
||||
else:
|
||||
return element.src_elem.is_displayed()
|
||||
except (Exceptions.ElementNotVisibleException,
|
||||
Exceptions.StaleElementReferenceException):
|
||||
return False
|
||||
|
||||
def _is_text_visible(self, element, text, strict=True):
|
||||
if not hasattr(element, 'text'):
|
||||
return False
|
||||
if strict:
|
||||
return element.text == text
|
||||
else:
|
||||
return text in element.text
|
||||
|
||||
def _get_element(self, *locator):
|
||||
return self.driver.find_element(*locator)
|
||||
|
||||
def _get_elements(self, *locator):
|
||||
return self.driver.find_elements(*locator)
|
||||
|
||||
def _fill_field_element(self, data, field_element):
|
||||
field_element.clear()
|
||||
field_element.send_keys(data)
|
||||
return field_element
|
||||
|
||||
def _select_dropdown(self, value, element):
|
||||
select = Support.Select(element)
|
||||
select.select_by_visible_text(value)
|
||||
|
||||
def _select_dropdown_by_value(self, value, element):
|
||||
select = Support.Select(element)
|
||||
select.select_by_value(value)
|
||||
|
||||
def _get_dropdown_options(self, element):
|
||||
select = Support.Select(element)
|
||||
return select.options
|
||||
|
||||
|
||||
class PageObject(BaseWebObject):
|
||||
"""Base class for page objects."""
|
||||
|
||||
PARTIAL_LOGIN_URL = 'login'
|
||||
|
||||
def __init__(self, driver):
|
||||
"""Constructor."""
|
||||
super(PageObject, self).__init__(driver)
|
||||
self._page_title = None
|
||||
|
||||
@property
|
||||
def page_title(self):
|
||||
return self.driver.title
|
||||
|
||||
def is_the_current_page(self, do_assert=False):
|
||||
found_expected_title = self.page_title.startswith(self._page_title)
|
||||
if do_assert:
|
||||
asserts.assert_true(
|
||||
found_expected_title,
|
||||
"Expected to find %s in page title, instead found: %s"
|
||||
% (self._page_title, self.page_title))
|
||||
return found_expected_title
|
||||
|
||||
def get_current_page_url(self):
|
||||
return self.driver.current_url
|
||||
|
||||
def close_window(self):
|
||||
return self.driver.close()
|
||||
|
||||
def is_nth_window_opened(self, n):
|
||||
return len(self.driver.window_handles) == n
|
||||
|
||||
def switch_window(self, name=None, index=None):
|
||||
"""Switches focus between the webdriver windows.
|
||||
Args:
|
||||
- name: The name of the window to switch to.
|
||||
- index: The index of the window handle to switch to.
|
||||
If the method is called without arguments it switches to the
|
||||
last window in the driver window_handles list.
|
||||
In case only one window exists nothing effectively happens.
|
||||
Usage:
|
||||
page.switch_window(name='_new')
|
||||
page.switch_window(index=2)
|
||||
page.switch_window()
|
||||
"""
|
||||
|
||||
if name is not None and index is not None:
|
||||
raise ValueError("switch_window receives the window's name or "
|
||||
"the window's index, not both.")
|
||||
if name is not None:
|
||||
self.driver.switch_to.window(name)
|
||||
elif index is not None:
|
||||
self.driver.switch_to.window(
|
||||
self.driver.window_handles[index])
|
||||
else:
|
||||
self.driver.switch_to.window(self.driver.window_handles[-1])
|
||||
|
||||
def go_to_previous_page(self):
|
||||
self.driver.back()
|
||||
|
||||
def go_to_next_page(self):
|
||||
self.driver.forward()
|
||||
|
||||
def refresh_page(self):
|
||||
self.driver.refresh()
|
35
stacklight_tests/helpers/ui/ui_settings.py
Normal file
35
stacklight_tests/helpers/ui/ui_settings.py
Normal file
@ -0,0 +1,35 @@
|
||||
# Copyright 2016 Mirantis, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import os
|
||||
|
||||
|
||||
# Use a virtual display server for running the tests headless or not
|
||||
headless_mode = os.environ.get('SELENIUM_HEADLESS', False)
|
||||
|
||||
# The browser session will be started with given proxy,
|
||||
# can be useful if you try to start UI tests on developer machine,
|
||||
# but environment is on remote server
|
||||
proxy_address = os.environ.get('DRIVER_PROXY', None)
|
||||
|
||||
# Maximize the current window that webdriver is using or not
|
||||
maximize_window = os.environ.get('SELENIUM_MAXIMIZE', True)
|
||||
|
||||
# Sets a sticky timeout to implicitly wait for an element to be found,
|
||||
# or a command to complete.
|
||||
implicit_wait = os.environ.get('IMPLICIT_WAIT', 5)
|
||||
|
||||
# Set the amount of time to wait for a page load to complete
|
||||
# before throwing an error.
|
||||
page_timeout = os.environ.get('PAGE_TIMEOUT', 15)
|
@ -12,21 +12,71 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from proboscis import asserts
|
||||
import contextlib
|
||||
import socket
|
||||
|
||||
from selenium import webdriver
|
||||
from selenium.webdriver.common.by import By
|
||||
from selenium.webdriver.support import expected_conditions as EC
|
||||
from selenium.webdriver.support.ui import WebDriverWait
|
||||
from selenium.webdriver.common import by
|
||||
from selenium.webdriver.common import proxy
|
||||
import xvfbwrapper
|
||||
|
||||
from stacklight_tests.helpers.ui import ui_settings
|
||||
|
||||
|
||||
def get_driver(ip, anchor, title):
|
||||
driver = webdriver.Firefox()
|
||||
driver.get(ip)
|
||||
WebDriverWait(driver, 120).until(
|
||||
EC.presence_of_element_located((By.XPATH, anchor)))
|
||||
asserts.assert_equal(True, title in driver.title,
|
||||
"Title {0} was not found in {1}!".format(
|
||||
title, driver.title))
|
||||
@contextlib.contextmanager
|
||||
def ui_driver(url, wait_element, title):
|
||||
vdisplay = None
|
||||
# Start a virtual display server for running the tests headless.
|
||||
if ui_settings.headless_mode:
|
||||
vdisplay = xvfbwrapper.Xvfb(width=1920, height=1080)
|
||||
args = []
|
||||
|
||||
# workaround for memory leak in Xvfb taken from:
|
||||
# http://blog.jeffterrace.com/2012/07/xvfb-memory-leak-workaround.html
|
||||
args.append("-noreset")
|
||||
|
||||
# disables X access control
|
||||
args.append("-ac")
|
||||
|
||||
if hasattr(vdisplay, 'extra_xvfb_args'):
|
||||
# xvfbwrapper 0.2.8 or newer
|
||||
vdisplay.extra_xvfb_args.extend(args)
|
||||
else:
|
||||
vdisplay.xvfb_cmd.extend(args)
|
||||
vdisplay.start()
|
||||
driver = get_driver(url, wait_element, title)
|
||||
try:
|
||||
yield driver
|
||||
finally:
|
||||
driver.quit()
|
||||
if vdisplay is not None:
|
||||
vdisplay.stop()
|
||||
|
||||
|
||||
def get_driver(url, anchor, title, by_selector_type=by.By.XPATH):
|
||||
proxy_address = ui_settings.proxy_address
|
||||
# Increase the default Python socket timeout from nothing
|
||||
# to something that will cope with slow webdriver startup times.
|
||||
# This *just* affects the communication between this test process
|
||||
# and the webdriver.
|
||||
socket.setdefaulttimeout(60)
|
||||
# Start the Selenium webdriver and setup configuration.
|
||||
proxy_ex = None
|
||||
if proxy_address is not None:
|
||||
proxy_ex = proxy.Proxy(
|
||||
{
|
||||
'proxyType': proxy.ProxyType.MANUAL,
|
||||
'socksProxy': proxy_address,
|
||||
}
|
||||
)
|
||||
driver = webdriver.Firefox(proxy=proxy_ex)
|
||||
if ui_settings.maximize_window:
|
||||
driver.maximize_window()
|
||||
driver.implicitly_wait(ui_settings.implicit_wait)
|
||||
driver.set_page_load_timeout(ui_settings.page_timeout)
|
||||
driver.get(url)
|
||||
driver.find_element(by_selector_type, anchor)
|
||||
assert title in driver.title
|
||||
return driver
|
||||
|
||||
|
||||
|
@ -18,6 +18,7 @@ from proboscis import asserts
|
||||
import requests
|
||||
|
||||
from stacklight_tests import base_test
|
||||
from stacklight_tests.influxdb_grafana.grafana_ui import api as ui_api
|
||||
from stacklight_tests.influxdb_grafana import plugin_settings
|
||||
|
||||
|
||||
@ -137,3 +138,7 @@ class InfluxdbPluginApi(base_test.PluginApi):
|
||||
def check_uninstall_failure(self):
|
||||
return self.helpers.check_plugin_cannot_be_uninstalled(
|
||||
self.settings.name, self.settings.version)
|
||||
|
||||
def check_grafana_dashboards(self):
|
||||
grafana_url = self.get_grafana_url()
|
||||
ui_api.check_grafana_dashboards(grafana_url)
|
||||
|
48
stacklight_tests/influxdb_grafana/grafana_ui/api.py
Normal file
48
stacklight_tests/influxdb_grafana/grafana_ui/api.py
Normal file
@ -0,0 +1,48 @@
|
||||
# Copyright 2016 Mirantis, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from proboscis import asserts
|
||||
|
||||
from stacklight_tests.helpers.ui_tester import ui_driver
|
||||
from stacklight_tests.influxdb_grafana.grafana_ui import pages
|
||||
|
||||
|
||||
def check_grafana_dashboards(grafana_url):
|
||||
|
||||
login_key_xpath = '/html/body/div/div[2]/div/div/div[2]/form/div[2]/button'
|
||||
|
||||
with ui_driver(grafana_url, login_key_xpath, "Grafana") as driver:
|
||||
login_page = pages.LoginPage(driver)
|
||||
login_page.is_login_page()
|
||||
home_page = login_page.login("grafana", "grafanapass")
|
||||
home_page.is_main_page()
|
||||
dashboard_names = {
|
||||
"Apache", "Cinder", "Elasticsearch", "Glance", "HAProxy", "Heat",
|
||||
"Hypervisor", "InfluxDB", "Keystone", "LMA self-monitoring",
|
||||
"Memcached", "MySQL", "Neutron", "Nova", "RabbitMQ", "System"
|
||||
}
|
||||
dashboard_names = {
|
||||
panel_name.lower() for panel_name in dashboard_names}
|
||||
available_dashboards_names = {
|
||||
dashboard.text.lower() for dashboard in home_page.dashboards}
|
||||
msg = ("There is not enough panels in available panels, "
|
||||
"panels that are not presented: {}")
|
||||
# NOTE(rpromyshlennikov): should there be 'elasticsearch'
|
||||
# and 'influxdb' dashboards?
|
||||
asserts.assert_true(
|
||||
dashboard_names.issubset(available_dashboards_names),
|
||||
msg.format(dashboard_names - available_dashboards_names))
|
||||
for name in available_dashboards_names:
|
||||
dashboard_page = home_page.open_dashboard(name)
|
||||
dashboard_page.get_back_to_home()
|
127
stacklight_tests/influxdb_grafana/grafana_ui/pages.py
Normal file
127
stacklight_tests/influxdb_grafana/grafana_ui/pages.py
Normal file
@ -0,0 +1,127 @@
|
||||
from selenium.webdriver.common import by
|
||||
from selenium.webdriver.common import keys
|
||||
|
||||
|
||||
from stacklight_tests.helpers.ui import base_pages
|
||||
|
||||
|
||||
class DashboardPage(base_pages.PageObject):
|
||||
_submenu_controls_locator = (
|
||||
by.By.CLASS_NAME,
|
||||
"submenu-controls"
|
||||
)
|
||||
|
||||
def __init__(self, driver, dashboard_name):
|
||||
super(DashboardPage, self).__init__(driver)
|
||||
self._page_title = "Grafana - {}".format(dashboard_name)
|
||||
|
||||
def is_dashboards_page(self):
|
||||
return (self.is_the_current_page() and
|
||||
self._is_element_visible(*self._submenu_controls_locator))
|
||||
|
||||
def get_back_to_home(self):
|
||||
self.go_to_previous_page()
|
||||
return MainPage(self.driver)
|
||||
|
||||
|
||||
class MainPage(base_pages.PageObject):
|
||||
_dropdown_menu_locator = (
|
||||
by.By.CLASS_NAME,
|
||||
'top-nav-dashboards-btn')
|
||||
|
||||
_dashboards_list_locator = (
|
||||
by.By.CLASS_NAME,
|
||||
'search-results-container'
|
||||
)
|
||||
|
||||
_dashboard_locator = (by.By.CLASS_NAME,
|
||||
"search-item-dash-db")
|
||||
|
||||
def __init__(self, driver):
|
||||
super(MainPage, self).__init__(driver)
|
||||
self._page_title = "Grafana - Home"
|
||||
|
||||
def is_main_page(self):
|
||||
return (self.is_the_current_page() and
|
||||
self._is_element_visible(*self._dropdown_menu_locator))
|
||||
|
||||
@property
|
||||
def dropdown_menu(self):
|
||||
return self._get_element(*self._dropdown_menu_locator)
|
||||
|
||||
@property
|
||||
def dashboards_list(self):
|
||||
self.open_dropdown_menu()
|
||||
return self._get_element(*self._dashboards_list_locator)
|
||||
|
||||
@property
|
||||
def dashboards(self):
|
||||
return self.dashboards_list.find_elements(*self._dashboard_locator)
|
||||
|
||||
def is_dropdown_menu_opened(self):
|
||||
return self._is_element_present(*self._dashboards_list_locator)
|
||||
|
||||
def open_dropdown_menu(self):
|
||||
if not self.is_dropdown_menu_opened():
|
||||
self.dropdown_menu.click()
|
||||
|
||||
def open_dashboard(self, dashboard_name):
|
||||
dashboards_mapping = {dashboard.text.lower(): dashboard
|
||||
for dashboard in self.dashboards}
|
||||
dashboards_mapping[dashboard_name.lower()].click()
|
||||
dashboard_page = DashboardPage(self.driver, dashboard_name)
|
||||
dashboard_page.is_dashboards_page()
|
||||
return dashboard_page
|
||||
|
||||
|
||||
class LoginPage(base_pages.PageObject):
|
||||
_login_username_field_locator = (by.By.NAME, 'username')
|
||||
_login_password_field_locator = (by.By.NAME, 'password')
|
||||
_login_submit_button_locator = (
|
||||
by.By.CLASS_NAME,
|
||||
'login-submit-button-row')
|
||||
|
||||
def __init__(self, driver):
|
||||
super(LoginPage, self).__init__(driver)
|
||||
self._page_title = "Grafana"
|
||||
|
||||
def is_login_page(self):
|
||||
return (self.is_the_current_page() and
|
||||
self._is_element_visible(*self._login_submit_button_locator))
|
||||
|
||||
@property
|
||||
def username(self):
|
||||
return self._get_element(*self._login_username_field_locator)
|
||||
|
||||
@property
|
||||
def password(self):
|
||||
return self._get_element(*self._login_password_field_locator)
|
||||
|
||||
@property
|
||||
def login_button(self):
|
||||
return self._get_element(*self._login_submit_button_locator)
|
||||
|
||||
def _click_on_login_button(self):
|
||||
self.login_button.click()
|
||||
|
||||
def _press_enter_on_login_button(self):
|
||||
self.login_button.send_keys(keys.Keys.RETURN)
|
||||
|
||||
def login(self, user, password):
|
||||
return self.login_with_mouse_click(user, password)
|
||||
|
||||
def login_with_mouse_click(self, user, password):
|
||||
return self._do_login(user, password, self._click_on_login_button)
|
||||
|
||||
def login_with_enter_key(self, user, password):
|
||||
return self._do_login(user, password,
|
||||
self._press_enter_on_login_button)
|
||||
|
||||
def _do_login(self, user, password, login_method):
|
||||
return self.login_as_user(user, password, login_method)
|
||||
|
||||
def login_as_user(self, user, password, login_method):
|
||||
self._fill_field_element(user, self.username)
|
||||
self._fill_field_element(password, self.password)
|
||||
login_method()
|
||||
return MainPage(self.driver)
|
@ -39,7 +39,6 @@ class TestDestructiveInfluxdbPlugin(api.InfluxdbPluginApi):
|
||||
6. Check that the cluster's state is okay
|
||||
|
||||
Duration 40m
|
||||
Snapshot check_cluster_outage_influxdb_grafana
|
||||
"""
|
||||
self.env.revert_snapshot("deploy_ha_influxdb_grafana")
|
||||
|
||||
@ -52,8 +51,6 @@ class TestDestructiveInfluxdbPlugin(api.InfluxdbPluginApi):
|
||||
|
||||
self.helpers.run_ostf()
|
||||
|
||||
self.env.make_snapshot("check_cluster_outage_influxdb_grafana")
|
||||
|
||||
@test(depends_on_groups=["deploy_influxdb_grafana"],
|
||||
groups=["check_disaster_influxdb_grafana", "influxdb_grafana",
|
||||
"destructive", "check_node_outage_influxdb_grafana"])
|
||||
@ -66,11 +63,10 @@ class TestDestructiveInfluxdbPlugin(api.InfluxdbPluginApi):
|
||||
1. Revert the snapshot with 3 deployed nodes
|
||||
2. Simulate network interruption on the InfluxDB/Grafana node
|
||||
3. Wait for at least 30 seconds before recover network availability
|
||||
5. Run OSTF
|
||||
6. Check that plugin is working
|
||||
4. Run OSTF
|
||||
5. Check that plugin is working
|
||||
|
||||
Duration 20m
|
||||
Snapshot check_node_outage_influxdb_grafana
|
||||
"""
|
||||
self.env.revert_snapshot("deploy_influxdb_grafana")
|
||||
|
||||
@ -83,5 +79,3 @@ class TestDestructiveInfluxdbPlugin(api.InfluxdbPluginApi):
|
||||
self.check_plugin_online()
|
||||
|
||||
self.helpers.run_ostf()
|
||||
|
||||
self.env.make_snapshot("check_node_outage_influxdb_grafana")
|
||||
|
64
stacklight_tests/influxdb_grafana/test_functional.py
Normal file
64
stacklight_tests/influxdb_grafana/test_functional.py
Normal file
@ -0,0 +1,64 @@
|
||||
# Copyright 2016 Mirantis, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from fuelweb_test.helpers.decorators import log_snapshot_after_test
|
||||
from proboscis import test
|
||||
|
||||
from stacklight_tests.influxdb_grafana import api
|
||||
|
||||
|
||||
@test(groups=["plugins"])
|
||||
class TestFunctionalInfluxdbPlugin(api.InfluxdbPluginApi):
|
||||
"""Class for functional testing of plugin."""
|
||||
|
||||
@test(depends_on_groups=["deploy_influxdb_grafana"],
|
||||
groups=["check_display_dashboards_influxdb_grafana",
|
||||
"influxdb_grafana", "functional"])
|
||||
@log_snapshot_after_test
|
||||
def check_display_dashboards_influxdb_grafana(self):
|
||||
"""Verify that the dashboards show up in the Grafana UI.
|
||||
|
||||
Scenario:
|
||||
1. Revert snapshot with 9 deployed nodes in HA configuration
|
||||
2. Open the Grafana URL (
|
||||
open the "Dashboard" tab and click the "Grafana" link)
|
||||
3. Sign-in using the credentials provided
|
||||
during the configuration of the environment
|
||||
4. Go to the Main dashboard and verify that everything is ok
|
||||
5. Repeat the previous step for the following dashboards:
|
||||
* Apache
|
||||
* Cinder
|
||||
* Elasticsearch
|
||||
* Glance
|
||||
* HAProxy
|
||||
* Heat
|
||||
* Hypervisor
|
||||
* InfluxDB
|
||||
* Keystone
|
||||
* LMA self-monitoring
|
||||
* Memcached
|
||||
* MySQL
|
||||
* Neutron
|
||||
* Nova
|
||||
* RabbitMQ
|
||||
* System
|
||||
|
||||
Duration 40m
|
||||
"""
|
||||
|
||||
self.env.revert_snapshot("deploy_influxdb_grafana_plugin")
|
||||
|
||||
self.check_plugin_online()
|
||||
|
||||
self.check_grafana_dashboards()
|
@ -66,8 +66,6 @@ class TestNodesInfluxdbPlugin(api.InfluxdbPluginApi):
|
||||
|
||||
self.helpers.run_ostf(should_fail=1)
|
||||
|
||||
self.env.make_snapshot("add_remove_controller_influxdb_grafana")
|
||||
|
||||
@test(depends_on_groups=["deploy_ha_influxdb_grafana"],
|
||||
groups=["check_scaling_influxdb_grafana", "scaling",
|
||||
"influxdb_grafana", "system",
|
||||
@ -112,8 +110,6 @@ class TestNodesInfluxdbPlugin(api.InfluxdbPluginApi):
|
||||
|
||||
self.helpers.run_ostf(should_fail=1)
|
||||
|
||||
self.env.make_snapshot("add_remove_compute_influxdb_grafana")
|
||||
|
||||
@test(depends_on_groups=["deploy_ha_influxdb_grafana"],
|
||||
groups=["check_scaling_influxdb_grafana", "scaling",
|
||||
"influxdb_grafana", "system",
|
||||
@ -162,8 +158,6 @@ class TestNodesInfluxdbPlugin(api.InfluxdbPluginApi):
|
||||
|
||||
self.helpers.run_ostf()
|
||||
|
||||
self.env.make_snapshot("add_remove_influxdb_grafana_node")
|
||||
|
||||
@test(depends_on_groups=["deploy_ha_influxdb_grafana"],
|
||||
groups=["check_failover_influxdb_grafana" "failover",
|
||||
"influxdb_grafana", "system", "destructive",
|
||||
@ -197,5 +191,3 @@ class TestNodesInfluxdbPlugin(api.InfluxdbPluginApi):
|
||||
# TODO(rpromyshlennikov): check no data lost
|
||||
|
||||
self.helpers.run_ostf()
|
||||
|
||||
self.env.make_snapshot("shutdown_influxdb_grafana_node")
|
||||
|
@ -44,6 +44,7 @@ def import_tests():
|
||||
from stacklight_tests.elasticsearch_kibana import test_smoke_bvt # noqa
|
||||
from stacklight_tests.elasticsearch_kibana import test_system # noqa
|
||||
from stacklight_tests.influxdb_grafana import test_destructive # noqa
|
||||
from stacklight_tests.influxdb_grafana import test_functional # noqa
|
||||
from stacklight_tests.influxdb_grafana import test_smoke_bvt # noqa
|
||||
from stacklight_tests.influxdb_grafana import test_system # noqa
|
||||
from stacklight_tests.lma_collector import test_smoke_bvt # noqa
|
||||
|
Loading…
Reference in New Issue
Block a user