Intergrate with osc-lib based client
Commits integrates monasca-agent with monascaclient, that is currently using osc-lib. That requires some changes in the initialization model of the client. Details: * no need to check if token has expired (underlying library [osc-lib] will request new token if it is about to expire * initializing the client happens once therefore keystone.Keystone instance can be created lazily (it is singleton, so it might happen it is already available) Extra: * marked all variables as private Depends-On: I1712a24739438e2d8331a495f18f357749a633c5 Depends-On: Iec97e50089ed31ae7ad8244b37cec128817871a5 Depends-On: I579f6bcd5975a32af2a255be41c9b6c4043fa1dc Change-Id: Ifee5b88ccb632222310aafb1081ecb9c9d085150
This commit is contained in:
parent
b71fd4bef4
commit
af806edd55
@ -155,18 +155,14 @@ def get_client(**kwargs):
|
||||
|
||||
There are two ways to call this method:
|
||||
|
||||
using existing session object (:py:class:`keystoneauth1.session.Session`
|
||||
using existing session object (:py:class:`keystoneauth1.session.Session`::
|
||||
|
||||
.. code-block:: python
|
||||
>>> s = session.Session(**args)
|
||||
>>> c = get_client(session=s)
|
||||
|
||||
s = session.Session(**args)
|
||||
c = get_client(session=s)
|
||||
initializing new keystone client from credentials::
|
||||
|
||||
initializing new keystone client from credentials
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
c = get_client({'username':'mini-mon', 'password':'test', ...})
|
||||
>>> c = get_client({'username':'mini-mon', 'password':'test', ...})
|
||||
|
||||
:param kwargs: list of arguments passed to method
|
||||
:type kwargs: dict
|
||||
@ -273,9 +269,6 @@ class Keystone(object):
|
||||
|
||||
return ks
|
||||
|
||||
def get_credential_args(self):
|
||||
return self._config
|
||||
|
||||
def get_monasca_url(self):
|
||||
"""Retrieves monasca endpoint url.
|
||||
|
||||
@ -318,3 +311,12 @@ class Keystone(object):
|
||||
|
||||
"""
|
||||
return self._init_client().auth_token
|
||||
|
||||
def get_session(self):
|
||||
"""Returns session of this client.
|
||||
|
||||
:return: session instance
|
||||
:rtype: keystoneauth1.session.Session
|
||||
|
||||
"""
|
||||
return self._init_client().session
|
||||
|
@ -5,11 +5,12 @@ import collections
|
||||
import copy
|
||||
import json
|
||||
import logging
|
||||
import random
|
||||
import time
|
||||
|
||||
from osc_lib import exceptions
|
||||
|
||||
from monascaclient import client
|
||||
|
||||
from monasca_agent.common import keystone
|
||||
import monascaclient.client
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
@ -22,34 +23,31 @@ class MonascaAPI(object):
|
||||
"""
|
||||
|
||||
LOG_INTERVAL = 10 # messages
|
||||
MIN_BACKOFF = 10 # seconds
|
||||
MAX_BACKOFF = 60 # seconds
|
||||
|
||||
def __init__(self, config):
|
||||
"""Initialize Mon api client connection."""
|
||||
self.config = config
|
||||
self.url = config.get('url', None)
|
||||
self.api_version = '2_0'
|
||||
self.keystone = keystone.Keystone(config)
|
||||
self.mon_client = None
|
||||
self._config = config
|
||||
self._mon_client = None
|
||||
self._api_version = '2_0'
|
||||
|
||||
self._failure_reason = None
|
||||
self._resume_time = None
|
||||
self._log_interval_remaining = 1
|
||||
self._current_number_measurements = 0
|
||||
self.max_buffer_size = int(config['max_buffer_size'])
|
||||
self.max_measurement_buffer_size = int(config['max_measurement_buffer_size'])
|
||||
self._max_buffer_size = int(config['max_buffer_size'])
|
||||
self._max_measurement_buffer_size = int(
|
||||
config['max_measurement_buffer_size'])
|
||||
|
||||
if self.max_buffer_size > -1:
|
||||
if self._max_buffer_size > -1:
|
||||
log.debug("'max_buffer_size' is deprecated. Please use"
|
||||
" 'max_measurement_buffer_size' instead")
|
||||
if self.max_measurement_buffer_size > -1:
|
||||
if self._max_measurement_buffer_size > -1:
|
||||
log.debug("Overriding 'max_buffer_size' option with new"
|
||||
" 'max_measurment_buffer_size' option")
|
||||
self.max_buffer_size = -1
|
||||
self._max_buffer_size = -1
|
||||
|
||||
self.backlog_send_rate = int(config['backlog_send_rate'])
|
||||
if self.max_buffer_size > -1:
|
||||
self.message_queue = collections.deque(maxlen=self.max_buffer_size)
|
||||
if self._max_buffer_size > -1:
|
||||
self.message_queue = collections.deque(maxlen=self._max_buffer_size)
|
||||
else:
|
||||
self.message_queue = collections.deque()
|
||||
self.write_timeout = int(config['write_timeout'])
|
||||
@ -70,9 +68,9 @@ class MonascaAPI(object):
|
||||
if tenant:
|
||||
kwargs['tenant_id'] = tenant
|
||||
|
||||
if not self.mon_client:
|
||||
self.mon_client = self.get_monclient()
|
||||
if not self.mon_client:
|
||||
if not self._mon_client:
|
||||
self._mon_client = self._get_mon_client()
|
||||
if not self._mon_client:
|
||||
# Keystone is down, queue the message
|
||||
self._queue_message(kwargs.copy(), "Keystone API is down or unreachable")
|
||||
return
|
||||
@ -121,46 +119,28 @@ class MonascaAPI(object):
|
||||
for tenant in tenant_group:
|
||||
self._post(tenant_group[tenant], tenant)
|
||||
|
||||
def get_monclient(self):
|
||||
"""get_monclient
|
||||
get a new monasca-client object
|
||||
"""
|
||||
token = self.keystone.get_token()
|
||||
if token:
|
||||
# Create the client.
|
||||
kwargs = self.keystone.get_credential_args()
|
||||
kwargs['token'] = token
|
||||
if not self.url:
|
||||
self.url = self.keystone.get_monasca_url()
|
||||
|
||||
return monascaclient.client.Client(self.api_version, self.url, write_timeout=self.write_timeout, **kwargs)
|
||||
|
||||
return None
|
||||
def _get_mon_client(self):
|
||||
k = keystone.Keystone(self._config)
|
||||
endpoint = k.get_monasca_url()
|
||||
session = k.get_session()
|
||||
c = client.Client(
|
||||
api_version=self._api_version,
|
||||
endpoint=endpoint,
|
||||
session=session,
|
||||
timeout=self.write_timeout,
|
||||
**keystone.get_args(self._config)
|
||||
)
|
||||
return c
|
||||
|
||||
def _send_message(self, **kwargs):
|
||||
if self._resume_time:
|
||||
if time.time() > self._resume_time:
|
||||
self._resume_time = None
|
||||
log.debug("Getting new token...")
|
||||
# Get a new keystone client and token
|
||||
if self.keystone.refresh_token():
|
||||
self.mon_client.replace_token(self.keystone.get_token())
|
||||
else:
|
||||
# Return without posting so the monasca client doesn't keep requesting new tokens
|
||||
return False
|
||||
try:
|
||||
self.mon_client.metrics.create(**kwargs)
|
||||
self._mon_client.metrics.create(**kwargs)
|
||||
return True
|
||||
except monascaclient.exc.HTTPException as ex:
|
||||
if ex.code == 401:
|
||||
# monasca client should already have retried once with a new token before returning this exception
|
||||
self._failure_reason = 'Invalid token detected. Waiting to get new token from Keystone'
|
||||
wait_time = random.randint(MonascaAPI.MIN_BACKOFF, MonascaAPI.MAX_BACKOFF + 1)
|
||||
self._resume_time = time.time() + wait_time
|
||||
log.info("Invalid token detected. Waiting %d seconds before getting new token.", wait_time)
|
||||
else:
|
||||
log.exception("HTTPException: error sending message to monasca-api.")
|
||||
self._failure_reason = 'Error sending message to the Monasca API: {0}'.format(str(ex.message))
|
||||
except exceptions.ClientException as ex:
|
||||
log.exception("ClientException: error sending "
|
||||
"message to monasca-api.")
|
||||
self._failure_reason = ('Error sending message to '
|
||||
'the Monasca API: {0}').format(str(ex))
|
||||
except Exception:
|
||||
log.exception("Error sending message to Monasca API.")
|
||||
self._failure_reason = 'The Monasca API is DOWN or unreachable'
|
||||
@ -168,7 +148,7 @@ class MonascaAPI(object):
|
||||
return False
|
||||
|
||||
def _queue_message(self, msg, reason):
|
||||
if self.max_buffer_size == 0 or self.max_measurement_buffer_size == 0:
|
||||
if self._max_buffer_size == 0 or self._max_measurement_buffer_size == 0:
|
||||
return
|
||||
|
||||
self.message_queue.append(json.dumps(msg))
|
||||
@ -176,16 +156,16 @@ class MonascaAPI(object):
|
||||
for value in msg.values():
|
||||
self._current_number_measurements += len(value)
|
||||
|
||||
if self.max_measurement_buffer_size > -1:
|
||||
while self._current_number_measurements > self.max_measurement_buffer_size:
|
||||
if self._max_measurement_buffer_size > -1:
|
||||
while self._current_number_measurements > self._max_measurement_buffer_size:
|
||||
self._remove_oldest_from_queue()
|
||||
|
||||
if self._log_interval_remaining <= 1:
|
||||
log.warn("{0}. Queuing the messages to send later...".format(reason))
|
||||
log.info("Current agent queue size: {0} of {1}.".format(len(self.message_queue),
|
||||
self.max_buffer_size))
|
||||
self._max_buffer_size))
|
||||
log.info("Current measurements in queue: {0} of {1}".format(
|
||||
self._current_number_measurements, self.max_measurement_buffer_size))
|
||||
self._current_number_measurements, self._max_measurement_buffer_size))
|
||||
|
||||
log.info("A message will be logged for every {0} messages queued.".format(MonascaAPI.LOG_INTERVAL))
|
||||
self._log_interval_remaining = MonascaAPI.LOG_INTERVAL
|
||||
|
Loading…
Reference in New Issue
Block a user