Some small improvements to pass pep8 and pep257.

This is just the first run.

Change-Id: If47a475b03d367a4e04f54ef31845e70d46f188c
This commit is contained in:
Stefano Canepa 2016-02-02 12:25:36 +00:00
parent fb00359b51
commit 444ebaa26f
6 changed files with 418 additions and 342 deletions

View File

@ -0,0 +1,15 @@
"""Common module for osha."""
# (c) Copyright 2016 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.

View File

@ -1,4 +1,6 @@
# (c) Copyright 2014,2015 Hewlett-Packard Development Company, L.P.
"""Manage all configuration the OpenStack way."""
# (c) Copyright 2016 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.
@ -11,12 +13,15 @@
# 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_config import cfg
from oslo_log import log
from osha import __version__ as OSHA_VERSION
from osha.common.utils import env
CONF = cfg.CONF
_MONITORS = [
@ -32,11 +37,10 @@ _MONITORS = [
cfg.DictOpt('kwargs',
default={},
help='List of kwargs if you want to pass it to initialize'
' the monitoring driver. should be provided in key:value '
'format')
' the monitoring driver. should be provided in key:value '
'format')
]
_COMMON = [
cfg.IntOpt('wait',
default=30,
@ -46,93 +50,92 @@ _COMMON = [
_FENCER = [
cfg.StrOpt('credentials-file',
help='YAML File contains the required credentials for compute '
'nodes'),
'nodes'),
cfg.IntOpt('retries',
default=1,
help='Number of retries to fence the each compute node. Must be'
' at least 1 to try first the soft shutdown'),
' at least 1 to try first the soft shutdown'),
cfg.IntOpt('hold-period',
default=10,
help='Time in seconds to wait between retries. Should be '
'reasonable amount of time as different servers take '
'different times to shut off'),
'reasonable amount of time as different servers take '
'different times to shut off'),
cfg.StrOpt('driver',
default='osha.fencers.drivers.ipmi.driver.IpmiDriver',
help='Choose the best fencer driver i.e.(ipmi, libvirt, ..'),
cfg.DictOpt('options',
default={},
help='List of kwargs to customize the fencer operation. You '
'fencer driver should support these options. Options '
'should be in key:value format')
'fencer driver should support these options. Options '
'should be in key:value format')
]
_KEYSTONE_AUTH_TOKEN = [
cfg.StrOpt('auth_uri',
help='Openstack auth URI i.e. http://controller:5000',
dest='auth_uri'),
cfg.StrOpt('auth_url',
help='Openstack auth URL i.e. http://controller:35357/v3',
dest='auth_url'),
dest='auth_uri'), cfg.StrOpt(
'auth_url',
help='Openstack auth URL i.e. http://controller:35357/v3',
dest='auth_url'),
cfg.StrOpt('auth_plugin',
help='Openstack auth plugin i.e. ( password, token, ...) '
'password is the only available plugin for the time being',
dest='auth_plugin'),
cfg.StrOpt('username',
help='Openstack username',
dest='username'),
'password is the only available plugin for the time being',
dest='auth_plugin'), cfg.StrOpt('username',
help='Openstack username',
dest='username'),
cfg.StrOpt('password',
help='Openstack Password',
dest='password'),
cfg.StrOpt('project_name',
help='Openstack Project Name.',
dest='project_name'),
dest='password'), cfg.StrOpt('project_name',
help='Openstack Project Name.',
dest='project_name'),
cfg.StrOpt('domain_name',
help='Openstack domain Name.',
dest='domain_name'),
cfg.StrOpt('project_domain_id',
help='Openstack Project Domain id, default is Default',
dest='project_domain_id'),
dest='domain_name'), cfg.StrOpt(
'project_domain_id',
help='Openstack Project Domain id, default is Default',
dest='project_domain_id'),
cfg.StrOpt('user_domain_id',
help='Openstack user Domain id, default is Default',
dest='user_domain_id'),
cfg.StrOpt('project_domain_name',
help='Openstack Project Domain name, default is Default',
dest='project_domain_name'),
cfg.StrOpt('user_domain_name',
help='Openstack user Domain name, default is Default',
dest='user_domain_name'),
dest='user_domain_id'), cfg.StrOpt(
'project_domain_name',
help='Openstack Project Domain name, default is Default',
dest='project_domain_name'), cfg.StrOpt(
'user_domain_name',
help='Openstack user Domain name, default is Default',
dest='user_domain_name'),
cfg.DictOpt('kwargs',
help='Openstack Authentication arguments you can pass it here '
'as Key:Value, Key1:Value1, ... ',
'as Key:Value, Key1:Value1, ... ',
dest='kwargs',
default={})
]
_EVACUATION = [
cfg.StrOpt('driver',
default='osha.evacuators.drivers.osha.standard.'
'OshaStandardEvacuator',
help='Time in seconds to wait between retries to disable compute'
' node or put it in maintenance mode. Default 10 seconds',
dest='driver'),
cfg.IntOpt('wait',
default=10,
help='Time in seconds to wait between retries to disable compute'
' node or put it in maintenance mode. Default 10 seconds',
dest='wait'),
cfg.StrOpt(
'driver',
default='osha.evacuators.drivers.osha.standard.'
'OshaStandardEvacuator',
help='Time in seconds to wait between retries to disable compute'
' node or put it in maintenance mode. Default 10 seconds',
dest='driver'), cfg.IntOpt(
'wait',
default=10,
help='Time in seconds to wait between retries to disable compute'
' node or put it in maintenance mode. Default 10 seconds',
dest='wait'),
cfg.IntOpt('retries',
default=1,
help='Number of retries to put node in maintenance mode before '
'reporting failure to evacuate the node',
'reporting failure to evacuate the node',
dest='retries'),
cfg.DictOpt('options',
default={},
help='Dict contains kwargs to be passed to the evacuator driver'
'. In case you have additional args needs to be passed to '
'your evacuator please, list them as key0:value0, '
'key1:value1, ....',
dest='options')
cfg.DictOpt(
'options',
default={},
help='Dict contains kwargs to be passed to the evacuator driver'
'. In case you have additional args needs to be passed to '
'your evacuator please, list them as key0:value0, '
'key1:value1, ....',
dest='options')
]
_NOTIFIERS = [
@ -140,121 +143,124 @@ _NOTIFIERS = [
default='osha.notifiers.drivers.osha.default_email.OshaEmail',
dest='driver',
help='Notification driver to load it to notify users '
'if something went wrong'),
'if something went wrong'),
cfg.StrOpt('endpoint',
default=None,
dest='endpoint',
help='Endpoint URL for the notification system. If you the '
'driver you are using doesnot require any URL just comment '
'it or use none'),
cfg.StrOpt('username',
default=None,
dest='username',
help='Username to authenticate against the notification system. '
'If the driver you are using doesnot require any '
'authentications comment or use None'),
cfg.StrOpt('password',
default=None,
dest='password',
help='Password to authenticate against the notification system. '
'If the driver you are using doesnot require any '
'authentications comment or use None'),
'driver you are using doesnot require any URL just comment '
'it or use none'),
cfg.StrOpt(
'username',
default=None,
dest='username',
help='Username to authenticate against the notification system. '
'If the driver you are using doesnot require any '
'authentications comment or use None'), cfg.StrOpt(
'password',
default=None,
dest='password',
help='Password to authenticate against the notification system. '
'If the driver you are using doesnot require any '
'authentications comment or use None'),
cfg.StrOpt('templates-dir',
dest='templates-dir',
default='/etc/osha/templates',
help='Path to Jinja2 templates directory that contains '
'message templates'),
'message templates'),
cfg.DictOpt('options',
default={},
dest='options',
help='Key:Value Kwargs to pass it to the notification driver, '
'if you want to pass any special arguments for your '
'driver. '),
'if you want to pass any special arguments for your '
'driver. '),
cfg.ListOpt('notify-list',
default=[],
dest='notify-list',
help='List of emails to sent them notification if something '
'went wrong and Osha wasnot able to send an email to the '
'tenant admin'),
'went wrong and Osha wasnot able to send an email to the '
'tenant admin'),
cfg.StrOpt('notify-from',
dest='notify-from',
help='The sender address, it can be email address if we used '
'default email driver, or phone number if we use sms '
'gateway for example.')
'default email driver, or phone number if we use sms '
'gateway for example.')
]
def build_os_options():
"""Build oslo options related to OpenStack environment."""
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].',
'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].',
'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].',
'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].',
'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].',
'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].',
'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].',
'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].',
'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].',
'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].',
'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-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]',
'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"',
'"public" or "publicURL", "internal" or "internalURL",'
' "admin" or "adminURL". Defaults to '
'env[OS_ENDPOINT_TYPE] or "public"',
dest='os_endpoint_type'),
]
@ -262,19 +268,20 @@ def build_os_options():
def configure():
"""Register configuration."""
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')
'monitor compute nodes')
CONF.register_group(monitors_grp)
CONF.register_opts(_MONITORS, group='monitoring')
fencers_grp = cfg.OptGroup('fencer',
title='fencer Options',
help='fencer Driver/plugin to be used to '
'fence compute nodes')
title='fencer Options',
help='fencer Driver/plugin to be used to '
'fence compute nodes')
CONF.register_group(fencers_grp)
CONF.register_opts(_FENCER, group='fencer')
@ -282,16 +289,16 @@ def configure():
evacuators_grp = cfg.OptGroup('evacuation',
title='Evacuation Options',
help='Evacuation Driver/plugin opts to be '
'used to Evacuate compute nodes')
'used to Evacuate compute nodes')
CONF.register_group(evacuators_grp)
CONF.register_opts(_EVACUATION, group='evacuation')
# Notification Section :)
notifiers_grp = cfg.OptGroup('notifiers',
title='Notification Options',
help='Notification Driver/plugin opts to be '
'used to Notify admins/users if failure '
'happens')
title='Notification Options',
help='Notification Driver/plugin opts to be '
'used to Notify admins/users if failure '
'happens')
CONF.register_group(notifiers_grp)
CONF.register_opts(_NOTIFIERS, group='notifiers')
@ -299,32 +306,33 @@ def configure():
keystone_grp = cfg.OptGroup('keystone_authtoken',
title='Keystone Auth Options',
help='Openstack Credentials to call the nova '
'APIs to evacuate ')
'APIs to evacuate ')
CONF.register_group(keystone_grp)
CONF.register_opts(_KEYSTONE_AUTH_TOKEN, group='keystone_authtoken')
default_conf = cfg.find_config_files('osha', 'osha',
'.conf')
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
)
version=OSHA_VERSION)
def setup_logging():
_DEFAULT_LOG_LEVELS = ['amqp=WARN', 'amqplib=WARN', 'boto=WARN','qpid=WARN',
'stevedore=WARN', 'oslo_log=INFO', 'iso8601=WARN',
"""Set some oslo log defaults."""
_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')
_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)
@ -340,4 +348,3 @@ def list_opts():
}
return _OPTS.items()

