Adds support for storing and getting vim creds 11/5911/2
authorBenjamin Diaz <bdiaz@whitestack.com>
Mon, 26 Mar 2018 02:45:55 +0000 (23:45 -0300)
committerBenjamin Diaz <bdiaz@whitestack.com>
Mon, 26 Mar 2018 18:00:49 +0000 (15:00 -0300)
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 <bdiaz@whitestack.com>
16 files changed:
.gitignore
Dockerfile
doc/MON_install_guide.rst
osm_mon/core/auth.py [new file with mode: 0644]
osm_mon/core/database.py [new file with mode: 0644]
osm_mon/core/message_bus/common_consumer [deleted file]
osm_mon/core/message_bus/common_consumer.py [new file with mode: 0755]
osm_mon/core/models/vim_account_create.json [new file with mode: 0644]
osm_mon/test/integration/__init__.py [new file with mode: 0644]
osm_mon/test/integration/test_access_cred.py
osm_mon/test/integration/test_alarm_integration.py
osm_mon/test/integration/test_metric_integration.py
osm_mon/test/integration/test_notify_alarm.py
osm_mon/test/integration/test_vim_account.py [new file with mode: 0644]
requirements.txt
setup.py

index f4d6bb1..d994eb7 100644 (file)
@@ -76,3 +76,4 @@ ChangeLog
 .settings/
 __pycache__/
 .idea
+*.db
\ No newline at end of file
index 8d281ca..baf3976 100644 (file)
@@ -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.*
index d086a82..5265e59 100644 (file)
@@ -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 (file)
index 0000000..bdc0498
--- /dev/null
@@ -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 (file)
index 0000000..2191106
--- /dev/null
@@ -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 (executable)
index efbb122..0000000
+++ /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 (executable)
index 0000000..27a4188
--- /dev/null
@@ -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 (file)
index 0000000..536e5cd
--- /dev/null
@@ -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 (file)
index 0000000..d81308a
--- /dev/null
@@ -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
+##
index 532a2f6..231711b 100644 (file)
 """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
index 489c307..13f0fef 100644 (file)
 """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")
index 6c87dad..312359a 100644 (file)
@@ -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")
index 519624f..96458ba 100644 (file)
@@ -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 (file)
index 0000000..bc610c3
--- /dev/null
@@ -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'])
index 92faf90..bad8167 100644 (file)
@@ -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.*
index b91ff35..163d17f 100644 (file)
--- 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,
       )