jolokia/api.py
"""Forms high-level API for Jolokia Python client"""
import logging
from jolokia.exceptions import IllegalArgumentException
from jolokia.models import JolokiaSession
from jolokia.utils.validators import verify_url
from jolokia.utils.decorators import require_params
LOGGER = logging.getLogger(__name__)
class JolokiaClient:
"""Main class for interacting with a single Jolokia agent"""
def __init__(self, base_url, username=None, password=None):
verify_url(base_url)
self.base_url = base_url
self.session = JolokiaSession(username, password)
@require_params(['mbean', 'operation', 'arguments'], 'execute method has 3 required keyword argument: mbean, operation, and arguments')
def execute(self, **kwargs):
"""Execute JMX operation on MBean."""
kwargs.update({'type': 'exec'})
resp = self.session.simple_post(self.base_url, data=kwargs)
LOGGER.debug('Return type of %s with return value of %s', type(resp), resp.text)
try:
return resp.json()
except ValueError:
return resp
finally:
LOGGER.debug(resp.content)
def list(self, path=None):
"""Returns a list of all MBeans on all available MBean servers."""
data = {
'type': 'list',
'path': path
}
LOGGER.debug(data)
resp = self.session.simple_post(self.base_url, data=data)
try:
return resp.json()
except ValueError:
return resp
finally:
LOGGER.debug(resp.content)
@require_params(['mbean'], 'search method has 1 required keyword argument: mbean')
def search(self, **kwargs):
"""Searches all available MBean servers for the desired MBean"""
kwargs.update({'type': 'search'})
resp = self.session.simple_post(self.base_url, data=kwargs)
try:
return resp.json()
except ValueError:
return resp
finally:
LOGGER.debug(resp.content)
def version(self):
"""Returns agent version"""
resp = self.session.simple_post(self.base_url, data={'type': 'version'})
try:
return resp.json()
except ValueError:
return resp
finally:
LOGGER.debug(resp.content)
@require_params(['mbean', 'attribute'], 'get_attribute method has 2 required keyword arguments: mbean and attribute')
def get_attribute(self, mbean=None, attribute=None, path=None):
"""Returns an attribute's value. Domain and MBean type must be specified
:param mbean: The MBean to query.
:param attribute: The MBean attribute to get
:param path: (optional) Path to query into MBean attribute
"""
if isinstance(attribute, list):
return self._bulk_read(mbean, attribute)
data = {
'type': 'read',
'mbean': mbean,
'attribute': attribute,
'path': path
}
LOGGER.debug(data)
resp = self.session.simple_post(self.base_url, data=data)
LOGGER.debug(resp.text)
try:
return resp.json()
except ValueError:
return resp
finally:
LOGGER.debug(resp.content)
@require_params(['mbean', 'attr_value_pairs'], 'set_attribute method has 2 required arguments: mbean, attr_value_pairs')
def set_attribute(self, mbean=None, attr_value_pairs=None, bulk=False, path=None):
"""Sets the value of an MBean's attribute
:param mbean: string, the mbean to query
:param attr_value_pairs: If bulk is false, a 2-tuple consisting of (attribute, value). If bulk is true, a list of such tuples.
:param bulk: (optional) Whether or not multiple attributes are to be set.
:param path: (optional) Inner path for nesteed mbean values
"""
if not _attr_value_pairs_is_valid(bulk, attr_value_pairs):
raise IllegalArgumentException('attr_value_pairs must either be a single 2-tuple or a list of 2-tuples.')
if bulk:
return self._bulk_write(mbean, attr_value_pairs)
attribute, value = attr_value_pairs
data = {
'type': 'write',
'mbean': mbean,
'attribute': attribute,
'value': value,
'path': path
}
LOGGER.debug(data)
resp = self.session.simple_post(self.base_url, data=data)
try:
return resp.json()
except ValueError:
return resp
finally:
LOGGER.debug(resp.content)
def _bulk_write(self, mbean, attr_value_pairs):
data = []
for avp in attr_value_pairs:
attr, value = avp
data.append({
'type': 'write',
'mbean': mbean,
'attribute': attr,
'value': value
})
LOGGER.debug(data)
resp = self.session.simple_post(self.base_url, data=data)
try:
return resp.json()
except ValueError:
return resp
finally:
LOGGER.debug(resp.content)
def _bulk_read(self, mbean, attribute, path=None):
data = []
for att in attribute:
data.append({
'type': 'read',
'mbean': mbean,
'attribute': att,
'path': path
})
LOGGER.debug(data)
resp = self.session.simple_post(self.base_url, data=data)
try:
return resp.json()
except ValueError:
return resp
finally:
LOGGER.debug(resp.content)
def _attr_value_pairs_is_valid(bulk, attr_value_pairs):
if not bulk:
return isinstance(attr_value_pairs, tuple) and len(attr_value_pairs) == 2
LOGGER.debug('Validating bulk write...')
if not isinstance(attr_value_pairs, list):
LOGGER.debug('Attribute-value pairs not a list')
return False
for avp in attr_value_pairs:
if not (isinstance(avp, tuple) and len(avp) == 2):
LOGGER.debug('At least one of the attribute-value pairs is invalid')
return False
return True