View File

@ -1,165 +1,183 @@
#!/usr/bin/env python
import sys, os, time, atexit
from signal import SIGTERM
"""Generic deamon."""
# (c) Copyright 2016 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 __future__ import print_function
import atexit
import logging as log
import os
import sys
import time
class Daemon:
from signal import SIGTERM
class Daemon(object):
"""A generic daemon class.
Usage: subclass the Daemon class and override the run() method
"""
def __init__(self, pidfile, stdin='/dev/null', stdout='/dev/null',
stderr='/dev/null'):
"""Instantiantion."""
self.stdin = stdin
self.stdout = stdout
self.stderr = stderr
self.pidfile = pidfile
def daemonize(self):
"""Do the UNIX double-fork magic.
See Stevens' "Advanced Programming in the UNIX Environment" for
details (ISBN 0201563177)
http://www.erlenstar.demon.co.uk/unix/faq_2.html#SEC16
"""
A generic daemon class.
Usage: subclass the Daemon class and override the run() method
try:
pid = os.fork()
if pid > 0:
# exit first parent
sys.exit(0)
except OSError as e:
sys.stderr.write("fork #1 failed: %d (%s)\n" %
(e.errno, e.strerror))
log.error(e)
sys.exit(1)
# decouple from parent environment
os.chdir("/")
os.setsid()
os.umask(0)
# do second fork
try:
pid = os.fork()
if pid > 0:
# exit from second parent
sys.exit(0)
except OSError as e:
sys.stderr.write("fork #2 failed: %d (%s)\n"
% (e.errno, e.strerror))
log.error(e)
sys.exit(1)
# redirect standard file descriptors
sys.stdout.flush()
sys.stderr.flush()
si = file(self.stdin, 'r')
so = file(self.stdout, 'a+')
se = file(self.stderr, 'a+', 0)
os.dup2(si.fileno(), sys.stdin.fileno())
os.dup2(so.fileno(), sys.stdout.fileno())
os.dup2(se.fileno(), sys.stderr.fileno())
# write pidfile
atexit.register(self.delpid)
pid = str(os.getpid())
f = file(self.pidfile, 'w+')
f.write("%s\n" % pid)
f.close()
def delpid(self):
"""Delete PID file."""
os.remove(self.pidfile)
def start(self):
"""Start the daemon."""
log.error("Test")
# Check for a pidfile to see if the daemon already runs
try:
pf = file(self.pidfile, 'r')
pid = int(pf.read().strip())
pf.close()
except IOError:
pid = None
if pid:
message = "pidfile %s already exist. Daemon" \
" already running?\n"
sys.stderr.write(message % self.pidfile)
sys.exit(1)
# Start the daemon
self.daemonize()
self.run()
# @todo needs some enhancement like check /proc/%pid/status if it's
# really running or not ! may be it's killed by external process
# the PID won't be updated !
def status(self):
"""Check daemon status."""
try:
pf = file(self.pidfile, 'r')
pid = int(pf.read().strip())
pf.close()
except IOError:
pid = None
if pid:
message = "pidfile %s already exist. Daemon already " \
"running. PID: %d \n"
sys.stdout.write(message % (self.pidfile, pid))
sys.exit(0)
else:
message = "Service not running!\n"
sys.stdout.write(message)
sys.exit(0)
def stop(self):
"""Stop the daemon."""
# Get the pid from the pidfile
try:
pf = file(self.pidfile, 'r')
pid = int(pf.read().strip())
pf.close()
except IOError:
pid = None
if not pid:
message = "pidfile %s does not exist." \
" Daemon not running?\n"
sys.stderr.write(message % self.pidfile)
return # not an error in a restart
# Try killing the daemon process
try:
while 1:
os.kill(pid, SIGTERM)
time.sleep(0.1)
except OSError as err:
err = str(err)
if err.find("No such process") > 0:
if os.path.exists(self.pidfile):
os.remove(self.pidfile)
else:
print(str(err))
sys.exit(1)
def restart(self):
"""Restart the daemon."""
self.stop()
self.start()
def run(self):
"""You should override this method when you subclass Daemon.
It will be called after the process has been
daemonized by start() or restart().
"""
def __init__(self, pidfile, stdin='/dev/null', stdout='/dev/null',
stderr='/dev/null'):
self.stdin = stdin
self.stdout = stdout
self.stderr = stderr
self.pidfile = pidfile
def daemonize(self):
"""
do the UNIX double-fork magic, see Stevens' "Advanced
Programming in the UNIX Environment" for details
(ISBN 0201563177)
http://www.erlenstar.demon.co.uk/unix/faq_2.html#SEC16
"""
try:
pid = os.fork()
if pid > 0:
# exit first parent
sys.exit(0)
except OSError, e:
sys.stderr.write("fork #1 failed: %d (%s)\n" %
(e.errno, e.strerror))
log.error(e)
sys.exit(1)
# decouple from parent environment
os.chdir("/")
os.setsid()
os.umask(0)
# do second fork
try:
pid = os.fork()
if pid > 0:
# exit from second parent
sys.exit(0)
except OSError, e:
sys.stderr.write("fork #2 failed: %d (%s)\n"
% (e.errno, e.strerror))
log.error(e)
sys.exit(1)
# redirect standard file descriptors
sys.stdout.flush()
sys.stderr.flush()
si = file(self.stdin, 'r')
so = file(self.stdout, 'a+')
se = file(self.stderr, 'a+', 0)
os.dup2(si.fileno(), sys.stdin.fileno())
os.dup2(so.fileno(), sys.stdout.fileno())
os.dup2(se.fileno(), sys.stderr.fileno())
# write pidfile
atexit.register(self.delpid)
pid = str(os.getpid())
f = file(self.pidfile, 'w+')
f.write("%s\n" % pid)
f.close()
def delpid(self):
os.remove(self.pidfile)
def start(self):
"""
Start the daemon
"""
log.error("Test")
# Check for a pidfile to see if the daemon already runs
try:
pf = file(self.pidfile,'r')
pid = int(pf.read().strip())
pf.close()
except IOError as e:
pid = None
if pid:
message = "pidfile %s already exist. Daemon" \
" already running?\n"
sys.stderr.write(message % self.pidfile)
sys.exit(1)
# Start the daemon
self.daemonize()
self.run()
# @todo needs some enhancement like check /proc/%pid/status if it's
# really running or not ! may be it's killed by external process
# the PID won't be updated !
def status(self):
try:
pf = file(self.pidfile, 'r')
pid = int(pf.read().strip())
pf.close()
except IOError as e:
pid = None
if pid:
message = "pidfile %s already exist. Daemon already " \
"running. PID: %d \n"
sys.stdout.write(message % (self.pidfile, pid))
sys.exit(0)
else:
message = "Service not running !\n"
sys.stdout.write(message)
sys.exit(0)
def stop(self):
"""
Stop the daemon
"""
# Get the pid from the pidfile
try:
pf = file(self.pidfile,'r')
pid = int(pf.read().strip())
pf.close()
except IOError:
pid = None
if not pid:
message = "pidfile %s does not exist." \
" Daemon not running?\n"
sys.stderr.write(message % self.pidfile)
return # not an error in a restart
# Try killing the daemon process
try:
while 1:
os.kill(pid, SIGTERM)
time.sleep(0.1)
except OSError, err:
err = str(err)
if err.find("No such process") > 0:
if os.path.exists(self.pidfile):
os.remove(self.pidfile)
else:
print str(err)
sys.exit(1)
def restart(self):
"""
Restart the daemon
"""
self.stop()
self.start()
def run(self):
"""
You should override this method when you subclass Daemon.
It will be called after the process has been
daemonized by start() or restart().
"""

