monasca-agent/monasca_setup/detection/plugins/mysql.py

166 lines
6.5 KiB
Python

# (C) Copyright 2015,2016 Hewlett Packard Enterprise Development Company LP
# 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 logging
import os
from six.moves import configparser
import monasca_setup.agent_config
import monasca_setup.detection
from monasca_setup.detection.utils import find_process_name
log = logging.getLogger(__name__)
mysql_conf = '/root/.my.cnf'
HOST = 'localhost'
PORT = 3306
SOCKET = '/var/run/mysqld/mysqld.sock'
class MySQL(monasca_setup.detection.Plugin):
"""Detect MySQL daemons and setup configuration to monitor them.
This plugin needs user/password info for mysql setup.
It needs either the host ip or socket if using
the default localhost hostname. You cannot use
the localhost name if using ssl. This plugin
accepts arguments, and if none are input it will
try to read the default config file which is
best placed in /root/.my.cnf in a format such as
[client]
user=root
password=yourpassword
host=padawan-ccp-c1-m1-mgmt
ssl_ca=/etc/ssl/certs/ca-certificates.crt
"""
def _detect(self):
"""Run detection, set self.available True if the service is detected.
"""
process_exist = find_process_name('mysqld') is not None
has_dependencies = self.dependencies_installed()
has_args_or_config_file = (self.args is not None or
os.path.isfile(mysql_conf))
self.available = (process_exist and has_args_or_config_file and
has_dependencies)
if not self.available:
if not process_exist:
log.info('MySQL process does not exist.')
elif not has_args_or_config_file:
log.warning(('MySQL process exists but '
'configuration file was not found and '
'no arguments were given.'))
elif not has_dependencies:
log.error(('MySQL process exists but required dependence '
'PyMySQL is not installed.'))
def _get_config(self):
"""Set the configuration to be used for connecting to mysql
:return:
"""
self.ssl_options = {}
# reads default config file if no input parameters
if self.args is None:
self._read_config(mysql_conf)
else:
self.host = self.args.get('host', HOST)
self.port = self.args.get('port', PORT)
self.user = self.args.get('user', 'root')
self.password = self.args.get('password', None)
self.socket = self.args.get('socket', None)
self.ssl_ca = self.args.get('ssl_ca', None)
self.ssl_key = self.args.get('ssl_key', None)
self.ssl_cert = self.args.get('ssl_cert', None)
if self.ssl_ca is not None:
self.ssl_options['ca'] = self.ssl_ca
if self.ssl_key is not None:
self.ssl_options['key'] = self.ssl_key
if self.ssl_cert is not None:
self.ssl_options['cert'] = self.ssl_cert
if self.socket is None and (self.host == 'localhost' or self.host == '127.0.0.1'):
self.socket = SOCKET
def _read_config(self, config_file):
"""Read the configuration setting member variables as appropriate.
:param config_file: The filename of the configuration to read and parse
"""
log.info("\tUsing client credentials from {}".format(config_file))
parser = configparser.RawConfigParser(defaults={
'user': None,
'password': None,
'host': HOST,
'port': PORT,
'socket': None,
'ssl_ca': None,
'ssl_key': None,
'ssl_cert': None
}, allow_no_value=True)
parser.read(config_file)
self.user = parser.get('client', 'user')
self.password = parser.get('client', 'password')
self.host = parser.get('client', 'host')
self.port = parser.get('client', 'port')
self.socket = parser.get('client', 'socket')
self.ssl_ca = parser.get('client', 'ssl_ca')
self.ssl_key = parser.get('client', 'ssl_key')
self.ssl_cert = parser.get('client', 'ssl_cert')
def build_config(self):
"""Build the config as a Plugins object and return.
"""
config = monasca_setup.agent_config.Plugins()
# First watch the process
config.merge(monasca_setup.detection.watch_process(['mysqld'], 'mysql'))
log.info("\tWatching the mysqld process.")
try:
import pymysql
self._get_config()
# connection test
pymysql.connect(host=self.host, user=self.user,
passwd=self.password, port=self.port,
unix_socket=self.socket, ssl=self.ssl_options)
log.info("\tConnection test success.")
config['mysql'] = {
'init_config': None, 'instances':
[{'name': self.host, 'server': self.host, 'port': self.port,
'user': self.user, 'pass': self.password,
'sock': self.socket, 'ssl_ca': self.ssl_ca,
'ssl_key': self.ssl_key, 'ssl_cert': self.ssl_cert}]}
except ImportError as e:
exception_msg = ('The mysql dependency PyMySQL is not '
'installed. {}'.format(e))
log.exception(exception_msg)
raise Exception(exception_msg)
except pymysql.MySQLError as e:
exception_msg = 'Could not connect to mysql. {}'.format(e)
log.exception(exception_msg)
raise Exception(exception_msg)
except Exception as e:
exception_msg = 'Error configuring the mysql check plugin. {}'.format(e)
log.exception(exception_msg)
raise Exception(exception_msg)
return config
def dependencies_installed(self):
try:
import pymysql # noqa
except ImportError:
return False
return True