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.auth.identity import v3
|
||||||
from keystoneclient import session
|
from keystoneclient import session
|
||||||
@ -7,7 +19,7 @@ from neutronclient.v2_0 import client as neutronclient
|
|||||||
|
|
||||||
|
|
||||||
class OSClient:
|
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
|
Provide Openstack credentials to initalize the connection to Openstack
|
||||||
:param authmethod: string authmethod should be password or token but
|
:param authmethod: string authmethod should be password or token but
|
||||||
@ -114,3 +126,7 @@ class OSClient:
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
print "ERROR ::: ", e
|
print "ERROR ::: ", e
|
||||||
return output
|
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
|
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'
|
#__author__ = 'saad'
|
||||||
from daemon import Daemon
|
|
||||||
import sys
|
import sys
|
||||||
import logging as log
|
import logging as log
|
||||||
import time
|
import time
|
||||||
|
from osha.common.daemon import Daemon
|
||||||
log.basicConfig(filename='osha.log')
|
log.basicConfig(filename='osha.log')
|
||||||
|
|
||||||
|
|
||||||
@ -35,3 +35,7 @@ if __name__ == '__main__':
|
|||||||
else:
|
else:
|
||||||
print "Usage %s start|stop|restart" % sys.argv[0]
|
print "Usage %s start|stop|restart" % sys.argv[0]
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -2,8 +2,7 @@ pbr>=0.6,!=0.7,<1.0
|
|||||||
python-keystoneclient>=1.2.0,<1.4.0
|
python-keystoneclient>=1.2.0,<1.4.0
|
||||||
python-neutronclient>=2.4.0,<2.5.0
|
python-neutronclient>=2.4.0,<2.5.0
|
||||||
python-novaclient>=2.22.0,<2.24.0
|
python-novaclient>=2.22.0,<2.24.0
|
||||||
python-openstackclient>=1.0.3,<1.1.0
|
|
||||||
PyYAML>=3.1.0
|
PyYAML>=3.1.0
|
||||||
oslo.config>=1.9.3,<1.10.0 # Apache-2.0
|
oslo.config>=1.9.3,<1.10.0 # Apache-2.0
|
||||||
oslo.i18n>=1.5.0,<1.6.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