View File

@ -1,4 +1,5 @@
# (c) Copyright 2014,2015 Hewlett-Packard Development Company, L.P.
"""OpenStack client class."""
# (c) Copyright 2016 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.
@ -11,21 +12,30 @@
# 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 __future__ import print_function
from keystoneclient import session
from keystoneclient.auth.identity import v3
from keystoneclient import session
from novaclient.v2 import client as novaclient
from neutronclient.v2_0 import client as neutronclient
from keystoneclient.v3 import client as keystoneclient
from neutronclient.v2_0 import client as neutronclient
from novaclient.v2 import client as novaclient
from oslo_log import log
LOG = log.getLogger(__name__)
class OSClient:
"""Provide OpenStack credentials to initalize the connection."""
def __init__(self, authurl, authmethod='password', ** kwargs):
"""
Provide Openstack credentials to initalize the connection to Openstack
"""Initialize the all class vars.
:param authmethod: string authmethod should be password or token but
currently we support only password !
:param kwargs: username, user_id, project_name, project_id,
@ -49,15 +59,17 @@ class OSClient:
# self.user_id = kwargs.get('user_id', None)
# self.user_domain_id = kwargs.get('user_domain_id', None)
# self.user_domain_name = kwargs.get('user_domain_name', None)
# self.project_domain_name = kwargs.get('project_domain_name', None)
# self.project_domain_name =
# kwargs.get('project_domain_name', None)
# self.endpoint_type = kwargs.get('endpoint_type', 'internalURL')
else:
print "The available authmethod is password for the time being" \
"Please, provide a password credentials :) "
print("The available authmethod is password for the time being")
print("Please, provide a password credential.")
self.auth()
def auth(self):
"""Create a session."""
auth = v3.Password(auth_url=self.authurl,
**self.kwargs)
self.auth_session = session.Session(auth=auth)
@ -89,16 +101,16 @@ class OSClient:
def neutronagents(self, hosts=[]):
if not hosts:
hosts = self.compute_hosts
new_sess = session.Session(auth=self.auth_session.auth)
neutron = neutronclient.Client(session=new_sess,
auth_session = session.Session(auth=self.auth_session.auth)
neutron = neutronclient.Client(session=auth_session,
endpoint_type=self.endpoint_type)
self.auth_session = new_sess
self.auth_session = auth_session
agents = neutron.list_agents()
neutron_agents = []
for agent in agents.get('agents'):
if agent.get('host') in hosts and agent.get('binary') == \
'neutron-openvswitch-agent':
neutron_agents.append(agent)
if agent.get('host') in hosts and agent.get('binary') == \
'neutron-openvswitch-agent':
neutron_agents.append(agent)
return neutron_agents
@ -109,10 +121,10 @@ class OSClient:
:param nodes: List of nodes to be evacuated !
:return: List of nodes with VMs that were running on that node
"""
new_sess = session.Session(auth=self.auth_session.auth)
nova = novaclient.Client(session=new_sess,
auth_session = session.Session(auth=self.auth_session.auth)
nova = novaclient.Client(session=auth_session,
endpoint_type=self.endpoint_type)
self.auth_session = new_sess
self.auth_session = auth_session
evacuated_nodes = []
for node in nodes:
hypervisors = nova.hypervisors.search(node.get('host'), True)
@ -125,15 +137,17 @@ class OSClient:
on_shared_storage=True)
except Exception as e:
LOG.error(e)
host = {'host': node.get('host'), 'servers': hypervisor.servers}
host = {'host': node.get(
'host'), 'servers': hypervisor.servers}
evacuated_nodes.append(host)
return evacuated_nodes
def set_in_maintance(self, nodes):
new_sess = session.Session(auth=self.auth_session.auth)
nova = novaclient.Client(session=new_sess,
def set_in_maintenance(self, nodes):
"""Set compute nodes in maintenance mode."""
auth_session = session.Session(auth=self.auth_session.auth)
nova = novaclient.Client(session=auth_session,
endpoint_type=self.endpoint_type)
self.auth_session = new_sess
self.auth_session = auth_session
for node in nodes:
output = []
host = nova.hosts.get(node)[0]
@ -145,12 +159,13 @@ class OSClient:
return output
def get_session(self):
"""Get the authentication section."""
auth_session = session.Session(auth=self.auth_session.auth)
return auth_session
def get_node_status(self, node):
"""
Check the node nova-service status and if it's disabled or not
"""Check the node nova-service status and if it's disabled or not.
:param node: dict contains node info
:return: True or False. True => node disabled, False => node is enabled
or unknow status !
@ -172,6 +187,7 @@ class OSClient:
return False
def disable_node(self, node):
"""Disable nova on the failing node."""
auth_session = session.Session(auth=self.auth_session.auth)
nova = novaclient.Client(session=auth_session,
endpoint_type=self.endpoint_type)
@ -189,7 +205,7 @@ class OSClient:
nova.services.disable_log_reason(
host=node.get('host'),
binary=node.get('binary'),
reason='Host Failed and needs to be evacuated.'
reason='Host failed and needs to be evacuated.'
)
del nova
LOG.info('Compute host: %s has been disabled to be evacuated. '
@ -200,6 +216,7 @@ class OSClient:
return True
def get_hypervisor_instances(self, node):
"""Get instances from an hypervisor."""
auth_session = session.Session(auth=self.auth_session.auth)
nova = novaclient.Client(session=auth_session,
endpoint_type=self.endpoint_type)
@ -209,8 +226,8 @@ class OSClient:
return hypervisors[0].servers
def get_hypervisor(self, node):
"""
Get an instance of the hypervisor, so you can do any operation you want.
"""Get an instance of the hypervisor.
:param node: dict contains host index
:return: Hypervisor
"""
@ -223,6 +240,7 @@ class OSClient:
return hypervisors[0]
def get_instances_list(self, node):
"""Get instances running on a node for all tenants."""
auth_session = session.Session(auth=self.auth_session.auth)
nova = novaclient.Client(session=auth_session,
endpoint_type=self.endpoint_type)
@ -239,6 +257,7 @@ class OSClient:
return self.get_instances_list(node)
def list_tenants(self):
"""List tenants."""
auth_session = session.Session(auth=self.auth_session.auth)
keystone = keystoneclient.Client(session=auth_session,
endpoint_type=self.endpoint_type)
@ -251,6 +270,7 @@ class OSClient:
return projects_data
def users_on_tenant(self, tenant):
"""List user per project."""
auth_session = session.Session(auth=self.auth_session.auth)
keystone = keystoneclient.Client(session=auth_session,
endpoint_type=self.endpoint_type,
@ -259,7 +279,7 @@ class OSClient:
try:
users = keystone.users.list(default_project=tenant)
except Exception as e:
print e
print(e)
users_list = []
for user in users:
users_list.append(user.to_dict())
@ -267,6 +287,7 @@ class OSClient:
return users_list
def get_hypervisors_stats(self):
"""Get stats for all hypervisors."""
auth_session = session.Session(auth=self.auth_session.auth)
nova = novaclient.Client(session=auth_session,
endpoint_type=self.endpoint_type)
@ -274,6 +295,7 @@ class OSClient:
return stats.to_dict()
def get_hypervisor_details(self, node):
"""Get details about hypervisor running on the provided node."""
auth_session = session.Session(auth=self.auth_session.auth)
nova = novaclient.Client(session=auth_session,
endpoint_type=self.endpoint_type)

View File

@ -1,4 +1,5 @@
# (c) Copyright 2014,2015 Hewlett-Packard Development Company, L.P.
"""Utility functions shared from all modules into the project."""
# (c) Copyright 2016 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.
@ -11,18 +12,22 @@
# 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
from osha.common.osclient import OSClient
import jinja2
from oslo_config import cfg
from oslo_log import log
import jinja2
from osha.common.osclient import OSClient
CONF = cfg.CONF
LOG = log.getLogger(__name__)
def env(*env_vars, **kwargs):
"""Get all environment variables."""
for variable in env_vars:
value = os.environ.get(variable, None)
if value:
@ -31,7 +36,8 @@ def env(*env_vars, **kwargs):
def get_os_client():
"""
"""Return the OpenStack client.
Loads credentials from [keystone_authtoken] section in the configuration
file and initialize the client and return an instance of the client
:return: Initialized instance of OS Client
@ -53,14 +59,15 @@ def get_os_client():
def load_jinja_templates(template_dir, template_name, template_vars):
"""
Load and render existing Jinja2 templates. The main purpose of the function
is to prepare the message to be sent and render it for the driver to send
it directly
"""Load and render existing Jinja2 templates.
The main purpose of the function is to prepare the message to be sent and
render it for the driver to send it directly.
:param template_dir: Location where jinja2 templates are stored
:param template_name: name of the template to load it
:param template_vars: Dict to replace existing vars in the template with
values.
values.
:return: String message
"""
template_loader = jinja2.FileSystemLoader(searchpath=template_dir)
@ -70,7 +77,8 @@ def load_jinja_templates(template_dir, template_name, template_vars):
def get_admin_os_client():
"""
"""Return admin client data.
Loads credentials from [keystone_authtoken] section in the configuration
file and initialize the client with admin privileges and return
an instance of the client

View File

@ -1,4 +1,4 @@
# (c) Copyright 2014,2015 Hewlett-Packard Development Company, L.P.
# (c) Copyright 2016 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.
@ -12,52 +12,58 @@
# See the License for the specific language governing permissions and
# limitations under the License.
"""Abstract fencer"""
import abc
import six
@six.add_metaclass(abc.ABCMeta)
class FencerBaseDriver(object):
"""
Abstract class that all fencer plugins should implement to have a
unified interface and as many plugins as we want...
"""Abstract class that all fencer plugins.
Should be implemented to have a unified interface and as many plugins as
needed.
"""
def __init__(self, node, **kwargs):
"""
Initializing the driver. Any fencer driver requires the following
parameters to do the api calls. All these parameters can be passed from
the configuration file in /etc/osha/osha.conf (default)
"""Initialize the driver.
Any fencer driver requires the following parameters to do the api
calls. All these parameters can be passed from the configuration
file in /etc/osha/osha.conf (default).
:param node: dict with all node details. (/etc/osha/servers.yml) ?
:param kwargs: any additional parameters can be passed using this config
option.
:param kwargs: any additional parameters can be passed using this
config option.
"""
self.node = node
self.kwargs = kwargs
@abc.abstractmethod
def graceful_shutdown(self):
"""
Gracefully shutdown the compute node to evacuate it.
"""
"""Gracefully shutdown the compute node to evacuate it."""
@abc.abstractmethod
def force_shutdown(self):
"""
Force shutdown the compute node to evacuate it. May be you can try force
shutdown if the graceful shutdown failed
"""Force shutdown the compute node to evacuate it.
May be you can try force shutdown if the graceful shutdown failed.
"""
@abc.abstractmethod
def status(self):
"""
Get compute node status. should return 1 if on and 0 if off or
-1 if error or unknown power status
"""Get compute node status.
Should return 1 if on and 0 if off or -1 if error or unknown power
status.
"""
@abc.abstractmethod
def get_info(self):
"""
Get Driver information ..
"""Get Driver information.
:return: dict of name, version, author, ...
"""