From: Benjamin Diaz Date: Mon, 26 Mar 2018 02:45:55 +0000 (-0300) Subject: Adds support for storing and getting vim creds X-Git-Tag: v4.0.0~27^2 X-Git-Url: https://osm.etsi.org/gitweb/?a=commitdiff_plain;h=refs%2Fchanges%2F11%2F5911%2F2;p=osm%2FMON.git Adds support for storing and getting vim creds Adds support for vim account create operation Adds local sqlite database Adds AuthManager and DatabaseManager classes Modifies integration tests Change-Id: I0609b53835be94c8c36c12df905e09ce14eff3a7 Signed-off-by: Benjamin Diaz --- diff --git a/.gitignore b/.gitignore index f4d6bb1..d994eb7 100644 --- a/.gitignore +++ b/.gitignore @@ -76,3 +76,4 @@ ChangeLog .settings/ __pycache__/ .idea +*.db \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 8d281ca..baf3976 100644 --- a/Dockerfile +++ b/Dockerfile @@ -29,7 +29,7 @@ RUN apt-get update && \ DEBIAN_FRONTEND=noninteractive pip install -U pip && \ DEBIAN_FRONTENT=noninteractive pip install -U requests logutils jsonschema lxml kafka mock && \ DEBIAN_FRONTEND=noninteractive pip install -U setuptools setuptools-version-command stdeb jsmin && \ - DEBIAN_FRONTEND=noninteractive pip install -U six pyvcloud bottle cherrypy pyopenssl && \ + DEBIAN_FRONTEND=noninteractive pip install -U six pyvcloud==18.2.* bottle cherrypy pyopenssl && \ DEBIAN_FRONTEND=noninteractive apt-get --yes install default-jre libmysqlclient-dev && \ DEBIAN_FRONTEND=noninteractive apt-get --yes install libmysqlclient-dev libxml2 && \ DEBIAN_FRONTEND=noninteractive pip install -U MySQL-python \ @@ -39,4 +39,5 @@ RUN apt-get update && \ gnocchiclient \ boto==2.48 \ python-cloudwatchlogs-logging \ - py-cloudwatch + py-cloudwatch \ + peewee==3.1.* diff --git a/doc/MON_install_guide.rst b/doc/MON_install_guide.rst index d086a82..5265e59 100644 --- a/doc/MON_install_guide.rst +++ b/doc/MON_install_guide.rst @@ -100,7 +100,7 @@ The following steps will allow you to use the plugins: :: - lxc exec MON -- nohup python /root/MON/osm_mon/core/message_bus/common_consumer & + lxc exec MON -- nohup python /root/MON/osm_mon/core/message_bus/common_consumer.py > /root/MON_plugins.log 2>&1 & * To enable Aodh alarm notifications to be sent to SO: diff --git a/osm_mon/core/auth.py b/osm_mon/core/auth.py new file mode 100644 index 0000000..bdc0498 --- /dev/null +++ b/osm_mon/core/auth.py @@ -0,0 +1,54 @@ +# -*- coding: utf-8 -*- + +# Copyright 2018 Whitestack, LLC +# ************************************************************* + +# This file is part of OSM Monitoring module +# All Rights Reserved to Whitestack, LLC + +# 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. + +# For those usages not covered by the Apache License, Version 2.0 please +# contact: bdiaz@whitestack.com or glavado@whitestack.com +## + +import json + +from osm_mon.core.database import VimCredentials, DatabaseManager + + +class AuthManager: + + def __init__(self): + self.database_manager = DatabaseManager() + + def store_auth_credentials(self, message): + values = json.loads(message.value) + credentials = VimCredentials() + credentials.uuid = values['_id'] + credentials.name = values['name'] + credentials.type = values['vim_type'] + credentials.url = values['vim_url'] + credentials.user = values['vim_user'] + credentials.password = values['vim_password'] + credentials.tenant_name = values['vim_tenant_name'] + credentials.config = json.dumps(values['config']) + self.database_manager.save_credentials(credentials) + + def get_credentials(self, vim_uuid): + return self.database_manager.get_credentials(vim_uuid) + + def delete_auth_credentials(self, message): + # TODO + pass + diff --git a/osm_mon/core/database.py b/osm_mon/core/database.py new file mode 100644 index 0000000..2191106 --- /dev/null +++ b/osm_mon/core/database.py @@ -0,0 +1,67 @@ +# -*- coding: utf-8 -*- + +# Copyright 2018 Whitestack, LLC +# ************************************************************* + +# This file is part of OSM Monitoring module +# All Rights Reserved to Whitestack, LLC + +# 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. + +# For those usages not covered by the Apache License, Version 2.0 please +# contact: bdiaz@whitestack.com or glavado@whitestack.com +## + +import logging + +from peewee import * +from playhouse.sqlite_ext import SqliteExtDatabase + +from osm_mon.plugins.OpenStack.settings import Config + +log = logging.getLogger(__name__) +cfg = Config.instance() + +db = SqliteExtDatabase('mon.db') + + +class BaseModel(Model): + class Meta: + database = db + + +class VimCredentials(BaseModel): + uuid = CharField() + name = CharField() + type = CharField() + url = CharField() + user = CharField() + password = CharField() + tenant_name = CharField() + config = TextField() + + +class DatabaseManager: + def create_tables(self): + try: + db.connect() + db.create_tables([VimCredentials]) + db.close() + except Exception as e: + log.exception("Error creating tables: ") + + def get_credentials(self, vim_uuid): + return VimCredentials.get(VimCredentials.uuid == vim_uuid) + + def save_credentials(self, vim_credentials): + vim_credentials.save() diff --git a/osm_mon/core/message_bus/common_consumer b/osm_mon/core/message_bus/common_consumer deleted file mode 100755 index efbb122..0000000 --- a/osm_mon/core/message_bus/common_consumer +++ /dev/null @@ -1,157 +0,0 @@ -# Copyright 2017 Intel Research and Development Ireland Limited -# ************************************************************* -# This file is part of OSM Monitoring module -# All Rights Reserved to Intel 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. -# -# For those usages not covered by the Apache License, Version 2.0 please -# contact: helena.mcgough@intel.com or adrian.hoban@intel.com -"""A common KafkaConsumer for all MON plugins.""" - -import json -import logging -import sys -import os - -sys.path.append("/root/MON") - -logging.basicConfig(filename='MON_plugins.log', - format='%(asctime)s %(message)s', - datefmt='%m/%d/%Y %I:%M:%S %p', filemode='a', - level=logging.INFO) -log = logging.getLogger(__name__) - -from kafka import KafkaConsumer -from kafka.errors import KafkaError - -from osm_mon.plugins.OpenStack.Aodh import alarming -from osm_mon.plugins.OpenStack.common import Common -from osm_mon.plugins.OpenStack.Gnocchi import metrics - -from osm_mon.plugins.CloudWatch.plugin_alarm import plugin_alarms -from osm_mon.plugins.CloudWatch.plugin_metric import plugin_metrics -from osm_mon.plugins.CloudWatch.connection import Connection -from osm_mon.plugins.CloudWatch.access_credentials import AccessCredentials - -from osm_mon.plugins.vRealiseOps import plugin_receiver - -# Initialize servers -if "BROKER_URI" in os.environ: - server = {'server': os.getenv("BROKER_URI")} -else: - server = {'server': 'localhost:9092'} - - - -# Initialize consumers for alarms and metrics -common_consumer = KafkaConsumer(bootstrap_servers=server['server']) - -# Create OpenStack alarming and metric instances -auth_token = None -openstack_auth = Common() -openstack_metrics = metrics.Metrics() -openstack_alarms = alarming.Alarming() - -# Create CloudWatch alarm and metric instances -cloudwatch_alarms = plugin_alarms() -cloudwatch_metrics = plugin_metrics() -aws_connection = Connection() -aws_access_credentials = AccessCredentials() - -#Create vROps plugin_receiver class instance -vrops_rcvr = plugin_receiver.PluginReceiver() - -def get_vim_type(message): - """Get the vim type that is required by the message.""" - try: - return json.loads(message.value)["vim_type"].lower() - except Exception as exc: - log.warn("vim_type is not configured correctly; %s", exc) - return None - -# Define subscribe the consumer for the plugins -topics = ['metric_request', 'alarm_request', 'access_credentials'] -common_consumer.subscribe(topics) - -try: - log.info("Listening for alarm_request and metric_request messages") - for message in common_consumer: - # Check the message topic - if message.topic == "metric_request": - # Check the vim desired by the message - vim_type = get_vim_type(message) - - if vim_type == "openstack": - log.info("This message is for the OpenStack plugin.") - openstack_metrics.metric_calls( - message, openstack_auth, auth_token) - - elif vim_type == "aws": - log.info("This message is for the CloudWatch plugin.") - aws_conn = aws_connection.setEnvironment() - cloudwatch_metrics.metric_calls(message,aws_conn) - - elif vim_type == "vmware": - log.info("This metric_request message is for the vROPs plugin.") - vrops_rcvr.consume(message) - - else: - log.debug("vim_type is misconfigured or unsupported; %s", - vim_type) - - elif message.topic == "alarm_request": - # Check the vim desired by the message - vim_type = get_vim_type(message) - if vim_type == "openstack": - log.info("This message is for the OpenStack plugin.") - openstack_alarms.alarming(message, openstack_auth, auth_token) - - elif vim_type == "aws": - log.info("This message is for the CloudWatch plugin.") - aws_conn = aws_connection.setEnvironment() - cloudwatch_alarms.alarm_calls(message, aws_conn) - - elif vim_type == "vmware": - log.info("This alarm_request message is for the vROPs plugin.") - vrops_rcvr.consume(message) - - else: - log.debug("vim_type is misconfigured or unsupported; %s", - vim_type) - - elif message.topic == "access_credentials": - # Check the vim desired by the message - vim_type = get_vim_type(message) - if vim_type == "openstack": - log.info("This message is for the OpenStack plugin.") - auth_token = openstack_auth._authenticate(message=message) - - elif vim_type == "aws": - log.info("This message is for the CloudWatch plugin.") - aws_access_credentials.access_credential_calls(message) - - elif vim_type == "vmware": - log.info("This access_credentials message is for the vROPs plugin.") - vrops_rcvr.consume(message) - - else: - log.debug("vim_type is misconfigured or unsupported; %s", - vim_type) - - else: - log.info("This topic is not relevant to any of the MON plugins.") - - -except KafkaError as exc: - log.warn("Exception: %s", exc) diff --git a/osm_mon/core/message_bus/common_consumer.py b/osm_mon/core/message_bus/common_consumer.py new file mode 100755 index 0000000..27a4188 --- /dev/null +++ b/osm_mon/core/message_bus/common_consumer.py @@ -0,0 +1,175 @@ +# Copyright 2017 Intel Research and Development Ireland Limited +# ************************************************************* +# This file is part of OSM Monitoring module +# All Rights Reserved to Intel 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. +# +# For those usages not covered by the Apache License, Version 2.0 please +# contact: helena.mcgough@intel.com or adrian.hoban@intel.com +"""A common KafkaConsumer for all MON plugins.""" + +import json +import logging +import os +import sys + +logging.basicConfig(stream=sys.stdout, + format='%(asctime)s %(message)s', + datefmt='%m/%d/%Y %I:%M:%S %p', + level=logging.INFO) +log = logging.getLogger(__name__) + +sys.path.append(os.path.abspath(os.path.join(os.path.realpath(__file__), '..', '..', '..', '..'))) + +from kafka import KafkaConsumer + +from osm_mon.plugins.OpenStack.Aodh import alarming +from osm_mon.plugins.OpenStack.common import Common +from osm_mon.plugins.OpenStack.Gnocchi import metrics + +from osm_mon.plugins.CloudWatch.plugin_alarm import plugin_alarms +from osm_mon.plugins.CloudWatch.plugin_metric import plugin_metrics +from osm_mon.plugins.CloudWatch.connection import Connection +from osm_mon.plugins.CloudWatch.access_credentials import AccessCredentials + +from osm_mon.plugins.vRealiseOps import plugin_receiver + +from osm_mon.core.auth import AuthManager +from osm_mon.core.database import DatabaseManager + +# Initialize servers +if "BROKER_URI" in os.environ: + server = {'server': os.getenv("BROKER_URI")} +else: + server = {'server': 'localhost:9092'} + +# Initialize consumers for alarms and metrics +common_consumer = KafkaConsumer(bootstrap_servers=server['server'], + key_deserializer=bytes.decode, + value_deserializer=bytes.decode, + group_id="mon-consumer") + +auth_manager = AuthManager() +database_manager = DatabaseManager() +database_manager.create_tables() + +# Create OpenStack alarming and metric instances +auth_token = None +openstack_auth = Common() +openstack_metrics = metrics.Metrics() +openstack_alarms = alarming.Alarming() + +# Create CloudWatch alarm and metric instances +cloudwatch_alarms = plugin_alarms() +cloudwatch_metrics = plugin_metrics() +aws_connection = Connection() +aws_access_credentials = AccessCredentials() + +# Create vROps plugin_receiver class instance +vrops_rcvr = plugin_receiver.PluginReceiver() + + +def get_vim_type(message): + """Get the vim type that is required by the message.""" + try: + return json.loads(message.value)["vim_type"].lower() + except Exception as exc: + log.warn("vim_type is not configured correctly; %s", exc) + return None + + +# Define subscribe the consumer for the plugins +topics = ['metric_request', 'alarm_request', 'access_credentials', 'vim_account'] +# TODO: Remove access_credentials +common_consumer.subscribe(topics) + +log.info("Listening for alarm_request and metric_request messages") +for message in common_consumer: + log.info("Message arrived: %s", message) + try: + # Check the message topic + if message.topic == "metric_request": + # Check the vim desired by the message + vim_type = get_vim_type(message) + + if vim_type == "openstack": + log.info("This message is for the OpenStack plugin.") + openstack_metrics.metric_calls( + message, openstack_auth, auth_token) + + elif vim_type == "aws": + log.info("This message is for the CloudWatch plugin.") + aws_conn = aws_connection.setEnvironment() + cloudwatch_metrics.metric_calls(message, aws_conn) + + elif vim_type == "vmware": + log.info("This metric_request message is for the vROPs plugin.") + vrops_rcvr.consume(message) + + else: + log.debug("vim_type is misconfigured or unsupported; %s", + vim_type) + + elif message.topic == "alarm_request": + # Check the vim desired by the message + vim_type = get_vim_type(message) + if vim_type == "openstack": + log.info("This message is for the OpenStack plugin.") + openstack_alarms.alarming(message, openstack_auth, auth_token) + + elif vim_type == "aws": + log.info("This message is for the CloudWatch plugin.") + aws_conn = aws_connection.setEnvironment() + cloudwatch_alarms.alarm_calls(message, aws_conn) + + elif vim_type == "vmware": + log.info("This alarm_request message is for the vROPs plugin.") + vrops_rcvr.consume(message) + + else: + log.debug("vim_type is misconfigured or unsupported; %s", + vim_type) + + elif message.topic == "vim_account": + if message.key == "create" or message.key == "edit": + auth_manager.store_auth_credentials(message) + if message.key == "delete": + auth_manager.delete_auth_credentials(message) + + # TODO: Remove in the near future. Modify tests accordingly. + elif message.topic == "access_credentials": + # Check the vim desired by the message + vim_type = get_vim_type(message) + if vim_type == "openstack": + log.info("This message is for the OpenStack plugin.") + auth_token = openstack_auth._authenticate(message=message) + + elif vim_type == "aws": + log.info("This message is for the CloudWatch plugin.") + aws_access_credentials.access_credential_calls(message) + + elif vim_type == "vmware": + log.info("This access_credentials message is for the vROPs plugin.") + vrops_rcvr.consume(message) + + else: + log.debug("vim_type is misconfigured or unsupported; %s", + vim_type) + + else: + log.info("This topic is not relevant to any of the MON plugins.") + + + except Exception as exc: + log.exception("Exception: %s") diff --git a/osm_mon/core/models/vim_account_create.json b/osm_mon/core/models/vim_account_create.json new file mode 100644 index 0000000..536e5cd --- /dev/null +++ b/osm_mon/core/models/vim_account_create.json @@ -0,0 +1,44 @@ +/* + Copyright 2018 Whitestack, LLC + ************************************************************* + + This file is part of OSM Monitoring module + All Rights Reserved to Whitestack, LLC + + 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. + + For those usages not covered by the Apache License, Version 2.0 please + contact: bdiaz@whitestack.com or glavado@whitestack.com +*/ +{ + "schema_version": { "type": "string" }, + "schema_type": { "type": "string" }, + "_id": { "type": "string" }, + "name": { "type": "string" }, + "description": { "type": "string" }, + "vim_type": { "type": "string" }, + "vim_url": { "type": "string" }, + "vim_user": { "type": "string" }, + "vim_password": { "type": "string" }, + "vim_tenant_name": { "type": "string" }, + "config": { "type":"object" }, + "required": [ "schema_version", + "schema_type", + "_id", + "name", + "vim_url", + "vim_type", + "vim_user", + "vim_password", + "vim_tenant_name" ] +} diff --git a/osm_mon/test/integration/__init__.py b/osm_mon/test/integration/__init__.py new file mode 100644 index 0000000..d81308a --- /dev/null +++ b/osm_mon/test/integration/__init__.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- + +# Copyright 2018 Whitestack, LLC +# ************************************************************* + +# This file is part of OSM Monitoring module +# All Rights Reserved to Whitestack, LLC + +# 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. + +# For those usages not covered by the Apache License, Version 2.0 please +# contact: bdiaz@whitestack.com or glavado@whitestack.com +## diff --git a/osm_mon/test/integration/test_access_cred.py b/osm_mon/test/integration/test_access_cred.py index 532a2f6..231711b 100644 --- a/osm_mon/test/integration/test_access_cred.py +++ b/osm_mon/test/integration/test_access_cred.py @@ -23,51 +23,59 @@ """Test an end to end Openstack access_credentials requests.""" import json - import logging +import unittest +import mock from kafka import KafkaConsumer from kafka import KafkaProducer - +from kafka.errors import KafkaError from keystoneclient.v3 import client -import mock - +from osm_mon.plugins.OpenStack.Aodh import alarming from osm_mon.plugins.OpenStack.common import Common log = logging.getLogger(__name__) -# Create an instance of the common openstack class, producer and consumer -openstack_auth = Common() - -producer = KafkaProducer(bootstrap_servers='localhost:9092') -req_consumer = KafkaConsumer(bootstrap_servers='localhost:9092', - group_id='osm_mon') -req_consumer.subscribe("access_credentials") - - -@mock.patch.object(client, "Client") -def test_access_cred_req(keyclient): - """Test access credentials request message from KafkaProducer.""" - # Set-up message, producer and consumer for tests - payload = {"vim_type": "OpenStack", - "access_config": - {"openstack_site": "my_site", - "user": "my_user", - "password": "my_password", - "vim_tenant_name": "my_tenant"}} - - producer.send('access_credentials', value=json.dumps(payload)) - - for message in req_consumer: - # Check the vim desired by the message - vim_type = json.loads(message.value)["vim_type"].lower() - if vim_type == "openstack": - openstack_auth._authenticate(message=message) - - # A keystone client is created with the valid access_credentials - keyclient.assert_called_with( - auth_url="my_site", username="my_user", password="my_password", - tenant_name="my_tenant") - return +# TODO: Remove this file +class AccessCredentialsTest(unittest.TestCase): + def setUp(self): + # Set up common and alarming class instances + self.alarms = alarming.Alarming() + self.openstack_auth = Common() + + try: + self.producer = KafkaProducer(bootstrap_servers='localhost:9092') + self.req_consumer = KafkaConsumer(bootstrap_servers='localhost:9092', + group_id='osm_mon', + consumer_timeout_ms=2000) + self.req_consumer.subscribe(['access_credentials']) + except KafkaError: + self.skipTest('Kafka server not present.') + + @mock.patch.object(client, "Client") + def test_access_cred_req(self, keyclient): + """Test access credentials request message from KafkaProducer.""" + # Set-up message, producer and consumer for tests + payload = {"vim_type": "OpenStack", + "access_config": + {"openstack_site": "my_site", + "user": "my_user", + "password": "my_password", + "vim_tenant_name": "my_tenant"}} + + self.producer.send('access_credentials', value=json.dumps(payload)) + + for message in self.req_consumer: + # Check the vim desired by the message + vim_type = json.loads(message.value)["vim_type"].lower() + if vim_type == "openstack": + self.openstack_auth._authenticate(message=message) + + # A keystone client is created with the valid access_credentials + keyclient.assert_called_with( + auth_url="my_site", username="my_user", password="my_password", + tenant_name="my_tenant") + + return diff --git a/osm_mon/test/integration/test_alarm_integration.py b/osm_mon/test/integration/test_alarm_integration.py index 489c307..13f0fef 100644 --- a/osm_mon/test/integration/test_alarm_integration.py +++ b/osm_mon/test/integration/test_alarm_integration.py @@ -23,182 +23,186 @@ """Test an end to end Openstack alarm requests.""" import json - import logging +import unittest -from osm_mon.core.message_bus.producer import KafkaProducer as prod - +import mock from kafka import KafkaConsumer from kafka import KafkaProducer +from kafka.errors import KafkaError -import mock - +from osm_mon.core.message_bus.producer import KafkaProducer as prod from osm_mon.plugins.OpenStack import response - from osm_mon.plugins.OpenStack.Aodh import alarming from osm_mon.plugins.OpenStack.common import Common log = logging.getLogger(__name__) -# Set up common and alarming class instances -alarms = alarming.Alarming() -openstack_auth = Common() - -# Initialise the alarm request consumer and a producer for testing -producer = KafkaProducer(bootstrap_servers='localhost:9092') -req_consumer = KafkaConsumer(bootstrap_servers='localhost:9092', - group_id='osm_mon') -req_consumer.subscribe("alarm_request") - - -@mock.patch.object(prod, "update_alarm_response") -@mock.patch.object(alarming.Alarming, "update_alarm") -@mock.patch.object(response.OpenStack_Response, "generate_response") -def test_update_alarm_req(resp, update_alarm, update_resp): - """Test Aodh update alarm request message from KafkaProducer.""" - # Set-up message, producer and consumer for tests - payload = {"vim_type": "OpenSTACK", - "alarm_update_request": - {"correlation_id": 123, - "alarm_uuid": "alarm_id", - "metric_uuid": "metric_id"}} - - producer.send('alarm_request', key="update_alarm_request", - value=json.dumps(payload)) - - for message in req_consumer: - # Check the vim desired by the message - vim_type = json.loads(message.value)["vim_type"].lower() - if vim_type == "openstack": - # Mock a valid alarm update - update_alarm.return_value = "alarm_id", True - alarms.alarming(message, openstack_auth, None) - - # A response message is generated and sent via MON's producer - resp.assert_called_with( - 'update_alarm_response', alarm_id="alarm_id", cor_id=123, - status=True) - update_resp.assert_called_with( - 'update_alarm_response', resp.return_value, 'alarm_response') - - return - - -@mock.patch.object(prod, "create_alarm_response") -@mock.patch.object(alarming.Alarming, "configure_alarm") -@mock.patch.object(response.OpenStack_Response, "generate_response") -def test_create_alarm_req(resp, config_alarm, create_resp): - """Test Aodh create alarm request message from KafkaProducer.""" - # Set-up message, producer and consumer for tests - payload = {"vim_type": "OpenSTACK", - "alarm_create_request": - {"correlation_id": 123, - "alarm_name": "my_alarm", - "metric_name": "my_metric", - "resource_uuid": "my_resource", - "severity": "WARNING"}} - - producer.send('alarm_request', key="create_alarm_request", - value=json.dumps(payload)) - - for message in req_consumer: - # Check the vim desired by the message - vim_type = json.loads(message.value)["vim_type"].lower() - if vim_type == "openstack": - # Mock a valid alarm creation - config_alarm.return_value = "alarm_id", True - alarms.alarming(message, openstack_auth, None) - - # A response message is generated and sent via MON's produce - resp.assert_called_with( - 'create_alarm_response', status=True, alarm_id="alarm_id", - cor_id=123) - create_resp.assert_called_with( - 'create_alarm_response', resp.return_value, 'alarm_response') - - return - - -@mock.patch.object(prod, "list_alarm_response") -@mock.patch.object(alarming.Alarming, "list_alarms") -@mock.patch.object(response.OpenStack_Response, "generate_response") -def test_list_alarm_req(resp, list_alarm, list_resp): - """Test Aodh list alarm request message from KafkaProducer.""" - # Set-up message, producer and consumer for tests - payload = {"vim_type": "OpenSTACK", - "alarm_list_request": - {"correlation_id": 123, - "resource_uuid": "resource_id", }} - - producer.send('alarm_request', key="list_alarm_request", - value=json.dumps(payload)) - - for message in req_consumer: - # Check the vim desired by the message - vim_type = json.loads(message.value)["vim_type"].lower() - if vim_type == "openstack": - # Mock an empty list generated by the request - list_alarm.return_value = [] - alarms.alarming(message, openstack_auth, None) - - # Resoonse message is generated - resp.assert_called_with( - 'list_alarm_response', alarm_list=[], - cor_id=123) - # Producer attempts to send the response message back to the SO - list_resp.assert_called_with( - 'list_alarm_response', resp.return_value, 'alarm_response') - - return - - -@mock.patch.object(alarming.Alarming, "delete_alarm") -@mock.patch.object(prod, "delete_alarm_response") -@mock.patch.object(response.OpenStack_Response, "generate_response") -def test_delete_alarm_req(resp, del_resp, del_alarm): - """Test Aodh delete alarm request message from KafkaProducer.""" - # Set-up message, producer and consumer for tests - payload = {"vim_type": "OpenSTACK", - "alarm_delete_request": - {"correlation_id": 123, - "alarm_uuid": "alarm_id", }} - - producer.send('alarm_request', key="delete_alarm_request", - value=json.dumps(payload)) - - for message in req_consumer: - # Check the vim desired by the message - vim_type = json.loads(message.value)["vim_type"].lower() - if vim_type == "openstack": - alarms.alarming(message, openstack_auth, None) - - # Response message is generated and sent by MON's producer - resp.assert_called_with( - 'delete_alarm_response', alarm_id="alarm_id", - status=del_alarm.return_value, cor_id=123) - del_resp.assert_called_with( - 'delete_alarm_response', resp.return_value, 'alarm_response') - - return - - -@mock.patch.object(alarming.Alarming, "update_alarm_state") -def test_ack_alarm_req(ack_alarm): - """Test Aodh acknowledge alarm request message from KafkaProducer.""" - # Set-up message, producer and consumer for tests - payload = {"vim_type": "OpenSTACK", - "ack_details": - {"alarm_uuid": "alarm_id", }} - - producer.send('alarm_request', key="acknowledge_alarm", - value=json.dumps(payload)) - - for message in req_consumer: - # Check the vim desired by the message - vim_type = json.loads(message.value)["vim_type"].lower() - if vim_type == "openstack": - alarms.alarming(message, openstack_auth, None) - # No response message is sent for and ack request - # Alarm state is updated from alarm -> ok - ack_alarm.assert_called_with(None, None, "alarm_id") - return + +class AlarmIntegrationTest(unittest.TestCase): + def setUp(self): + # Set up common and alarming class instances + self.alarms = alarming.Alarming() + self.openstack_auth = Common() + + try: + self.producer = KafkaProducer(bootstrap_servers='localhost:9092') + self.req_consumer = KafkaConsumer(bootstrap_servers='localhost:9092', + group_id='osm_mon', + consumer_timeout_ms=2000) + self.req_consumer.subscribe(['alarm_request']) + except KafkaError: + self.skipTest('Kafka server not present.') + + @mock.patch.object(prod, "update_alarm_response") + @mock.patch.object(alarming.Alarming, "update_alarm") + @mock.patch.object(response.OpenStack_Response, "generate_response") + def test_update_alarm_req(self, resp, update_alarm, update_resp): + """Test Aodh update alarm request message from KafkaProducer.""" + # Set-up message, producer and consumer for tests + payload = {"vim_type": "OpenSTACK", + "alarm_update_request": + {"correlation_id": 123, + "alarm_uuid": "alarm_id", + "metric_uuid": "metric_id"}} + + self.producer.send('alarm_request', key="update_alarm_request", + value=json.dumps(payload)) + + for message in self.req_consumer: + # Check the vim desired by the message + vim_type = json.loads(message.value)["vim_type"].lower() + if vim_type == "openstack": + # Mock a valid alarm update + update_alarm.return_value = "alarm_id", True + self.alarms.alarming(message, self.openstack_auth, None) + + # A response message is generated and sent via MON's producer + resp.assert_called_with( + 'update_alarm_response', alarm_id="alarm_id", cor_id=123, + status=True) + update_resp.assert_called_with( + 'update_alarm_response', resp.return_value, 'alarm_response') + + return + self.fail("No message received in consumer") + + @mock.patch.object(prod, "create_alarm_response") + @mock.patch.object(alarming.Alarming, "configure_alarm") + @mock.patch.object(response.OpenStack_Response, "generate_response") + def test_create_alarm_req(self, resp, config_alarm, create_resp): + """Test Aodh create alarm request message from KafkaProducer.""" + # Set-up message, producer and consumer for tests + payload = {"vim_type": "OpenSTACK", + "alarm_create_request": + {"correlation_id": 123, + "alarm_name": "my_alarm", + "metric_name": "my_metric", + "resource_uuid": "my_resource", + "severity": "WARNING"}} + + self.producer.send('alarm_request', key="create_alarm_request", + value=json.dumps(payload)) + + for message in self.req_consumer: + # Check the vim desired by the message + vim_type = json.loads(message.value)["vim_type"].lower() + if vim_type == "openstack": + # Mock a valid alarm creation + config_alarm.return_value = "alarm_id", True + self.alarms.alarming(message, self.openstack_auth, None) + + # A response message is generated and sent via MON's produce + resp.assert_called_with( + 'create_alarm_response', status=True, alarm_id="alarm_id", + cor_id=123) + create_resp.assert_called_with( + 'create_alarm_response', resp.return_value, 'alarm_response') + + return + self.fail("No message received in consumer") + + @mock.patch.object(prod, "list_alarm_response") + @mock.patch.object(alarming.Alarming, "list_alarms") + @mock.patch.object(response.OpenStack_Response, "generate_response") + def test_list_alarm_req(self, resp, list_alarm, list_resp): + """Test Aodh list alarm request message from KafkaProducer.""" + # Set-up message, producer and consumer for tests + payload = {"vim_type": "OpenSTACK", + "alarm_list_request": + {"correlation_id": 123, + "resource_uuid": "resource_id", }} + + self.producer.send('alarm_request', key="list_alarm_request", + value=json.dumps(payload)) + + for message in self.req_consumer: + # Check the vim desired by the message + vim_type = json.loads(message.value)["vim_type"].lower() + if vim_type == "openstack": + # Mock an empty list generated by the request + list_alarm.return_value = [] + self.alarms.alarming(message, self.openstack_auth, None) + + # Resoonse message is generated + resp.assert_called_with( + 'list_alarm_response', alarm_list=[], + cor_id=123) + # Producer attempts to send the response message back to the SO + list_resp.assert_called_with( + 'list_alarm_response', resp.return_value, 'alarm_response') + + return + self.fail("No message received in consumer") + + @mock.patch.object(alarming.Alarming, "delete_alarm") + @mock.patch.object(prod, "delete_alarm_response") + @mock.patch.object(response.OpenStack_Response, "generate_response") + def test_delete_alarm_req(self, resp, del_resp, del_alarm): + """Test Aodh delete alarm request message from KafkaProducer.""" + # Set-up message, producer and consumer for tests + payload = {"vim_type": "OpenSTACK", + "alarm_delete_request": + {"correlation_id": 123, + "alarm_uuid": "alarm_id", }} + + self.producer.send('alarm_request', key="delete_alarm_request", + value=json.dumps(payload)) + + for message in self.req_consumer: + # Check the vim desired by the message + vim_type = json.loads(message.value)["vim_type"].lower() + if vim_type == "openstack": + self.alarms.alarming(message, self.openstack_auth, None) + + # Response message is generated and sent by MON's producer + resp.assert_called_with( + 'delete_alarm_response', alarm_id="alarm_id", + status=del_alarm.return_value, cor_id=123) + del_resp.assert_called_with( + 'delete_alarm_response', resp.return_value, 'alarm_response') + + return + self.fail("No message received in consumer") + + @mock.patch.object(alarming.Alarming, "update_alarm_state") + def test_ack_alarm_req(self, ack_alarm): + """Test Aodh acknowledge alarm request message from KafkaProducer.""" + # Set-up message, producer and consumer for tests + payload = {"vim_type": "OpenSTACK", + "ack_details": + {"alarm_uuid": "alarm_id", }} + + self.producer.send('alarm_request', key="acknowledge_alarm", + value=json.dumps(payload)) + + for message in self.req_consumer: + # Check the vim desired by the message + vim_type = json.loads(message.value)["vim_type"].lower() + if vim_type == "openstack": + self.alarms.alarming(message, self.openstack_auth, None) + # No response message is sent for and ack request + # Alarm state is updated from alarm -> ok + ack_alarm.assert_called_with(None, None, "alarm_id") + return + self.fail("No message received in consumer") diff --git a/osm_mon/test/integration/test_metric_integration.py b/osm_mon/test/integration/test_metric_integration.py index 6c87dad..312359a 100644 --- a/osm_mon/test/integration/test_metric_integration.py +++ b/osm_mon/test/integration/test_metric_integration.py @@ -25,6 +25,9 @@ import json import logging +import unittest + +from kafka.errors import KafkaError from osm_mon.core.message_bus.producer import KafkaProducer as prod @@ -41,178 +44,184 @@ from osm_mon.plugins.OpenStack.common import Common log = logging.getLogger(__name__) -# Instances for the openstack common and metric classes -metric_req = metrics.Metrics() -openstack_auth = Common() - -# A metric_request consumer and a producer for testing purposes -producer = KafkaProducer(bootstrap_servers='localhost:9092') -req_consumer = KafkaConsumer(bootstrap_servers='localhost:9092', - group_id='osm_mon') -req_consumer.subscribe("metric_request") - - -@mock.patch.object(metrics.Metrics, "configure_metric") -@mock.patch.object(prod, "create_metrics_resp") -@mock.patch.object(response.OpenStack_Response, "generate_response") -def test_create_metric_req(resp, create_resp, config_metric): - """Test Gnocchi create metric request message from producer.""" - # Set-up message, producer and consumer for tests - payload = {"vim_type": "OpenSTACK", - "correlation_id": 123, - "metric_create": - {"metric_name": "my_metric", - "resource_uuid": "resource_id"}} - - producer.send('metric_request', key="create_metric_request", - value=json.dumps(payload)) - - for message in req_consumer: - # Check the vim desired by the message - vim_type = json.loads(message.value)["vim_type"].lower() - if vim_type == "openstack": - # A valid metric is created - config_metric.return_value = "metric_id", "resource_id", True - metric_req.metric_calls(message, openstack_auth, None) - - # A response message is generated and sent by MON's producer - resp.assert_called_with( - 'create_metric_response', status=True, cor_id=123, - metric_id="metric_id", r_id="resource_id") - create_resp.assert_called_with( - 'create_metric_response', resp.return_value, 'metric_response') - - return - - -@mock.patch.object(metrics.Metrics, "delete_metric") -@mock.patch.object(prod, "delete_metric_response") -@mock.patch.object(response.OpenStack_Response, "generate_response") -def test_delete_metric_req(resp, del_resp, del_metric): - """Test Gnocchi delete metric request message from producer.""" - # Set-up message, producer and consumer for tests - payload = {"vim_type": "OpenSTACK", - "correlation_id": 123, - "metric_uuid": "metric_id", - "metric_name": "metric_name", - "resource_uuid": "resource_id"} - - producer.send('metric_request', key="delete_metric_request", - value=json.dumps(payload)) - - for message in req_consumer: - # Check the vim desired by the message - vim_type = json.loads(message.value)["vim_type"].lower() - if vim_type == "openstack": - # Metric has been deleted - del_metric.return_value = True - metric_req.metric_calls(message, openstack_auth, None) - - # A response message is generated and sent by MON's producer - resp.assert_called_with( - 'delete_metric_response', m_id="metric_id", - m_name="metric_name", status=True, r_id="resource_id", - cor_id=123) - del_resp.assert_called_with( - 'delete_metric_response', resp.return_value, 'metric_response') - - return - - -@mock.patch.object(metrics.Metrics, "read_metric_data") -@mock.patch.object(prod, "read_metric_data_response") -@mock.patch.object(response.OpenStack_Response, "generate_response") -def test_read_metric_data_req(resp, read_resp, read_data): - """Test Gnocchi read metric data request message from producer.""" - # Set-up message, producer and consumer for tests - payload = {"vim_type": "OpenSTACK", - "correlation_id": 123, - "metric_uuid": "metric_id", - "metric_name": "metric_name", - "resource_uuid": "resource_id"} - - producer.send('metric_request', key="read_metric_data_request", - value=json.dumps(payload)) - - for message in req_consumer: - # Check the vim desired by the message - vim_type = json.loads(message.value)["vim_type"].lower() - if vim_type == "openstack": - # Mock empty lists generated by the request message - read_data.return_value = [], [] - metric_req.metric_calls(message, openstack_auth, None) - - # A response message is generated and sent by MON's producer - resp.assert_called_with( - 'read_metric_data_response', m_id="metric_id", - m_name="metric_name", r_id="resource_id", cor_id=123, times=[], - metrics=[]) - read_resp.assert_called_with( - 'read_metric_data_response', resp.return_value, - 'metric_response') - - return - - -@mock.patch.object(metrics.Metrics, "list_metrics") -@mock.patch.object(prod, "list_metric_response") -@mock.patch.object(response.OpenStack_Response, "generate_response") -def test_list_metrics_req(resp, list_resp, list_metrics): - """Test Gnocchi list metrics request message from producer.""" - # Set-up message, producer and consumer for tests - payload = {"vim_type": "OpenSTACK", - "metrics_list_request": - {"correlation_id": 123, }} - - producer.send('metric_request', key="list_metric_request", - value=json.dumps(payload)) - - for message in req_consumer: - # Check the vim desired by the message - vim_type = json.loads(message.value)["vim_type"].lower() - if vim_type == "openstack": - # Mock an empty list generated by the request - list_metrics.return_value = [] - metric_req.metric_calls(message, openstack_auth, None) - - # A response message is generated and sent by MON's producer - resp.assert_called_with( - 'list_metric_response', m_list=[], cor_id=123) - list_resp.assert_called_with( - 'list_metric_response', resp.return_value, 'metric_response') - - return - - -@mock.patch.object(metrics.Metrics, "get_metric_id") -@mock.patch.object(prod, "update_metric_response") -@mock.patch.object(response.OpenStack_Response, "generate_response") -def test_update_metrics_req(resp, update_resp, get_id): - """Test Gnocchi update metric request message from KafkaProducer.""" - # Set-up message, producer and consumer for tests - payload = {"vim_type": "OpenSTACK", - "correlation_id": 123, - "metric_create": - {"metric_name": "my_metric", - "resource_uuid": "resource_id", }} - - producer.send('metric_request', key="update_metric_request", - value=json.dumps(payload)) - - for message in req_consumer: - # Check the vim desired by the message - vim_type = json.loads(message.value)["vim_type"].lower() - if vim_type == "openstack": - # Gnocchi doesn't support metric updates - get_id.return_value = "metric_id" - metric_req.metric_calls(message, openstack_auth, None) - - # Reponse message is generated and sent via MON's producer - # No metric update has taken place - resp.assert_called_with( - 'update_metric_response', status=False, cor_id=123, - r_id="resource_id", m_id="metric_id") - update_resp.assert_called_with( - 'update_metric_response', resp.return_value, 'metric_response') - - return + +class MetricIntegrationTest(unittest.TestCase): + def setUp(self): + # Set up common and alarming class instances + self.metric_req = metrics.Metrics() + self.openstack_auth = Common() + + try: + self.producer = KafkaProducer(bootstrap_servers='localhost:9092') + self.req_consumer = KafkaConsumer(bootstrap_servers='localhost:9092', + group_id='osm_mon', + consumer_timeout_ms=2000) + self.req_consumer.subscribe(['metric_request']) + except KafkaError: + self.skipTest('Kafka server not present.') + + @mock.patch.object(metrics.Metrics, "configure_metric") + @mock.patch.object(prod, "create_metrics_resp") + @mock.patch.object(response.OpenStack_Response, "generate_response") + def test_create_metric_req(self, resp, create_resp, config_metric): + """Test Gnocchi create metric request message from producer.""" + # Set-up message, producer and consumer for tests + payload = {"vim_type": "OpenSTACK", + "correlation_id": 123, + "metric_create": + {"metric_name": "my_metric", + "resource_uuid": "resource_id"}} + + self.producer.send('metric_request', key="create_metric_request", + value=json.dumps(payload)) + + for message in self.req_consumer: + # Check the vim desired by the message + vim_type = json.loads(message.value)["vim_type"].lower() + if vim_type == "openstack": + # A valid metric is created + config_metric.return_value = "metric_id", "resource_id", True + self.metric_req.metric_calls(message, self.openstack_auth, None) + + # A response message is generated and sent by MON's producer + resp.assert_called_with( + 'create_metric_response', status=True, cor_id=123, + metric_id="metric_id", r_id="resource_id") + create_resp.assert_called_with( + 'create_metric_response', resp.return_value, 'metric_response') + + return + self.fail("No message received in consumer") + + @mock.patch.object(metrics.Metrics, "delete_metric") + @mock.patch.object(prod, "delete_metric_response") + @mock.patch.object(response.OpenStack_Response, "generate_response") + def test_delete_metric_req(self, resp, del_resp, del_metric): + """Test Gnocchi delete metric request message from producer.""" + # Set-up message, producer and consumer for tests + payload = {"vim_type": "OpenSTACK", + "correlation_id": 123, + "metric_uuid": "metric_id", + "metric_name": "metric_name", + "resource_uuid": "resource_id"} + + self.producer.send('metric_request', key="delete_metric_request", + value=json.dumps(payload)) + + for message in self.req_consumer: + # Check the vim desired by the message + vim_type = json.loads(message.value)["vim_type"].lower() + if vim_type == "openstack": + # Metric has been deleted + del_metric.return_value = True + self.metric_req.metric_calls(message, self.openstack_auth, None) + + # A response message is generated and sent by MON's producer + resp.assert_called_with( + 'delete_metric_response', m_id="metric_id", + m_name="metric_name", status=True, r_id="resource_id", + cor_id=123) + del_resp.assert_called_with( + 'delete_metric_response', resp.return_value, 'metric_response') + + return + self.fail("No message received in consumer") + + @mock.patch.object(metrics.Metrics, "read_metric_data") + @mock.patch.object(prod, "read_metric_data_response") + @mock.patch.object(response.OpenStack_Response, "generate_response") + def test_read_metric_data_req(self, resp, read_resp, read_data): + """Test Gnocchi read metric data request message from producer.""" + # Set-up message, producer and consumer for tests + payload = {"vim_type": "OpenSTACK", + "correlation_id": 123, + "metric_uuid": "metric_id", + "metric_name": "metric_name", + "resource_uuid": "resource_id"} + + self.producer.send('metric_request', key="read_metric_data_request", + value=json.dumps(payload)) + + for message in self.req_consumer: + # Check the vim desired by the message + vim_type = json.loads(message.value)["vim_type"].lower() + if vim_type == "openstack": + # Mock empty lists generated by the request message + read_data.return_value = [], [] + self.metric_req.metric_calls(message, self.openstack_auth, None) + + # A response message is generated and sent by MON's producer + resp.assert_called_with( + 'read_metric_data_response', m_id="metric_id", + m_name="metric_name", r_id="resource_id", cor_id=123, times=[], + metrics=[]) + read_resp.assert_called_with( + 'read_metric_data_response', resp.return_value, + 'metric_response') + + return + self.fail("No message received in consumer") + + @mock.patch.object(metrics.Metrics, "list_metrics") + @mock.patch.object(prod, "list_metric_response") + @mock.patch.object(response.OpenStack_Response, "generate_response") + def test_list_metrics_req(self, resp, list_resp, list_metrics): + """Test Gnocchi list metrics request message from producer.""" + # Set-up message, producer and consumer for tests + payload = {"vim_type": "OpenSTACK", + "metrics_list_request": + {"correlation_id": 123, }} + + self.producer.send('metric_request', key="list_metric_request", + value=json.dumps(payload)) + + for message in self.req_consumer: + # Check the vim desired by the message + vim_type = json.loads(message.value)["vim_type"].lower() + if vim_type == "openstack": + # Mock an empty list generated by the request + list_metrics.return_value = [] + self.metric_req.metric_calls(message, self.openstack_auth, None) + + # A response message is generated and sent by MON's producer + resp.assert_called_with( + 'list_metric_response', m_list=[], cor_id=123) + list_resp.assert_called_with( + 'list_metric_response', resp.return_value, 'metric_response') + + return + self.fail("No message received in consumer") + + @mock.patch.object(metrics.Metrics, "get_metric_id") + @mock.patch.object(prod, "update_metric_response") + @mock.patch.object(response.OpenStack_Response, "generate_response") + def test_update_metrics_req(self, resp, update_resp, get_id): + """Test Gnocchi update metric request message from KafkaProducer.""" + # Set-up message, producer and consumer for tests + payload = {"vim_type": "OpenSTACK", + "correlation_id": 123, + "metric_create": + {"metric_name": "my_metric", + "resource_uuid": "resource_id", }} + + self.producer.send('metric_request', key="update_metric_request", + value=json.dumps(payload)) + + for message in self.req_consumer: + # Check the vim desired by the message + vim_type = json.loads(message.value)["vim_type"].lower() + if vim_type == "openstack": + # Gnocchi doesn't support metric updates + get_id.return_value = "metric_id" + self.metric_req.metric_calls(message, self.openstack_auth, None) + + # Reponse message is generated and sent via MON's producer + # No metric update has taken place + resp.assert_called_with( + 'update_metric_response', status=False, cor_id=123, + r_id="resource_id", m_id="metric_id") + update_resp.assert_called_with( + 'update_metric_response', resp.return_value, 'metric_response') + + return + self.fail("No message received in consumer") diff --git a/osm_mon/test/integration/test_notify_alarm.py b/osm_mon/test/integration/test_notify_alarm.py index 519624f..96458ba 100644 --- a/osm_mon/test/integration/test_notify_alarm.py +++ b/osm_mon/test/integration/test_notify_alarm.py @@ -26,6 +26,7 @@ import json import logging import socket +import unittest from BaseHTTPServer import BaseHTTPRequestHandler from BaseHTTPServer import HTTPServer @@ -72,7 +73,7 @@ class MockNotifierHandler(BaseHTTPRequestHandler): def do_GET(self): """Mock functionality for GET request.""" -# self.send_response(requests.codes.ok) + # self.send_response(requests.codes.ok) self._set_headers() pass @@ -152,38 +153,39 @@ def test_do_get(): assert response.ok -@mock.patch.object(KafkaProducer, "notify_alarm") -@mock.patch.object(OpenStack_Response, "generate_response") -@mock.patch.object(Common, "_perform_request") -@mock.patch.object(Common, "get_endpoint") -@mock.patch.object(Common, "_authenticate") -def test_post_notify_alarm(auth, endpoint, perf_req, resp, notify): - """Integration test for notify_alarm.""" - url = 'http://localhost:{port}/users'.format(port=mock_server_port) - payload = {"severity": "critical", - "alarm_name": "my_alarm", - "current": "current_state", - "alarm_id": "my_alarm_id", - "reason": "Threshold has been broken", - "reason_data": {"count": 1, - "most_recent": "null", - "type": "threshold", - "disposition": "unknown"}, - "previous": "previous_state"} - - # Mock authenticate and request response for testing - auth.return_value = "my_auth_token" - endpoint.return_value = "my_endpoint" - perf_req.return_value = MockResponse(valid_get_resp) - - # Generate a post reqest for testing - requests.post(url, json.dumps(payload)) - - # A response message is generated with the following details - resp.assert_called_with( - "notify_alarm", a_id="my_alarm_id", r_id="my_resource_id", - sev="critical", date='dd-mm-yyyy 00:00', state="current_state", - vim_type="OpenStack") - - # Reponse message is sent back to the SO via MON's producer - notify.assert_called_with("notify_alarm", mock.ANY, "alarm_response") +class AlarmNotificationTest(unittest.TestCase): + @mock.patch.object(KafkaProducer, "notify_alarm") + @mock.patch.object(OpenStack_Response, "generate_response") + @mock.patch.object(Common, "_perform_request") + @mock.patch.object(Common, "get_endpoint") + @mock.patch.object(Common, "_authenticate") + def test_post_notify_alarm(self, auth, endpoint, perf_req, resp, notify): + """Integration test for notify_alarm.""" + url = 'http://localhost:{port}/users'.format(port=mock_server_port) + payload = {"severity": "critical", + "alarm_name": "my_alarm", + "current": "current_state", + "alarm_id": "my_alarm_id", + "reason": "Threshold has been broken", + "reason_data": {"count": 1, + "most_recent": "null", + "type": "threshold", + "disposition": "unknown"}, + "previous": "previous_state"} + + # Mock authenticate and request response for testing + auth.return_value = "my_auth_token" + endpoint.return_value = "my_endpoint" + perf_req.return_value = MockResponse(valid_get_resp) + + # Generate a post reqest for testing + requests.post(url, json.dumps(payload)) + + # A response message is generated with the following details + resp.assert_called_with( + "notify_alarm", a_id="my_alarm_id", r_id="my_resource_id", + sev="critical", date='dd-mm-yyyy 00:00', state="current_state", + vim_type="OpenStack") + + # Reponse message is sent back to the SO via MON's producer + notify.assert_called_with("notify_alarm", mock.ANY, "alarm_response") diff --git a/osm_mon/test/integration/test_vim_account.py b/osm_mon/test/integration/test_vim_account.py new file mode 100644 index 0000000..bc610c3 --- /dev/null +++ b/osm_mon/test/integration/test_vim_account.py @@ -0,0 +1,77 @@ +# -*- coding: utf-8 -*- + +# Copyright 2018 Whitestack, LLC +# ************************************************************* + +# This file is part of OSM Monitoring module +# All Rights Reserved to Whitestack, LLC + +# 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. + +# For those usages not covered by the Apache License, Version 2.0 please +# contact: bdiaz@whitestack.com or glavado@whitestack.com +## + +"""Test an end to end Openstack vim_account requests.""" + +import json +import logging +import time +import unittest + +from kafka import KafkaConsumer +from kafka import KafkaProducer +from kafka.errors import KafkaError + +from osm_mon.core.auth import AuthManager + +log = logging.getLogger(__name__) + + +class VimAccountTest(unittest.TestCase): + def setUp(self): + try: + self.producer = KafkaProducer(bootstrap_servers='localhost:9092') + self.consumer = KafkaConsumer(bootstrap_servers='localhost:9092', + group_id='osm_mon') + self.consumer.subscribe(['vim_account']) + self.auth_manager = AuthManager() + except KafkaError: + self.skipTest('Kafka server not present.') + + def test_create_vim_account(self): + """Test vim_account creation message from KafkaProducer.""" + # Set-up message, producer and consumer for tests + payload = { + "_id": "test_id", + "name": "test_name", + "vim_type": "openstack", + "vim_url": "auth_url", + "vim_user": "user", + "vim_password": "password", + "vim_tenant_name": "tenant", + "config": + { + "foo": "bar" + } + } + + self.producer.send('vim_account', key=b'create', value=json.dumps(payload)) + + self.producer.flush() + + # FIXME: Create a schema for a vim_account_create_response, so we can test it + time.sleep(5) + creds = self.auth_manager.get_credentials(payload['_id']) + self.assertEqual(creds.name, payload['name']) + self.assertEqual(json.loads(creds.config), payload['config']) diff --git a/requirements.txt b/requirements.txt index 92faf90..bad8167 100644 --- a/requirements.txt +++ b/requirements.txt @@ -18,7 +18,7 @@ # For those usages not covered by the Apache License, Version 2.0 please # contact: prithiv.mohan@intel.com or adrian.hoban@intel.com - +peewee stdeb MySQL-python kafka @@ -37,7 +37,8 @@ gnocchiclient boto==2.48 python-cloudwatchlogs-logging py-cloudwatch -pyvcloud +pyvcloud==18.2.* pyopenssl six bottle +peewee==3.1.* diff --git a/setup.py b/setup.py index b91ff35..163d17f 100644 --- a/setup.py +++ b/setup.py @@ -50,6 +50,6 @@ setup(name="osm_mon", data_files = [('/etc/systemd/system/', ['scripts/kafka.sh']), ], scripts=['osm_mon/plugins/vRealiseOps/vROPs_Webservice/vrops_webservice', - 'kafkad', 'osm_mon/core/message_bus/common_consumer'], + 'kafkad', 'osm_mon/core/message_bus/common_consumer.py'], include_package_data=True, )