Merge "Handle Heat notifications for stack CRUD"

This commit is contained in:
Jenkins 2014-02-19 17:35:55 +00:00 committed by Gerrit Code Review
commit 71d78e7bf2
8 changed files with 247 additions and 0 deletions

View File

View File

@ -0,0 +1,76 @@
# Author: Swann Croiset <swann.croiset@bull.net>
#
# 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.
"""Handler for producing orchestration metering from Heat notification
events.
"""
from oslo.config import cfg
from ceilometer import plugin
from ceilometer import sample
OPTS = [
cfg.StrOpt('heat_control_exchange',
default='heat',
help="Exchange name for Heat notifications"),
]
cfg.CONF.register_opts(OPTS)
SERVICE = 'orchestration'
class StackCRUD(plugin.NotificationBase):
resource_name = '%s.stack' % SERVICE
@property
def event_types(self):
return [
'%s.create.end' % (self.resource_name),
'%s.update.end' % (self.resource_name),
'%s.delete.end' % (self.resource_name),
'%s.resume.end' % (self.resource_name),
'%s.suspend.end' % (self.resource_name),
]
@staticmethod
def get_exchange_topics(conf):
return [
plugin.ExchangeTopics(
exchange=conf.heat_control_exchange,
topics=set(topic + ".info"
for topic in conf.notification_topics)),
]
def process_notification(self, message):
name = message['event_type'] \
.replace(self.resource_name, 'stack') \
.replace('.end', '')
project_id = message['payload']['tenant_id']
# Trying to use the trustor_id if trusts is used by Heat,
user_id = message.get('_context_trustor_user_id') or \
message['_context_user_id']
yield sample.Sample.from_notification(
name=name,
type=sample.TYPE_DELTA,
unit='stack',
volume=1,
resource_id=message['payload']['stack_identity'],
user_id=user_id,
project_id=project_id,
message=message)

View File

@ -0,0 +1,130 @@
# Author: Swann Croiset <swann.croiset@bull.net>
#
# 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 datetime
from oslo.config import cfg
from ceilometer.openstack.common import test
from ceilometer.orchestration import notifications
from ceilometer import sample
NOW = datetime.datetime.isoformat(datetime.datetime.utcnow())
TENANT_ID = u'4c35985848bf4419b3f3d52c22e5792d'
STACK_NAME = u'AS1-ASGroup-53sqbo7sor7i'
STACK_ID = u'cb4a6fd1-1f5d-4002-ae91-9b91573cfb03'
USER_NAME = u'demo'
USER_ID = u'2e61f25ec63a4f6c954a6245421448a4'
TRUSTOR_ID = u'foo-Trustor-Id'
STACK_ARN = u'arn:openstack:heat::%s:stacks/%s/%s' % (TENANT_ID,
STACK_NAME,
STACK_ID)
CONF = cfg.CONF
CONF.set_override('use_stderr', True)
from ceilometer.openstack.common import log
LOG = log.getLogger(__name__)
def stack_notification_for(operation, use_trust=None):
if use_trust:
trust_id = 'footrust'
trustor_id = TRUSTOR_ID
else:
trust_id = None
trustor_id = None
return {
u'event_type': '%s.stack.%s.end' % (notifications.SERVICE,
operation),
u'_context_roles': [
u'Member',
],
u'_context_request_id': u'req-cf24cf30-af35-4a47-ae29-e74d75ebc6de',
u'_context_auth_url': u'http://0.1.0.1:1010/v2.0',
u'timestamp': NOW,
u'_unique_id': u'1afb4283660f410c802af4d5992a39f2',
u'_context_tenant_id': TENANT_ID,
u'payload': {
u'state_reason': u'Stack create completed successfully',
u'user_id': USER_NAME,
u'stack_identity': STACK_ARN,
u'stack_name': STACK_NAME,
u'tenant_id': TENANT_ID,
u'create_at': u'2014-01-27T13:13:19Z',
u'state': u'CREATE_COMPLETE'
},
u'_context_username': USER_NAME,
u'_context_auth_token': u'MIISAwYJKoZIhvcNAQcCoII...',
u'_context_password': u'password',
u'_context_user_id': USER_ID,
u'_context_trustor_user_id': trustor_id,
u'_context_aws_creds': None,
u'_context_show_deleted': False,
u'_context_tenant': USER_NAME,
u'_context_trust_id': trust_id,
u'priority': u'INFO',
u'_context_is_admin': False,
u'_context_user': USER_NAME,
u'publisher_id': u'orchestration.node-n5x66lxdy67d',
u'message_id': u'ef921faa-7f7b-4854-8b86-a424ab93c96e',
}
class TestNotification(test.BaseTestCase):
def _verify_common_sample(self, s, name, volume):
self.assertIsNotNone(s)
self.assertEqual(s.name, 'stack.%s' % name)
self.assertEqual(s.timestamp, NOW)
self.assertEqual(s.type, sample.TYPE_DELTA)
self.assertEqual(s.project_id, TENANT_ID)
self.assertEqual(s.resource_id, STACK_ARN)
metadata = s.resource_metadata
self.assertEqual(metadata.get('host'),
u'orchestration.node-n5x66lxdy67d')
def _test_operation(self, operation, trust=None):
notif = stack_notification_for(operation, trust)
handler = notifications.StackCRUD()
data = list(handler.process_notification(notif))
self.assertEqual(len(data), 1)
if trust:
self.assertEqual(data[0].user_id, TRUSTOR_ID)
else:
self.assertEqual(data[0].user_id, USER_ID)
self._verify_common_sample(data[0], operation, 1)
def test_create(self):
self._test_operation('create')
def test_create_trust(self):
self._test_operation('create', trust=True)
def test_update(self):
self._test_operation('update')
def test_delete(self):
self._test_operation('delete')
def test_resume(self):
self._test_operation('resume')
def test_suspend(self):
self._test_operation('suspend')

