175 lines
5.3 KiB
Python
175 lines
5.3 KiB
Python
# Copyright 2015 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 collections import namedtuple
|
|
import logging
|
|
import os
|
|
import random
|
|
|
|
from contextlib import contextmanager
|
|
|
|
from nailgun import consts
|
|
from nailgun.extensions.network_manager import manager
|
|
from nailgun.logger import set_logger
|
|
from nailgun.settings import settings
|
|
from nailgun.statistics import errors
|
|
|
|
|
|
logger = logging.getLogger('statistics')
|
|
|
|
|
|
WhiteListRule = namedtuple(
|
|
'WhiteListItem', ['path', 'map_to_name', 'transform_func'])
|
|
|
|
|
|
def get_mgmt_ip_of_cluster_controller(cluster):
|
|
return manager.NetworkManager.get_ip_by_network_name(
|
|
get_online_controller(cluster),
|
|
consts.NETWORKS.management
|
|
).ip_addr
|
|
|
|
|
|
def get_proxy_for_cluster(cluster):
|
|
proxy_host = get_online_controller(cluster).ip
|
|
proxy_port = settings.OPENSTACK_INFO_COLLECTOR_PROXY_PORT
|
|
proxy = "http://{0}:{1}".format(proxy_host, proxy_port)
|
|
|
|
return proxy
|
|
|
|
|
|
def get_online_controller(cluster):
|
|
online_controllers = filter(
|
|
lambda node: ("controller" in node.roles and node.online is True),
|
|
cluster.nodes
|
|
)
|
|
|
|
if not online_controllers:
|
|
raise errors.NoOnlineControllers(
|
|
"No online controllers could be found for cluster with id {0}"
|
|
.format(cluster.id)
|
|
)
|
|
|
|
controller = online_controllers[0]
|
|
|
|
return controller
|
|
|
|
|
|
def get_attr_value(path, func, attrs):
|
|
"""Gets attribute value from 'attrs' by specified path
|
|
|
|
In case of nested list - list of found values will be returned
|
|
|
|
:param path: list of keys for accessing the attribute value
|
|
:param func: if not None - will be applied to the value
|
|
:param attrs: attributes data
|
|
:return: found value(s)
|
|
"""
|
|
for idx, p in enumerate(path):
|
|
if isinstance(attrs, (tuple, list)):
|
|
result_list = []
|
|
for cur_attr in attrs:
|
|
try:
|
|
value = get_attr_value(path[idx:], func, cur_attr)
|
|
result_list.append(value)
|
|
except (KeyError, TypeError):
|
|
pass
|
|
return result_list
|
|
else:
|
|
attrs = attrs[p]
|
|
if func is not None:
|
|
attrs = func(attrs)
|
|
return attrs
|
|
|
|
|
|
def get_nested_attr(obj, attr_path):
|
|
# prevent from error in case of empty list and
|
|
# None object
|
|
if not all([obj, attr_path]):
|
|
return None
|
|
|
|
attr_name = attr_path[0]
|
|
attr_value = getattr(obj, attr_name, None)
|
|
|
|
# stop recursion as we already are on last level of attributes nesting
|
|
if len(attr_path) == 1:
|
|
return attr_value
|
|
|
|
return get_nested_attr(attr_value, attr_path[1:])
|
|
|
|
|
|
@contextmanager
|
|
def set_proxy(proxy):
|
|
"""Replace http_proxy environment var for the scope of context execution
|
|
|
|
After exit from context old proxy value (if any) is restored
|
|
|
|
:param proxy: - proxy url
|
|
"""
|
|
variable_values = {
|
|
'http_proxy': os.environ.get('http_proxy'),
|
|
'https_proxy': os.environ.get('https_proxy')
|
|
}
|
|
for variable_name, variable_value in variable_values.items():
|
|
if variable_value:
|
|
logger.warning("{0} variable is already set with "
|
|
"value: {1}. Changing to {2}. Old value "
|
|
"will be restored after exit from script's "
|
|
"execution context"
|
|
.format(variable_name, variable_value, proxy))
|
|
os.environ[variable_name] = proxy
|
|
|
|
try:
|
|
yield
|
|
finally:
|
|
for variable_name, variable_value in variable_values.items():
|
|
if variable_value:
|
|
logger.info("Restoring old value for http_proxy")
|
|
os.environ[variable_name] = variable_value
|
|
else:
|
|
logger.info("Deleting set {0} environment variable"
|
|
.format(variable_name))
|
|
del os.environ[variable_name]
|
|
|
|
|
|
def dithered(medium, interval=(0.9, 1.1)):
|
|
return random.randint(int(medium * interval[0]), int(medium * interval[1]))
|
|
|
|
|
|
def get_version_info(cluster):
|
|
"""Returns current Fuel and OpenStack version info
|
|
|
|
:param cluster: cluster
|
|
:type cluster: nailgun.db.sqlalchemy.models.Cluster
|
|
:return: dict with version info or None
|
|
"""
|
|
try:
|
|
return {
|
|
'fuel_version': cluster.fuel_version,
|
|
'release_version': cluster.release.version,
|
|
'release_name': cluster.release.name,
|
|
'release_os': cluster.release.operating_system,
|
|
'environment_version': cluster.release.environment_version
|
|
}
|
|
except Exception:
|
|
logger.exception("Fetching version info for cluster '%s' failed",
|
|
cluster)
|
|
|
|
|
|
def prepare_logger(logger, file_name):
|
|
handler = logging.FileHandler(
|
|
os.path.join(settings.STATS_LOGS_PATH, file_name)
|
|
)
|
|
set_logger(logger, handler)
|
|
|
|
return logger
|