Adding support for plugable monitoring systems
adding support for pbr restructuring osha Change-Id: I0a899deeb33a5ebe77a199d33f3c0af48cddcbe6
This commit is contained in:
parent
0ee63ad837
commit
f785d6a413
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
*.pyc
|
||||
*.egg/
|
||||
*.egg-info/
|
||||
build/
|
181
etc/osha.conf
Normal file
181
etc/osha.conf
Normal file
@ -0,0 +1,181 @@
|
||||
[DEFAULT]
|
||||
|
||||
#
|
||||
# From osha
|
||||
#
|
||||
|
||||
# Time to wait between different operations (integer value)
|
||||
#wait = 30
|
||||
|
||||
#
|
||||
# From oslo.log
|
||||
#
|
||||
|
||||
# Print debugging output (set logging level to DEBUG instead of
|
||||
# default WARNING level). (boolean value)
|
||||
#debug = false
|
||||
|
||||
# Print more verbose output (set logging level to INFO instead of
|
||||
# default WARNING level). (boolean value)
|
||||
#verbose = false
|
||||
|
||||
# The name of a logging configuration file. This file is appended to
|
||||
# any existing logging configuration files. For details about logging
|
||||
# configuration files, see the Python logging module documentation.
|
||||
# (string value)
|
||||
# Deprecated group/name - [DEFAULT]/log_config
|
||||
#log_config_append = <None>
|
||||
|
||||
# DEPRECATED. A logging.Formatter log message format string which may
|
||||
# use any of the available logging.LogRecord attributes. This option
|
||||
# is deprecated. Please use logging_context_format_string and
|
||||
# logging_default_format_string instead. (string value)
|
||||
#log_format = <None>
|
||||
|
||||
# Format string for %%(asctime)s in log records. Default: %(default)s
|
||||
# . (string value)
|
||||
#log_date_format = %Y-%m-%d %H:%M:%S
|
||||
|
||||
# (Optional) Name of log file to output to. If no default is set,
|
||||
# logging will go to stdout. (string value)
|
||||
# Deprecated group/name - [DEFAULT]/logfile
|
||||
#log_file = <None>
|
||||
|
||||
# (Optional) The base directory used for relative --log-file paths.
|
||||
# (string value)
|
||||
# Deprecated group/name - [DEFAULT]/logdir
|
||||
#log_dir = <None>
|
||||
|
||||
# Use syslog for logging. Existing syslog format is DEPRECATED during
|
||||
# I, and will change in J to honor RFC5424. (boolean value)
|
||||
#use_syslog = false
|
||||
|
||||
# (Optional) Enables or disables syslog rfc5424 format for logging. If
|
||||
# enabled, prefixes the MSG part of the syslog message with APP-NAME
|
||||
# (RFC5424). The format without the APP-NAME is deprecated in I, and
|
||||
# will be removed in J. (boolean value)
|
||||
#use_syslog_rfc_format = false
|
||||
|
||||
# Syslog facility to receive log lines. (string value)
|
||||
#syslog_log_facility = LOG_USER
|
||||
|
||||
# Log output to standard error. (boolean value)
|
||||
#use_stderr = true
|
||||
|
||||
# Format string to use for log messages with context. (string value)
|
||||
#logging_context_format_string = %(asctime)s.%(msecs)03d %(process)d %(levelname)s %(name)s [%(request_id)s %(user_identity)s] %(instance)s%(message)s
|
||||
|
||||
# Format string to use for log messages without context. (string
|
||||
# value)
|
||||
#logging_default_format_string = %(asctime)s.%(msecs)03d %(process)d %(levelname)s %(name)s [-] %(instance)s%(message)s
|
||||
|
||||
# Data to append to log format when level is DEBUG. (string value)
|
||||
#logging_debug_format_suffix = %(funcName)s %(pathname)s:%(lineno)d
|
||||
|
||||
# Prefix each line of exception output with this format. (string
|
||||
# value)
|
||||
#logging_exception_prefix = %(asctime)s.%(msecs)03d %(process)d TRACE %(name)s %(instance)s
|
||||
|
||||
# List of logger=LEVEL pairs. (list value)
|
||||
#default_log_levels = amqp=WARN,amqplib=WARN,boto=WARN,qpid=WARN,sqlalchemy=WARN,suds=INFO,oslo.messaging=INFO,iso8601=WARN,requests.packages.urllib3.connectionpool=WARN,urllib3.connectionpool=WARN,websocket=WARN,requests.packages.urllib3.util.retry=WARN,urllib3.util.retry=WARN,keystonemiddleware=WARN,routes.middleware=WARN,stevedore=WARN
|
||||
|
||||
# Enables or disables publication of error events. (boolean value)
|
||||
#publish_errors = false
|
||||
|
||||
# Enables or disables fatal status of deprecations. (boolean value)
|
||||
#fatal_deprecations = false
|
||||
|
||||
# The format for an instance that is passed with the log message.
|
||||
# (string value)
|
||||
#instance_format = "[instance: %(uuid)s] "
|
||||
|
||||
# The format for an instance UUID that is passed with the log message.
|
||||
# (string value)
|
||||
#instance_uuid_format = "[instance: %(uuid)s] "
|
||||
|
||||
|
||||
[keystone]
|
||||
|
||||
#
|
||||
# From osha
|
||||
#
|
||||
|
||||
# Name used for authentication with the OpenStack Identity service.
|
||||
# Defaults to env[OS_USERNAME]. (string value)
|
||||
#os_username =
|
||||
|
||||
# Password used for authentication with the OpenStack Identity
|
||||
# service. Defaults to env[OS_PASSWORD]. (string value)
|
||||
#os_password =
|
||||
|
||||
# Project name to scope to. Defaults to env[OS_PROJECT_NAME]. (string
|
||||
# value)
|
||||
#os_project_name =
|
||||
|
||||
# Domain name containing project. Defaults to
|
||||
# env[OS_PROJECT_DOMAIN_NAME]. (string value)
|
||||
#os_project_domain_name =
|
||||
|
||||
# User's domain name. Defaults to env[OS_USER_DOMAIN_NAME]. (string
|
||||
# value)
|
||||
#os_user_domain_name =
|
||||
|
||||
# Tenant to request authorization on. Defaults to env[OS_TENANT_NAME].
|
||||
# (string value)
|
||||
#os_tenant_name =
|
||||
|
||||
# Tenant to request authorization on. Defaults to env[OS_TENANT_ID].
|
||||
# (string value)
|
||||
#os_tenant_id =
|
||||
|
||||
# Specify the Identity endpoint to use for authentication. Defaults to
|
||||
# env[OS_AUTH_URL]. (string value)
|
||||
#os_auth_url =
|
||||
|
||||
# Specify the Freezer backup service endpoint to use. Defaults to
|
||||
# env[OS_BACKUP_URL]. (string value)
|
||||
#os_backup_url =
|
||||
|
||||
# Specify the region to use. Defaults to env[OS_REGION_NAME]. (string
|
||||
# value)
|
||||
#os_region_name =
|
||||
|
||||
# Specify an existing token to use instead of retrieving one via
|
||||
# authentication (e.g. with username & password). Defaults to
|
||||
# env[OS_TOKEN]. (string value)
|
||||
#os_token =
|
||||
|
||||
# Identity API version: 2.0 or 3. Defaults to
|
||||
# env[OS_IDENTITY_API_VERSION] (string value)
|
||||
#os_identity_api_version =
|
||||
|
||||
# Endpoint type to select. Valid endpoint types: "public" or
|
||||
# "publicURL", "internal" or "internalURL", "admin" or "adminURL".
|
||||
# Defaults to env[OS_ENDPOINT_TYPE] or "public" (string value)
|
||||
# Allowed values: public, publicURL, internal, internalURL, admin, adminURL
|
||||
#os_endpoint_type = public
|
||||
|
||||
|
||||
[monitoring]
|
||||
|
||||
#
|
||||
# From osha
|
||||
#
|
||||
|
||||
# Driver used to get a status updates of compute nodes (string value)
|
||||
#driver = osha.monitors.plugins.osha.OshaDriver
|
||||
|
||||
# username to be used to initialize the monitoring driver (string
|
||||
# value)
|
||||
#username = <None>
|
||||
|
||||
# Password to be used for initializing monitoring driver (string
|
||||
# value)
|
||||
#password = <None>
|
||||
|
||||
# Monitoring system API endpoint (string value)
|
||||
#endpoint = <None>
|
||||
|
||||
# List of kwargs if you want to pass it to initialize the monitoring
|
||||
# driver (dict value)
|
||||
#kwargs = <None>
|
22
evacuate.py
22
evacuate.py
@ -1,22 +0,0 @@
|
||||
#__author__ = 'saad'
|
||||
from monitor import Monitor
|
||||
import osclient
|
||||
|
||||
password = 'BOMrLNGHsoBb'
|
||||
user_id = 'ec2548d6acb54e7ba24f479e2f3cb1a5'
|
||||
username = 'admin'
|
||||
auth_url = 'http://192.168.245.9:35357/v3'
|
||||
project_name = 'demo'
|
||||
project_id = 'f749b2874b0040aca92ea131210eb774'
|
||||
user_domain_name = 'Default'
|
||||
project_domain_name = 'Default'
|
||||
|
||||
client = osclient.OSClient(authurl=auth_url,
|
||||
username=username,
|
||||
password=password,
|
||||
user_domain_name=user_domain_name,
|
||||
project_name=project_name,
|
||||
project_domain_name=project_domain_name,
|
||||
endpoint_type='internal')
|
||||
monitor = Monitor(client, 1)
|
||||
monitor.monitor()
|
20
osha/__init__.py
Normal file
20
osha/__init__.py
Normal file
@ -0,0 +1,20 @@
|
||||
# (c) Copyright 2014,2015 Hewlett-Packard Development Company, L.P.
|
||||
#
|
||||
# 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.
|
||||
|
||||
# Osha Versions
|
||||
|
||||
import pbr.version
|
||||
|
||||
|
||||
__version__ = pbr.version.VersionInfo('osha').version_string()
|
0
osha/common/__init__.py
Normal file
0
osha/common/__init__.py
Normal file
167
osha/common/config.py
Normal file
167
osha/common/config.py
Normal file
@ -0,0 +1,167 @@
|
||||
# (c) Copyright 2014,2015 Hewlett-Packard Development Company, L.P.
|
||||
#
|
||||
# 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 oslo_config import cfg
|
||||
from osha.common.utils import env
|
||||
import sys
|
||||
from osha import __version__ as OSHA_VERSION
|
||||
from oslo_log import log
|
||||
|
||||
CONF = cfg.CONF
|
||||
|
||||
_MONITORS = [
|
||||
cfg.StrOpt('driver',
|
||||
default='osha.monitors.plugins.osha.OshaDriver',
|
||||
help='Driver used to get a status updates of compute nodes'),
|
||||
cfg.StrOpt('username',
|
||||
help='username to be used to initialize the monitoring driver'),
|
||||
cfg.StrOpt('password',
|
||||
help='Password to be used for initializing monitoring driver'),
|
||||
cfg.StrOpt('endpoint',
|
||||
help='Monitoring system API endpoint'),
|
||||
cfg.DictOpt('kwargs',
|
||||
default={},
|
||||
help='List of kwargs if you want to pass it to initialize'
|
||||
' the monitoring driver')
|
||||
]
|
||||
|
||||
|
||||
_COMMON = [
|
||||
cfg.IntOpt('wait',
|
||||
default=30,
|
||||
help='Time to wait between different operations')
|
||||
]
|
||||
|
||||
|
||||
def build_os_options():
|
||||
osclient_opts = [
|
||||
cfg.StrOpt('os-username',
|
||||
default=env('OS_USERNAME'),
|
||||
help='Name used for authentication with the OpenStack '
|
||||
'Identity service. Defaults to env[OS_USERNAME].',
|
||||
dest='os_username'),
|
||||
cfg.StrOpt('os-password',
|
||||
default=env('OS_PASSWORD'),
|
||||
help='Password used for authentication with the OpenStack '
|
||||
'Identity service. Defaults to env[OS_PASSWORD].',
|
||||
dest='os_password'),
|
||||
cfg.StrOpt('os-project-name',
|
||||
default=env('OS_PROJECT_NAME'),
|
||||
help='Project name to scope to. Defaults to '
|
||||
'env[OS_PROJECT_NAME].',
|
||||
dest='os_project_name'),
|
||||
cfg.StrOpt('os-project-domain-name',
|
||||
default=env('OS_PROJECT_DOMAIN_NAME'),
|
||||
help='Domain name containing project. Defaults to '
|
||||
'env[OS_PROJECT_DOMAIN_NAME].',
|
||||
dest='os_project_domain_name'),
|
||||
cfg.StrOpt('os-user-domain-name',
|
||||
default=env('OS_USER_DOMAIN_NAME'),
|
||||
help='User\'s domain name. Defaults to '
|
||||
'env[OS_USER_DOMAIN_NAME].',
|
||||
dest='os_user_domain_name'),
|
||||
cfg.StrOpt('os-tenant-name',
|
||||
default=env('OS_TENANT_NAME'),
|
||||
help='Tenant to request authorization on. Defaults to '
|
||||
'env[OS_TENANT_NAME].',
|
||||
dest='os_tenant_name'),
|
||||
cfg.StrOpt('os-tenant-id',
|
||||
default=env('OS_TENANT_ID'),
|
||||
help='Tenant to request authorization on. Defaults to '
|
||||
'env[OS_TENANT_ID].',
|
||||
dest='os_tenant_id'),
|
||||
cfg.StrOpt('os-auth-url',
|
||||
default=env('OS_AUTH_URL'),
|
||||
help='Specify the Identity endpoint to use for '
|
||||
'authentication. Defaults to env[OS_AUTH_URL].',
|
||||
dest='os_auth_url'),
|
||||
cfg.StrOpt('os-backup-url',
|
||||
default=env('OS_BACKUP_URL'),
|
||||
help='Specify the Freezer backup service endpoint to use. '
|
||||
'Defaults to env[OS_BACKUP_URL].',
|
||||
dest='os_backup_url'),
|
||||
cfg.StrOpt('os-region-name',
|
||||
default=env('OS_REGION_NAME'),
|
||||
help='Specify the region to use. Defaults to '
|
||||
'env[OS_REGION_NAME].',
|
||||
dest='os_region_name'),
|
||||
cfg.StrOpt('os-token',
|
||||
default=env('OS_TOKEN'),
|
||||
help='Specify an existing token to use instead of retrieving'
|
||||
' one via authentication (e.g. with username & '
|
||||
'password). Defaults to env[OS_TOKEN].',
|
||||
dest='os_token'),
|
||||
cfg.StrOpt('os-identity-api-version',
|
||||
default=env('OS_IDENTITY_API_VERSION'),
|
||||
help='Identity API version: 2.0 or 3. '
|
||||
'Defaults to env[OS_IDENTITY_API_VERSION]',
|
||||
dest='os_identity_api_version'),
|
||||
cfg.StrOpt('os-endpoint-type',
|
||||
choices=['public', 'publicURL', 'internal', 'internalURL',
|
||||
'admin', 'adminURL'],
|
||||
default=env('OS_ENDPOINT_TYPE') or 'public',
|
||||
help='Endpoint type to select. Valid endpoint types: '
|
||||
'"public" or "publicURL", "internal" or "internalURL",'
|
||||
' "admin" or "adminURL". Defaults to '
|
||||
'env[OS_ENDPOINT_TYPE] or "public"',
|
||||
dest='os_endpoint_type'),
|
||||
]
|
||||
|
||||
return osclient_opts
|
||||
|
||||
|
||||
def configure():
|
||||
CONF.register_cli_opts(build_os_options())
|
||||
CONF.register_opts(_COMMON)
|
||||
monitors_grp = cfg.OptGroup('monitoring',
|
||||
title='Monitoring',
|
||||
help='Monitoring Driver/plugin to be used to '
|
||||
'monitor compute nodes')
|
||||
CONF.register_group(monitors_grp)
|
||||
CONF.register_opts(_MONITORS, group='monitoring')
|
||||
|
||||
default_conf = cfg.find_config_files('osha', 'osha',
|
||||
'.conf')
|
||||
log.register_options(CONF)
|
||||
|
||||
CONF(args=sys.argv[1:],
|
||||
project='osha',
|
||||
default_config_files=default_conf,
|
||||
version=OSHA_VERSION
|
||||
)
|
||||
|
||||
|
||||
def setup_logging():
|
||||
_DEFAULT_LOG_LEVELS = ['amqp=WARN', 'amqplib=WARN', 'boto=WARN','qpid=WARN',
|
||||
'stevedore=WARN', 'oslo_log=INFO', 'iso8601=WARN',
|
||||
'requests.packages.urllib3.connectionpool=WARN',
|
||||
'urllib3.connectionpool=WARN', 'websocket=WARN',
|
||||
'keystonemiddleware=WARN', 'osha=INFO']
|
||||
|
||||
_DEFAULT_LOGGING_CONTEXT_FORMAT = ('%(asctime)s.%(msecs)03d %(process)d '
|
||||
'%(levelname)s %(name)s [%(request_id)s '
|
||||
'%(user_identity)s] %(instance)s'
|
||||
'%(message)s')
|
||||
log.set_defaults(_DEFAULT_LOGGING_CONTEXT_FORMAT, _DEFAULT_LOG_LEVELS)
|
||||
log.setup(CONF, 'osha', version=OSHA_VERSION)
|
||||
|
||||
|
||||
def list_opts():
|
||||
_OPTS = {
|
||||
None: _COMMON,
|
||||
'monitoring': _MONITORS,
|
||||
'keystone': build_os_options()
|
||||
}
|
||||
|
||||
return _OPTS.items()
|
||||
|
@ -1,4 +1,16 @@
|
||||
__author__ = 'saad'
|
||||
# (c) Copyright 2014,2015 Hewlett-Packard Development Company, L.P.
|
||||
#
|
||||
# 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 keystoneclient.auth.identity import v3
|
||||
from keystoneclient import session
|
||||
@ -7,7 +19,7 @@ from neutronclient.v2_0 import client as neutronclient
|
||||
|
||||
|
||||
class OSClient:
|
||||
def __init__(self, authurl, authmethod = 'password', ** kwargs):
|
||||
def __init__(self, authurl, authmethod='password', ** kwargs):
|
||||
"""
|
||||
Provide Openstack credentials to initalize the connection to Openstack
|
||||
:param authmethod: string authmethod should be password or token but
|
||||
@ -114,3 +126,7 @@ class OSClient:
|
||||
except Exception as e:
|
||||
print "ERROR ::: ", e
|
||||
return output
|
||||
|
||||
def get_session(self):
|
||||
auth_session = session.Session(auth=self.authSession.auth)
|
||||
return auth_session
|
23
osha/common/utils.py
Normal file
23
osha/common/utils.py
Normal file
@ -0,0 +1,23 @@
|
||||
# (c) Copyright 2014,2015 Hewlett-Packard Development Company, L.P.
|
||||
#
|
||||
# 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
|
||||
|
||||
|
||||
def env(*env_vars, **kwargs):
|
||||
for variable in env_vars:
|
||||
value = os.environ.get(variable, None)
|
||||
if value:
|
||||
return value
|
||||
return kwargs.get('default', '')
|
34
osha/evacuate.py
Normal file
34
osha/evacuate.py
Normal file
@ -0,0 +1,34 @@
|
||||
# (c) Copyright 2014,2015 Hewlett-Packard Development Company, L.P.
|
||||
#
|
||||
# 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 osha.monitor import Monitor
|
||||
import osclient
|
||||
|
||||
password = 'a22dQNcT'
|
||||
user_id = None
|
||||
username = 'admin'
|
||||
auth_url = 'http://192.168.245.9:35357/v3'
|
||||
project_name = 'demo'
|
||||
project_id = None
|
||||
user_domain_name = 'Default'
|
||||
project_domain_name = 'Default'
|
||||
|
||||
client = osclient.OSClient(authurl=auth_url,
|
||||
username=username,
|
||||
password=password,
|
||||
user_domain_name=user_domain_name,
|
||||
project_name=project_name,
|
||||
project_domain_name=project_domain_name,
|
||||
endpoint_type='internal')
|
||||
monitor = Monitor(client, 1)
|
||||
monitor.monitor()
|
36
osha/main.py
Normal file
36
osha/main.py
Normal file
@ -0,0 +1,36 @@
|
||||
# (c) Copyright 2014,2015 Hewlett-Packard Development Company, L.P.
|
||||
#
|
||||
# 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 osha.common import config
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log
|
||||
from oslo_utils import importutils
|
||||
from osha.monitors.common.manager import MonitorManager
|
||||
|
||||
CONF = cfg.CONF
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
|
||||
def main():
|
||||
config.configure()
|
||||
config.setup_logging()
|
||||
LOG.info('Starting osha ... ')
|
||||
# load and initialize the monitoring driver
|
||||
monitor = MonitorManager()
|
||||
# Do the monitoring procedure
|
||||
# Monitor, analyse, nodes down ?, wait, double check ? evacuate ..
|
||||
nodes = monitor.monitor()
|
||||
print "Evacuate those nodes:> ", nodes
|
||||
if nodes:
|
||||
# evacuate process goes here !
|
||||
pass
|
@ -1,4 +1,16 @@
|
||||
#__author__ = 'saad'
|
||||
# (c) Copyright 2014,2015 Hewlett-Packard Development Company, L.P.
|
||||
#
|
||||
# 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 time import sleep
|
||||
|
||||
|
13
osha/monitors/__init__.py
Normal file
13
osha/monitors/__init__.py
Normal file
@ -0,0 +1,13 @@
|
||||
# (c) Copyright 2014,2015 Hewlett-Packard Development Company, L.P.
|
||||
#
|
||||
# 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.
|
1
osha/monitors/common/__init__.py
Normal file
1
osha/monitors/common/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
|
96
osha/monitors/common/driver.py
Normal file
96
osha/monitors/common/driver.py
Normal file
@ -0,0 +1,96 @@
|
||||
# (c) Copyright 2014,2015 Hewlett-Packard Development Company, L.P.
|
||||
#
|
||||
# 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 abc
|
||||
import six
|
||||
|
||||
|
||||
@six.add_metaclass(abc.ABCMeta)
|
||||
class MonitorBaseDriver(object):
|
||||
"""
|
||||
Abstract class that all monitoring plugins should implement to have a
|
||||
unified interface and as many plugins as we want...
|
||||
"""
|
||||
|
||||
def __init__(self, username, password, endpoint, kwargs):
|
||||
"""
|
||||
Initializing the driver. Any monitoring system requires the following
|
||||
parameters to call it's api. All these parameters can be passed from the
|
||||
configuration file in /etc/osha/osha.conf
|
||||
:param username: Username
|
||||
:param password: Password
|
||||
:param endpoint: API URL
|
||||
:param kwargs: any additional parameters can be passed using this config
|
||||
option.
|
||||
"""
|
||||
self.username = username
|
||||
self.password = password
|
||||
self.endpoint = endpoint
|
||||
self.kwargs = kwargs
|
||||
|
||||
@abc.abstractmethod
|
||||
def get_data(self):
|
||||
"""
|
||||
Gathering metrics data. making the actual api call to
|
||||
the monitoring system and get a list of nodes status.
|
||||
"""
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def get_metrics(self):
|
||||
"""
|
||||
return list of metrics used to monitor compute nodes. it's Optional
|
||||
not all drivers need to implement this method.
|
||||
"""
|
||||
raise NotImplementedError()
|
||||
|
||||
@abc.abstractmethod
|
||||
def analyze_nodes(self, nodes):
|
||||
"""
|
||||
Process nodes from get_data and return list of down nodes
|
||||
:param nodes: dict of metrics of nodes { 'metric1': nodes,
|
||||
'metric2': nodes}
|
||||
:return: a list of down nodes
|
||||
"""
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def process_failed(self, nodes=[], wait=0):
|
||||
"""
|
||||
Double check the failed nodes again to make sure that nodes are down.
|
||||
return a list of down nodes to be passed to the evacuation tool to
|
||||
process failed hosts.
|
||||
:param nodes: a list contains pre-checked nodes to re-check them again
|
||||
:param wait: a configurable a mount of time to wait before doing this
|
||||
check to give a chance for the host to recover if there was a minor
|
||||
issue.
|
||||
:return: a list of nodes to be evacuated, the list will be passed
|
||||
directly to the evacuation tool to process them
|
||||
"""
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def is_alive(self):
|
||||
"""
|
||||
Plugin should provide a way to make sure that the monitoring system is
|
||||
a live or not. It's optional not all drivers need to implement it.
|
||||
:return: True or False
|
||||
"""
|
||||
raise NotImplementedError()
|
||||
|
||||
def get_info(self):
|
||||
"""
|
||||
Get Driver information ..
|
||||
:return: dict of name, version, author, ...
|
||||
"""
|
66
osha/monitors/common/manager.py
Normal file
66
osha/monitors/common/manager.py
Normal file
@ -0,0 +1,66 @@
|
||||
# (c) Copyright 2014,2015 Hewlett-Packard Development Company, L.P.
|
||||
#
|
||||
# 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 oslo_config import cfg
|
||||
from oslo_log import log
|
||||
from oslo_utils import importutils
|
||||
|
||||
CONF = cfg.CONF
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
|
||||
class MonitorManager(object):
|
||||
|
||||
def __init__(self):
|
||||
monitor = CONF.get('monitoring')
|
||||
self.driver = importutils.import_object(
|
||||
monitor.get('driver'),
|
||||
monitor.get('username'),
|
||||
monitor.get('password'),
|
||||
monitor.get('endpoint'),
|
||||
**monitor.get('kwargs')
|
||||
)
|
||||
driver_info = self.driver.get_info()
|
||||
LOG.info('Initializing driver %s with version %s found in %s' %
|
||||
(driver_info['name'], driver_info['version'],
|
||||
monitor.get('driver')))
|
||||
|
||||
def monitor(self):
|
||||
# Check if the monitoring system is a live
|
||||
is_alive = self.driver.is_alive()
|
||||
# if not a live will record that in logs and will try to communicate !
|
||||
if not is_alive:
|
||||
LOG.error('Monitoring system is not a live or may be driver is '
|
||||
'missing implementation for is_alive method')
|
||||
|
||||
# getting data from the monitoring system
|
||||
# may be in future we add a hock function to external data processors !
|
||||
# @todo add external data processors to analyze the monitoring systems
|
||||
# data to separate monitoring from analysis
|
||||
data = self.driver.get_data()
|
||||
|
||||
# Asking the driver to analyze the data provided and provide list
|
||||
# of failed nodes
|
||||
nodes_down = self.driver.analyze_nodes(nodes=data)
|
||||
if not nodes_down:
|
||||
LOG.info('No nodes reported down from %s')
|
||||
return 0 # for the time being we will exit with no error !
|
||||
|
||||
LOG.info('Nodes Down are: %s will be double checked again after %s '
|
||||
'seconds' % (str(nodes_down), CONF.wait))
|
||||
nodes_to_evacuate = self.driver.process_failed(nodes=nodes_down,
|
||||
wait=CONF.wait)
|
||||
return nodes_to_evacuate
|
||||
|
||||
def get_driver_info(self):
|
||||
return self.driver.get_info()
|
1
osha/monitors/drivers/__init__.py
Normal file
1
osha/monitors/drivers/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
__author__ = 'saad'
|
1
osha/monitors/drivers/osha/__init__.py
Normal file
1
osha/monitors/drivers/osha/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
__author__ = 'saad'
|
131
osha/monitors/drivers/osha/driver.py
Normal file
131
osha/monitors/drivers/osha/driver.py
Normal file
@ -0,0 +1,131 @@
|
||||
# (c) Copyright 2014,2015 Hewlett-Packard Development Company, L.P.
|
||||
#
|
||||
# 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 osha.common.osclient import OSClient
|
||||
from osha.monitors.common.driver import MonitorBaseDriver
|
||||
from time import sleep
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log
|
||||
from httplib import HTTPConnection, socket
|
||||
from urlparse import urlparse
|
||||
|
||||
CONF = cfg.CONF
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
|
||||
class OshaDriver(MonitorBaseDriver):
|
||||
|
||||
def __init__(self, username, password, endpoint, **kwargs):
|
||||
super(OshaDriver, self).__init__(username, password, endpoint, kwargs)
|
||||
client = OSClient(
|
||||
authurl=endpoint,
|
||||
username=username,
|
||||
password=password,
|
||||
**kwargs
|
||||
)
|
||||
LOG.info("OSClient:: username: %s, password: %s, endpoint: %s, kwargs:"
|
||||
" %s" % (username, '****', endpoint, kwargs))
|
||||
self.client = client
|
||||
|
||||
def get_data(self):
|
||||
hypervisors = self.client.novahypervisors()
|
||||
computes = self.client.novacomputes()
|
||||
agents = self.client.neutronagents()
|
||||
data = {'hypervisors': hypervisors,
|
||||
'computes': computes,
|
||||
'agents': agents}
|
||||
return data
|
||||
|
||||
def process_failed(self, nodes=None, wait=0):
|
||||
if not wait:
|
||||
wait = CONF.wait
|
||||
if not nodes:
|
||||
return None
|
||||
sleep(wait)
|
||||
# @todo do the api call again to get the nodes status again
|
||||
data = self.get_data()
|
||||
nodes_down = self.analyze_nodes(nodes=data)
|
||||
# Thanks Eldar :) for sets
|
||||
nodes_down_hosts = set([dnode['host'] for dnode in nodes_down])
|
||||
return [node for node in nodes if node['host'] in nodes_down_hosts]
|
||||
|
||||
def get_metrics(self):
|
||||
return ['nova-compute', 'hypervisor', 'neutron-ovs-agent']
|
||||
|
||||
def analyze_nodes(self, nodes):
|
||||
# list all down nova compute
|
||||
nova_down = self.is_nova_service_down(nodes.get('computes'))
|
||||
# list all down hypervisors
|
||||
hypervisor_down = self.is_hpyervisor_down(nodes.get('hypervisors'))
|
||||
# list all down openvswitch agents
|
||||
agents_down = self.is_neutron_agents_down(nodes.get('agents'))
|
||||
|
||||
nodes_down = []
|
||||
for server in hypervisor_down:
|
||||
ip = server.get('ip')
|
||||
host = server.get('host')
|
||||
if host in nova_down and host in agents_down:
|
||||
node = {'ip': ip, 'host': host}
|
||||
nodes_down.append(node)
|
||||
|
||||
return nodes_down
|
||||
|
||||
def is_alive(self):
|
||||
url = urlparse(self.endpoint)
|
||||
try:
|
||||
connection = HTTPConnection(host=url.netloc)
|
||||
connection.request('HEAD', url=url.path)
|
||||
response = connection.getresponse()
|
||||
except socket.error:
|
||||
return False
|
||||
try:
|
||||
if getattr(response, 'status') == 200:
|
||||
return True
|
||||
except AttributeError:
|
||||
pass
|
||||
return False
|
||||
|
||||
def get_info(self):
|
||||
return {
|
||||
'name': 'Osha Native Driver',
|
||||
'version': 1.0,
|
||||
'author': 'Hewlett-Packard Development Company, L.P'
|
||||
}
|
||||
|
||||
|
||||
def is_hpyervisor_down(self, hypervisors):
|
||||
down_hosts = []
|
||||
for hypervisor in hypervisors:
|
||||
if hypervisor.get('state') == 'down':
|
||||
host = {}
|
||||
host['host'] = hypervisor.get('service').get('host')
|
||||
host['ip'] = hypervisor.get('host_ip')
|
||||
down_hosts.append(host)
|
||||
|
||||
return down_hosts
|
||||
|
||||
def is_nova_service_down(self, computes):
|
||||
down_hosts = []
|
||||
for node in computes:
|
||||
if node.get('state') == 'down' and node.get('status') == 'enabled':
|
||||
down_hosts.append(node.get('host'))
|
||||
return down_hosts
|
||||
|
||||
def is_neutron_agents_down(self, agents):
|
||||
down_hosts = []
|
||||
for agent in agents:
|
||||
if agent.get('admin_state_up') and not agent.get('alive'):
|
||||
down_hosts.append(agent.get('host'))
|
||||
|
||||
return down_hosts
|
||||
|
@ -1,8 +1,8 @@
|
||||
#__author__ = 'saad'
|
||||
from daemon import Daemon
|
||||
import sys
|
||||
import logging as log
|
||||
import time
|
||||
from osha.common.daemon import Daemon
|
||||
log.basicConfig(filename='osha.log')
|
||||
|
||||
|
||||
@ -35,3 +35,7 @@ if __name__ == '__main__':
|
||||
else:
|
||||
print "Usage %s start|stop|restart" % sys.argv[0]
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
|
||||
|
@ -2,8 +2,7 @@ pbr>=0.6,!=0.7,<1.0
|
||||
python-keystoneclient>=1.2.0,<1.4.0
|
||||
python-neutronclient>=2.4.0,<2.5.0
|
||||
python-novaclient>=2.22.0,<2.24.0
|
||||
python-openstackclient>=1.0.3,<1.1.0
|
||||
PyYAML>=3.1.0
|
||||
oslo.config>=1.9.3,<1.10.0 # Apache-2.0
|
||||
oslo.i18n>=1.5.0,<1.6.0 # Apache-2.0
|
||||
oslo.log>=1.0.0,<1.1.0 # Apache-2.0
|
||||
oslo.utils>=1.4.0,!=1.4.1,<1.5.0
|
||||
|
37
setup.cfg
Normal file
37
setup.cfg
Normal file
@ -0,0 +1,37 @@
|
||||
[metadata]
|
||||
name = Osha
|
||||
version = 0.1
|
||||
summary = OpenStack Compute High Availability
|
||||
description-file =
|
||||
README.rst
|
||||
author = OpenStack
|
||||
author-email = openstack-dev@lists.openstack.org
|
||||
home-page = http://www.openstack.org/
|
||||
classifier =
|
||||
Environment :: OpenStack
|
||||
Intended Audience :: Information Technology
|
||||
Intended Audience :: System Administrators
|
||||
License :: OSI Approved :: Apache Software License
|
||||
Operating System :: POSIX :: Linux
|
||||
Programming Language :: Python
|
||||
Programming Language :: Python :: 2
|
||||
Programming Language :: Python :: 2.7
|
||||
|
||||
[files]
|
||||
packages =
|
||||
osha
|
||||
|
||||
[global]
|
||||
setup-hooks =
|
||||
pbr.hooks.setup_hook
|
||||
|
||||
|
||||
[pbr]
|
||||
warnerrors = True
|
||||
|
||||
|
||||
[entry_points]
|
||||
oslo.config.opts =
|
||||
osha = osha.common.config:list_opts
|
||||
console_scripts =
|
||||
osha = osha.main:main
|
29
setup.py
Normal file
29
setup.py
Normal file
@ -0,0 +1,29 @@
|
||||
# Copyright (c) 2013 Hewlett-Packard Development Company, L.P.
|
||||
#
|
||||
# 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.
|
||||
|
||||
# THIS FILE IS MANAGED BY THE GLOBAL REQUIREMENTS REPO - DO NOT EDIT
|
||||
import setuptools
|
||||
|
||||
# In python < 2.7.4, a lazy loading of package `pbr` will break
|
||||
# setuptools if some other modules registered functions in `atexit`.
|
||||
# solution from: http://bugs.python.org/issue15881#msg170215
|
||||
try:
|
||||
import multiprocessing # noqa
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
setuptools.setup(
|
||||
setup_requires=['pbr'],
|
||||
pbr=True)
|
Loading…
Reference in New Issue
Block a user