View File

@ -467,6 +467,23 @@ Configuring keystone to work with API
default port value for ceilometer API is 8777. If the port value default port value for ceilometer API is 8777. If the port value
has been customized, adjust accordingly. has been customized, adjust accordingly.
Configuring Heat to send notifications
======================================
Configure the driver in ``heat.conf``
::
notification_driver=heat.openstack.common.notifier.rpc_notifier
Or if migration to oslo.messaging is done for Icehouse:
::
notification_driver=oslo.messaging.notifier.Notifier
Notifications queues Notifications queues
======================== ========================

View File

@ -170,6 +170,21 @@ Swift as described in :ref:`installing_manually`. Note that they may not be
updated right after an upload/download, since Swift takes some time to update updated right after an upload/download, since Swift takes some time to update
the container properties. the container properties.
Orchestration (Heat)
====================
=============================== ========== ========== =========== ============ ==========================================
Name Type Unit Resource Origin Note
=============================== ========== ========== =========== ============ ==========================================
stack.create Delta stack stack ID notification Creation requests for a stack successful
stack.update Delta stack stack ID notification Updating requests for a stack successful
stack.delete Delta stack stack ID notification Deletion requests for a stack successful
stack.resume Delta stack stack ID notification Resuming requests for a stack successful
stack.suspend Delta stack stack ID notification Suspending requests for a stack successful
=============================== ========== ========== =========== ============ ==========================================
To enable Heat notifications configure Heat as described in :ref:`installing_manually`.
Energy (Kwapi) Energy (Kwapi)
============== ==============

View File

@ -486,6 +486,14 @@
#matchmaker_heartbeat_ttl=600 #matchmaker_heartbeat_ttl=600
#
# Options defined in ceilometer.orchestration.notifications
#
# Exchange name for Heat notifications (string value)
#heat_control_exchange=heat
# #
# Options defined in ceilometer.storage # Options defined in ceilometer.storage
# #

View File

@ -62,6 +62,7 @@ ceilometer.notification =
bandwidth = ceilometer.network.notifications:Bandwidth bandwidth = ceilometer.network.notifications:Bandwidth
http.request = ceilometer.middleware:HTTPRequest http.request = ceilometer.middleware:HTTPRequest
http.response = ceilometer.middleware:HTTPResponse http.response = ceilometer.middleware:HTTPResponse
stack_crud = ceilometer.orchestration.notifications:StackCRUD
ceilometer.poll.compute = ceilometer.poll.compute =
disk.read.requests = ceilometer.compute.pollsters.disk:ReadRequestsPollster disk.read.requests = ceilometer.compute.pollsters.disk:ReadRequestsPollster