3c1be65209
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
123 lines
3.7 KiB
Python
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)
|