fuel-library/files/fuel-notify/fuel_notify.py
Cao Xuan Hoang 3c1be65209 Add Apache 2.0 license to source file
As per OpenStack licensing guide lines [1]:
[H102 H103] Newly contributed Source Code should be licensed under
the Apache 2.0 license.
[H104] Files with no code shouldn't contain any license header nor
comments, and must be left completely empty.

[1] http://docs.openstack.org/developer/hacking/#openstack-licensing

Change-Id: Id37d20c647b9f4e580732cf5d600ec9c53fdb7d8
2016-09-30 15:19:23 +07:00

123 lines
3.7 KiB
Python

#!/usr/bin/env python
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import logging
import logging.handlers
import os
import six
import subprocess
import sys
import yaml
log = logging.getLogger('fuel_notify')
log_handler = logging.handlers.SysLogHandler(address='/dev/log')
log_handler.setFormatter(logging.Formatter('%(name)s: %(message)s'))
log.addHandler(log_handler)
log.setLevel(logging.INFO)
CONFIG_FILE = '/etc/fuel/free_disk_check.yaml'
STATE_FILE = '/var/run/free_disk_check_state.yaml'
def read_state():
try:
with open(STATE_FILE) as f:
return yaml.load(f)
except IOError:
return {}
def get_credentials():
with open(CONFIG_FILE) as f:
config = yaml.load(f)
if not config:
log.error('Config empty, exiting')
sys.exit(1)
# NOTE(pkaminski): 'monitord' user is for sending notifications only
# We cannot use admin -- in case the end user changes admin's password
# we wouldn't be able to send notifications.
return (
config['monitord_user'],
config['monitord_password'],
config['monitord_tenant']
)
def save_notify_state(mount_point, state):
state_dict = read_state()
state_dict[mount_point] = state
with open(STATE_FILE, 'w') as f:
f.write(yaml.dump(state_dict, default_flow_style=False))
def was_notified(mount_point, state):
"""Checks if user was notified of mount_point being in given state."""
return read_state().get(mount_point, 'SUCCESS') == state
def notify(message, topic=None):
user, password, tenant = get_credentials()
try:
command = [
'fuel', '--user', user, '--password', password, '--tenant', tenant,
'notify', '-m', message
]
if topic:
command.extend(['--topic', topic])
subprocess.Popen(command)
except OSError:
sys.exit(1)
def get_error(state='SUCCESS', mount_point='/'):
s = os.statvfs(mount_point)
# Convert to GB
free_gb = s.f_bavail * s.f_frsize / (1024.0 ** 3)
if state == 'ERROR':
return ('Your disk space on {0} is running low ({1:.2f} GB '
'currently available).').format(mount_point, free_gb)
return ('Your free disk space on {0} is back to normal ({1:.2f} GB '
'currently available).').format(mount_point, free_gb)
if __name__ == '__main__':
if len(sys.argv) != 3 or sys.argv[1] not in ['ERROR', 'SUCCESS']:
six.print_(
'Syntax: {0} [ERROR|SUCCESS] <mount-point>'.format(sys.argv[0])
)
sys.exit(1)
state = sys.argv[1]
mount_point = sys.argv[2]
message = get_error(state=state, mount_point=mount_point)
if state == 'SUCCESS' and not was_notified(mount_point, state):
# Notify about disk space back to normal
log.info('Notifying about SUCCESS state for {0}'.format(mount_point))
notify(message, topic='done')
save_notify_state(mount_point, state)
if state == 'ERROR' and not was_notified(mount_point, state):
# Notify about disk space error
log.info('Notifying about ERROR state for {0}'.format(mount_point))
notify(message, topic='error')
save_notify_state(mount_point, state)