Add common notification sending functions

This patch adds common notification sending functions.
This functions are used by three monitors.

Change-Id: I8be71f64a513aeaa2d8cd9f59c37e658f9497d66
Implements: bp pythonize-host-and-process-monitor
This commit is contained in:
Kengo Takahara 2017-02-01 14:13:30 +09:00 committed by takahara.kengo
parent 31b7efbab7
commit fd7b703035
6 changed files with 145 additions and 86 deletions

View File

View File

@ -0,0 +1,105 @@
# Copyright(c) 2016 Nippon Telegraph and Telephone Corporation
#
# 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 eventlet
from openstack import connection
from openstack import profile
from oslo_log import log as oslo_logging
from masakariclient.sdk.ha import ha_service
import masakarimonitors.conf
from masakarimonitors.i18n import _LE
from masakarimonitors.i18n import _LI
from masakarimonitors.i18n import _LW
LOG = oslo_logging.getLogger(__name__)
CONF = masakarimonitors.conf.CONF
PROFILE_TYPE = "ha"
PROFILE_NAME = "masakari"
class SendNotification(object):
def _get_connection(self, api_version, region, interface, auth_url,
project_name, username, password, project_domain_id,
user_domain_id):
# Create profile object.
prof = profile.Profile()
prof._add_service(ha_service.HAService(version=api_version))
prof.set_name(PROFILE_TYPE, PROFILE_NAME)
prof.set_region(PROFILE_TYPE, region)
prof.set_version(PROFILE_TYPE, api_version)
prof.set_interface(PROFILE_TYPE, interface)
# Get connection.
conn = connection.Connection(
auth_url=auth_url,
project_name=project_name,
username=username,
password=password,
project_domain_id=project_domain_id,
user_domain_id=user_domain_id,
profile=prof)
return conn
def send_notification(self, api_retry_max, api_retry_interval, event):
"""Send a notification.
This method sends a notification to the masakari-api.
:param api_retry_max: Number of retries when the notification
processing is error.
:param api_retry_interval: Trial interval of time of the notification
processing is error.
:param event: dictionary of event that included in notification.
"""
LOG.info(_LI("Send a notification. %s"), event)
# Get connection.
conn = self._get_connection(
api_version=CONF.api.api_version,
region=CONF.api.region,
interface=CONF.api.api_interface,
auth_url=CONF.api.auth_url,
project_name=CONF.api.project_name,
username=CONF.api.username,
password=CONF.api.password,
project_domain_id=CONF.api.project_domain_name,
user_domain_id=CONF.api.project_domain_name)
# Send a notification.
retry_count = 0
while True:
try:
response = conn.ha.create_notification(
type=event['notification']['type'],
hostname=event['notification']['hostname'],
generated_time=event['notification']['generated_time'],
payload=event['notification']['payload'])
LOG.info(_LI("Response: %s"), response)
break
except Exception as e:
if retry_count < api_retry_max:
LOG.warning(_LW("Retry sending a notification. (%s)"), e)
retry_count = retry_count + 1
eventlet.greenthread.sleep(api_retry_interval)
else:
LOG.exception(_LE("Exception caught: %s"), e)
break

View File

@ -12,103 +12,22 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import time
from openstack import connection
from openstack import profile
from oslo_log import log as oslo_logging
from masakariclient.sdk.ha import ha_service
import masakarimonitors.conf
from masakarimonitors.i18n import _LE
from masakarimonitors.ha import masakari
from masakarimonitors.i18n import _LI
from masakarimonitors.i18n import _LW
LOG = oslo_logging.getLogger(__name__)
CONF = masakarimonitors.conf.CONF
TYPE = "ha"
NAME = "masakari"
class Callback(object):
"""Class of callback processing."""
def _get_connection(self, api_version, region, interface, auth_url,
project_name, username, password, project_domain_id,
user_domain_id):
prof = profile.Profile()
prof._add_service(ha_service.HAService(version=api_version))
prof.set_name(TYPE, NAME)
prof.set_region(TYPE, region)
prof.set_version(TYPE, api_version)
prof.set_interface(TYPE, interface)
conn = connection.Connection(auth_url=auth_url,
project_name=project_name,
username=username,
password=password,
project_domain_id=project_domain_id,
user_domain_id=user_domain_id,
profile=prof)
return conn
def _post_event(self, event):
type = event['notification']['type']
hostname = event['notification']['hostname']
generated_time = event['notification']['generated_time']
payload = event['notification']['payload']
LOG.info(_LI("Send notification for hostname '%(hostname)s',"
" type '%(type)s' ") % {'hostname': hostname,
'type': type})
# Set conf value.
project_domain_name = CONF.api.project_domain_name
project_name = CONF.api.project_name
username = CONF.api.username
password = CONF.api.password
auth_url = CONF.api.auth_url
region = CONF.api.region
interface = CONF.api.api_interface
api_version = CONF.api.api_version
retry_max = CONF.callback.retry_max
retry_interval = CONF.callback.retry_interval
conn = self._get_connection(
api_version=api_version, region=region,
interface=interface, auth_url=auth_url,
project_name=project_name, username=username,
password=password, project_domain_id=project_domain_name,
user_domain_id=project_domain_name)
retry_count = 0
while True:
try:
response = conn.ha.create_notification(
type=type,
hostname=hostname,
generated_time=generated_time,
payload=payload)
LOG.info(_LI("Notification response received : %s"), response)
break
except Exception as e:
# TODO(rkmrHonjo):
# We should determine retriable exceptions or not.
if retry_count < retry_max:
LOG.warning(_LW("Retry sending a notification. (%s)"), e)
retry_count = retry_count + 1
time.sleep(retry_interval)
else:
LOG.exception(_LE("Failed to send notification for type"
" '%(type)s' for hostname"
" '%(hostname)s'") %
{'type': type, 'hostname': hostname})
break
def __init__(self):
self.notifier = masakari.SendNotification()
def libvirt_event_callback(self, event_id, details, domain_uuid,
notice_type, hostname, current_time):
@ -153,4 +72,6 @@ class Callback(object):
}
}
self._post_event(event)
self.notifier.send_notification(CONF.callback.retry_max,
CONF.callback.retry_interval,
event)

View File

@ -23,6 +23,7 @@ from oslo_utils import timeutils
from masakarimonitors.instancemonitor.libvirt_handler import callback
from masakarimonitors.instancemonitor.libvirt_handler \
import eventfilter_table as evft
from masakarimonitors.objects import event_constants as ec
LOG = oslo_logging.getLogger(__name__)
@ -43,7 +44,7 @@ class EventFilter(object):
:pram uuID: UUID
"""
noticeType = 'VM'
noticeType = ec.EventConstants.TYPE_VM
hostname = socket.gethostname()
currentTime = timeutils.utcnow()

View File

View File

@ -0,0 +1,32 @@
# Copyright(c) 2016 Nippon Telegraph and Telephone Corporation
#
# 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.
class EventConstants(object):
# Define event types.
TYPE_PROCESS = "PROCESS"
TYPE_COMPUTE_HOST = "COMPUTE_HOST"
TYPE_VM = "VM"
# Define event details.
EVENT_STARTED = "STARTED"
EVENT_STOPPED = "STOPPED"
# Define host status.
HOST_STATUS_NORMAL = "NORMAL"
HOST_STATUS_UNKNOWN = "UNKNOWN"
# Define cluster status.
CLUSTER_STATUS_ONLINE = "ONLINE"
CLUSTER_STATUS_OFFLINE = "OFFLINE"