Adds collection of vim status metric
Current support is only OpenStack. It tries to do a simple project list query
to check if VIM is up or not.
Change-Id: Ifec844d9514b6c676b065fee7cf785bdf2a2ea3d
Signed-off-by: Benjamin Diaz <bdiaz@whitestack.com>
diff --git a/osm_mon/cmd/mon_collector.py b/osm_mon/cmd/mon_collector.py
index 6389d49..c4e2969 100644
--- a/osm_mon/cmd/mon_collector.py
+++ b/osm_mon/cmd/mon_collector.py
@@ -25,6 +25,7 @@
import sys
from osm_mon.collector.collector import Collector
+from osm_mon.core.database import DatabaseManager
from osm_mon.core.settings import Config
@@ -45,6 +46,10 @@
log = logging.getLogger(__name__)
log.info("Starting MON Collector...")
log.debug("Config: %s", vars(cfg))
+ log.info("Initializing database...")
+ db_manager = DatabaseManager()
+ db_manager.create_tables()
+ log.info("Database initialized correctly.")
collector = Collector()
collector.collect_forever()
diff --git a/osm_mon/cmd/mon_evaluator.py b/osm_mon/cmd/mon_evaluator.py
index 3343b9c..79adabd 100644
--- a/osm_mon/cmd/mon_evaluator.py
+++ b/osm_mon/cmd/mon_evaluator.py
@@ -24,6 +24,7 @@
import logging
import sys
+from osm_mon.core.database import DatabaseManager
from osm_mon.core.settings import Config
from osm_mon.evaluator.evaluator import Evaluator
@@ -45,6 +46,10 @@
log = logging.getLogger(__name__)
log.info("Starting MON Evaluator...")
log.debug("Config: %s", vars(cfg))
+ log.info("Initializing database...")
+ db_manager = DatabaseManager()
+ db_manager.create_tables()
+ log.info("Database initialized correctly.")
evaluator = Evaluator()
evaluator.evaluate_forever()
diff --git a/osm_mon/cmd/mon_server.py b/osm_mon/cmd/mon_server.py
index a100c20..34fe0b1 100644
--- a/osm_mon/cmd/mon_server.py
+++ b/osm_mon/cmd/mon_server.py
@@ -24,6 +24,7 @@
import logging
import sys
+from osm_mon.core.database import DatabaseManager
from osm_mon.core.settings import Config
from osm_mon.server.server import Server
@@ -45,6 +46,10 @@
log = logging.getLogger(__name__)
log.info("Starting MON Server...")
log.debug("Config: %s", vars(cfg))
+ log.info("Initializing database...")
+ db_manager = DatabaseManager()
+ db_manager.create_tables()
+ log.info("Database initialized correctly.")
server = Server()
server.run()
diff --git a/osm_mon/collector/backends/prometheus.py b/osm_mon/collector/backends/prometheus.py
index 31f3122..fbe6d36 100644
--- a/osm_mon/collector/backends/prometheus.py
+++ b/osm_mon/collector/backends/prometheus.py
@@ -49,10 +49,9 @@
prometheus_metrics[metric.name] = GaugeMetricFamily(
OSM_METRIC_PREFIX + metric.name,
'OSM metric',
- labels=['ns_id', 'vnf_member_index', 'vdu_name']
+ labels=list(metric.tags.keys())
)
- prometheus_metrics[metric.name].add_metric([metric.nsr_id, metric.vnf_member_index, metric.vdur_name],
- metric.value)
+ prometheus_metrics[metric.name].add_metric(list(metric.tags.values()), metric.value)
self.custom_collector.metrics = prometheus_metrics.values()
def _start_exporter(self, port):
diff --git a/osm_mon/collector/collector.py b/osm_mon/collector/collector.py
index 3143882..36ce1b0 100644
--- a/osm_mon/collector/collector.py
+++ b/osm_mon/collector/collector.py
@@ -27,9 +27,11 @@
import peewee
from osm_mon.collector.backends.prometheus import PrometheusBackend
-from osm_mon.collector.collectors.juju import VCACollector
-from osm_mon.collector.collectors.openstack import OpenstackCollector
-from osm_mon.collector.collectors.vmware import VMwareCollector
+from osm_mon.collector.vnf_collectors.vmware import VMwareCollector
+from osm_mon.collector.infra_collectors.openstack import OpenstackInfraCollector
+from osm_mon.collector.metric import Metric
+from osm_mon.collector.vnf_collectors.juju import VCACollector
+from osm_mon.collector.vnf_collectors.openstack import OpenstackCollector
from osm_mon.core.common_db import CommonDbClient
from osm_mon.core.database import DatabaseManager
from osm_mon.core.settings import Config
@@ -40,6 +42,9 @@
"openstack": OpenstackCollector,
"vmware": VMwareCollector
}
+VIM_INFRA_COLLECTORS = {
+ "openstack": OpenstackInfraCollector
+}
METRIC_BACKENDS = [
PrometheusBackend
]
@@ -69,7 +74,8 @@
def _collect_vim_metrics(self, vnfr: dict, vim_account_id: str):
# TODO(diazb) Add support for vrops and aws
- vim_type = self.database_manager.get_vim_type(vim_account_id)
+ database_manager = DatabaseManager()
+ vim_type = database_manager.get_vim_type(vim_account_id)
if vim_type in VIM_COLLECTORS:
collector = VIM_COLLECTORS[vim_type](vim_account_id)
metrics = collector.collect(vnfr)
@@ -78,6 +84,17 @@
else:
log.debug("vimtype %s is not supported.", vim_type)
+ def _collect_vim_infra_metrics(self, vim_account_id: str):
+ database_manager = DatabaseManager()
+ vim_type = database_manager.get_vim_type(vim_account_id)
+ if vim_type in VIM_INFRA_COLLECTORS:
+ collector = VIM_INFRA_COLLECTORS[vim_type](vim_account_id)
+ status = collector.is_vim_ok()
+ status_metric = Metric({'vim_id': vim_account_id}, 'vim_status', status)
+ self.queue.put(status_metric)
+ else:
+ log.debug("vimtype %s is not supported.", vim_type)
+
def _collect_vca_metrics(self, vnfr: dict):
log.debug('_collect_vca_metrics')
log.debug('vnfr: %s', vnfr)
@@ -101,6 +118,12 @@
args=(vnfr,))
processes.append(p)
p.start()
+ vims = self.common_db.get_vim_accounts()
+ for vim in vims:
+ p = multiprocessing.Process(target=self._collect_vim_infra_metrics,
+ args=(vim['_id'],))
+ processes.append(p)
+ p.start()
for process in processes:
process.join()
metrics = []
diff --git a/osm_mon/collector/collectors/__init__.py b/osm_mon/collector/infra_collectors/__init__.py
similarity index 100%
copy from osm_mon/collector/collectors/__init__.py
copy to osm_mon/collector/infra_collectors/__init__.py
diff --git a/osm_mon/collector/collectors/base_vim.py b/osm_mon/collector/infra_collectors/base.py
similarity index 84%
copy from osm_mon/collector/collectors/base_vim.py
copy to osm_mon/collector/infra_collectors/base.py
index 2ae0617..6f137d0 100644
--- a/osm_mon/collector/collectors/base_vim.py
+++ b/osm_mon/collector/infra_collectors/base.py
@@ -20,9 +20,6 @@
# contact: bdiaz@whitestack.com or glavado@whitestack.com
##
-from osm_mon.collector.collectors.base import BaseCollector
-
-class BaseVimCollector(BaseCollector):
- def __init__(self, vim_account_id: str):
- pass
+class BaseInfraCollector:
+ pass
diff --git a/osm_mon/collector/collectors/base_vim.py b/osm_mon/collector/infra_collectors/base_vim.py
similarity index 84%
copy from osm_mon/collector/collectors/base_vim.py
copy to osm_mon/collector/infra_collectors/base_vim.py
index 2ae0617..0a075a1 100644
--- a/osm_mon/collector/collectors/base_vim.py
+++ b/osm_mon/collector/infra_collectors/base_vim.py
@@ -19,10 +19,12 @@
# For those usages not covered by the Apache License, Version 2.0 please
# contact: bdiaz@whitestack.com or glavado@whitestack.com
##
-
-from osm_mon.collector.collectors.base import BaseCollector
+from osm_mon.collector.infra_collectors.base import BaseInfraCollector
-class BaseVimCollector(BaseCollector):
+class BaseVimInfraCollector(BaseInfraCollector):
def __init__(self, vim_account_id: str):
pass
+
+ def is_vim_ok(self) -> bool:
+ pass
diff --git a/osm_mon/collector/infra_collectors/openstack.py b/osm_mon/collector/infra_collectors/openstack.py
new file mode 100644
index 0000000..4237e4f
--- /dev/null
+++ b/osm_mon/collector/infra_collectors/openstack.py
@@ -0,0 +1,58 @@
+# 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 keystoneauth1 import session
+from keystoneauth1.identity import v3
+from keystoneclient.v3 import client
+
+from osm_mon.collector.infra_collectors.base_vim import BaseVimInfraCollector
+from osm_mon.core.auth import AuthManager
+
+log = logging.getLogger(__name__)
+
+
+class OpenstackInfraCollector(BaseVimInfraCollector):
+ def __init__(self, vim_account_id: str):
+ super().__init__(vim_account_id)
+ self.auth_manager = AuthManager()
+ self.keystone_client = self._build_keystone_client(vim_account_id)
+
+ def is_vim_ok(self) -> bool:
+ try:
+ self.keystone_client.projects.list()
+ return True
+ except Exception:
+ log.exception("VIM status is not OK!")
+ return False
+
+ def _build_keystone_client(self, vim_account_id):
+ creds = self.auth_manager.get_credentials(vim_account_id)
+ verify_ssl = self.auth_manager.is_verify_ssl(vim_account_id)
+ auth = v3.Password(auth_url=creds.url,
+ username=creds.user,
+ password=creds.password,
+ project_name=creds.tenant_name,
+ project_domain_id='default',
+ user_domain_id='default')
+ sess = session.Session(auth=auth, verify=verify_ssl)
+ return client.Client(session=sess)
diff --git a/osm_mon/collector/metric.py b/osm_mon/collector/metric.py
index e8da11b..741096f 100644
--- a/osm_mon/collector/metric.py
+++ b/osm_mon/collector/metric.py
@@ -22,9 +22,7 @@
class Metric:
- def __init__(self, nsr_id, vnf_member_index, vdur_name, name, value):
- self.nsr_id = nsr_id
- self.vnf_member_index = vnf_member_index
- self.vdur_name = vdur_name
+ def __init__(self, tags: dict, name: str, value):
+ self.tags = tags
self.name = name
self.value = value
diff --git a/osm_mon/collector/collectors/__init__.py b/osm_mon/collector/vnf_collectors/__init__.py
similarity index 100%
rename from osm_mon/collector/collectors/__init__.py
rename to osm_mon/collector/vnf_collectors/__init__.py
diff --git a/osm_mon/collector/collectors/base.py b/osm_mon/collector/vnf_collectors/base.py
similarity index 100%
rename from osm_mon/collector/collectors/base.py
rename to osm_mon/collector/vnf_collectors/base.py
diff --git a/osm_mon/collector/collectors/base_vim.py b/osm_mon/collector/vnf_collectors/base_vim.py
similarity index 93%
rename from osm_mon/collector/collectors/base_vim.py
rename to osm_mon/collector/vnf_collectors/base_vim.py
index 2ae0617..29a348f 100644
--- a/osm_mon/collector/collectors/base_vim.py
+++ b/osm_mon/collector/vnf_collectors/base_vim.py
@@ -20,7 +20,7 @@
# contact: bdiaz@whitestack.com or glavado@whitestack.com
##
-from osm_mon.collector.collectors.base import BaseCollector
+from osm_mon.collector.vnf_collectors.base import BaseCollector
class BaseVimCollector(BaseCollector):
diff --git a/osm_mon/collector/collectors/juju.py b/osm_mon/collector/vnf_collectors/juju.py
similarity index 91%
rename from osm_mon/collector/collectors/juju.py
rename to osm_mon/collector/vnf_collectors/juju.py
index 638086a..928b35a 100644
--- a/osm_mon/collector/collectors/juju.py
+++ b/osm_mon/collector/vnf_collectors/juju.py
@@ -25,8 +25,9 @@
from n2vc.vnf import N2VC
-from osm_mon.collector.collectors.base import BaseCollector
from osm_mon.collector.metric import Metric
+from osm_mon.collector.vnf_collectors.base import BaseCollector
+from osm_mon.collector.vnf_metric import VnfMetric
from osm_mon.core.common_db import CommonDbClient
from osm_mon.core.exceptions import VcaDeploymentInfoNotFound
from osm_mon.core.settings import Config
@@ -64,7 +65,8 @@
for measure_list in measures.values():
for measure in measure_list:
log.debug("Measure: %s", measure)
- metric = Metric(nsr_id, vnf_member_index, vdur['name'], measure['key'], float(measure['value']))
+ metric = VnfMetric(nsr_id, vnf_member_index, vdur['name'], measure['key'],
+ float(measure['value']))
metrics.append(metric)
if 'vnf-configuration' in vnfd and 'metrics' in vnfd['vnf-configuration']:
try:
@@ -77,7 +79,7 @@
for measure_list in measures.values():
for measure in measure_list:
log.debug("Measure: %s", measure)
- metric = Metric(nsr_id, vnf_member_index, '', measure['key'], float(measure['value']))
+ metric = VnfMetric(nsr_id, vnf_member_index, '', measure['key'], float(measure['value']))
metrics.append(metric)
return metrics
diff --git a/osm_mon/collector/collectors/openstack.py b/osm_mon/collector/vnf_collectors/openstack.py
similarity index 95%
rename from osm_mon/collector/collectors/openstack.py
rename to osm_mon/collector/vnf_collectors/openstack.py
index 30bab0c..8dbab5c 100644
--- a/osm_mon/collector/collectors/openstack.py
+++ b/osm_mon/collector/vnf_collectors/openstack.py
@@ -29,8 +29,9 @@
from keystoneauth1 import session
from keystoneauth1.identity import v3
-from osm_mon.collector.collectors.base_vim import BaseVimCollector
from osm_mon.collector.metric import Metric
+from osm_mon.collector.vnf_collectors.base_vim import BaseVimCollector
+from osm_mon.collector.vnf_metric import VnfMetric
from osm_mon.core.auth import AuthManager
from osm_mon.core.common_db import CommonDbClient
from osm_mon.core.settings import Config
@@ -108,7 +109,7 @@
resource_id=resource_id,
granularity=self.granularity)
if len(measures):
- metric = Metric(nsr_id, vnf_member_index, vdur['name'], metric_name, measures[-1][2])
+ metric = VnfMetric(nsr_id, vnf_member_index, vdur['name'], metric_name, measures[-1][2])
metrics.append(metric)
except gnocchiclient.exceptions.NotFound as e:
log.debug("No metric found: %s", e)
diff --git a/osm_mon/collector/collectors/vmware.py b/osm_mon/collector/vnf_collectors/vmware.py
similarity index 95%
rename from osm_mon/collector/collectors/vmware.py
rename to osm_mon/collector/vnf_collectors/vmware.py
index f347446..7402afb 100644
--- a/osm_mon/collector/collectors/vmware.py
+++ b/osm_mon/collector/vnf_collectors/vmware.py
@@ -23,17 +23,17 @@
import json
import logging
+import time
+import traceback
+from xml.etree import ElementTree as XmlElementTree
+import requests
+import six
from pyvcloud.vcd.client import BasicLoginCredentials
from pyvcloud.vcd.client import Client
-import requests
-import time
-from xml.etree import ElementTree as XmlElementTree
-import traceback
-import six
-from osm_mon.collector.collectors.base_vim import BaseVimCollector
-from osm_mon.collector.metric import Metric
+from osm_mon.collector.vnf_collectors.base_vim import BaseVimCollector
+from osm_mon.collector.vnf_metric import VnfMetric
from osm_mon.core.auth import AuthManager
from osm_mon.core.common_db import CommonDbClient
from osm_mon.core.settings import Config
@@ -270,7 +270,7 @@
for resource_identifier in resource_identifiers:
if resource_identifier['identifierType']['name'] == 'VMEntityObjectID':
if resource_identifier.get('value') is not None and \
- resource_identifier['value'] == vm_moref_id:
+ resource_identifier['value'] == vm_moref_id:
vm_resource_id = resource['identifier']
log.info("Found VM resource ID: {} for vm_moref_id: {}".format(vm_resource_id,
vm_moref_id))
@@ -316,7 +316,7 @@
begin_time = end_time - time_diff
api_url = "/suite-api/api/resources/{}/stats?statKey={}&begin={}&end={}".format(
- resource_id, vrops_metric_name, str(begin_time), str(end_time))
+ resource_id, vrops_metric_name, str(begin_time), str(end_time))
headers = {'Accept': 'application/json'}
@@ -347,11 +347,11 @@
metrics_data['metrics_series'] = stat_list_v[0]['data']
if metrics_data:
- metric = Metric(nsr_id,
- vnf_member_index,
- vdur['name'],
- metric_name,
- metrics_data['metrics_series'][-1])
+ metric = VnfMetric(nsr_id,
+ vnf_member_index,
+ vdur['name'],
+ metric_name,
+ metrics_data['metrics_series'][-1])
metrics.append(metric)
diff --git a/osm_mon/collector/collectors/base_vim.py b/osm_mon/collector/vnf_metric.py
similarity index 72%
copy from osm_mon/collector/collectors/base_vim.py
copy to osm_mon/collector/vnf_metric.py
index 2ae0617..d0f39c3 100644
--- a/osm_mon/collector/collectors/base_vim.py
+++ b/osm_mon/collector/vnf_metric.py
@@ -19,10 +19,14 @@
# For those usages not covered by the Apache License, Version 2.0 please
# contact: bdiaz@whitestack.com or glavado@whitestack.com
##
-
-from osm_mon.collector.collectors.base import BaseCollector
+from osm_mon.collector.metric import Metric
-class BaseVimCollector(BaseCollector):
- def __init__(self, vim_account_id: str):
- pass
+class VnfMetric(Metric):
+ def __init__(self, nsr_id, vnf_member_index, vdur_name, name, value):
+ tags = {
+ 'ns_id': nsr_id,
+ 'vnf_member_index': vnf_member_index,
+ 'vdu_name': vdur_name
+ }
+ super().__init__(tags, name, value)
diff --git a/osm_mon/core/common_db.py b/osm_mon/core/common_db.py
index beaac3d..9cc9c06 100644
--- a/osm_mon/core/common_db.py
+++ b/osm_mon/core/common_db.py
@@ -75,3 +75,6 @@
def get_vim_account_id(self, nsr_id: str, vnf_member_index: int) -> str:
vnfr = self.get_vnfr(nsr_id, vnf_member_index)
return vnfr['vim-account-id']
+
+ def get_vim_accounts(self):
+ return self.common_db.get_list('vim_accounts')
diff --git a/osm_mon/core/database.py b/osm_mon/core/database.py
index a41c0fd..4cbd75f 100644
--- a/osm_mon/core/database.py
+++ b/osm_mon/core/database.py
@@ -25,16 +25,14 @@
import logging
import uuid
-from peewee import CharField, TextField, FloatField, Model, AutoField
+from peewee import CharField, TextField, FloatField, Model, AutoField, Proxy
from playhouse.db_url import connect
from osm_mon.core.settings import Config
log = logging.getLogger(__name__)
-cfg = Config.instance()
-cfg.read_environ()
-db = connect(cfg.DATABASE)
+db = Proxy()
class BaseModel(Model):
@@ -69,54 +67,60 @@
class DatabaseManager:
- def create_tables(self) -> None:
- try:
- db.connect()
- db.create_tables([VimCredentials, Alarm])
- db.close()
- except Exception:
- log.exception("Error creating tables: ")
+ def __init__(self):
+ cfg = Config.instance()
+ cfg.read_environ()
+ db.initialize(connect(cfg.DATABASE))
- def get_credentials(self, vim_uuid) -> VimCredentials:
- return VimCredentials.get_or_none(VimCredentials.uuid == vim_uuid)
+ def create_tables(self) -> None:
+ with db.atomic():
+ db.create_tables([VimCredentials, Alarm])
+
+ def get_credentials(self, vim_uuid: str = None) -> VimCredentials:
+ with db.atomic():
+ return VimCredentials.get_or_none(VimCredentials.uuid == vim_uuid)
def save_credentials(self, vim_credentials) -> VimCredentials:
"""Saves vim credentials. If a record with same uuid exists, overwrite it."""
- exists = VimCredentials.get_or_none(VimCredentials.uuid == vim_credentials.uuid)
- if exists:
- vim_credentials.id = exists.id
- vim_credentials.save()
- return vim_credentials
+ with db.atomic():
+ exists = VimCredentials.get_or_none(VimCredentials.uuid == vim_credentials.uuid)
+ if exists:
+ vim_credentials.id = exists.id
+ vim_credentials.save()
+ return vim_credentials
def get_alarm(self, alarm_id) -> Alarm:
- alarm = (Alarm.select()
- .where(Alarm.alarm_id == alarm_id)
- .get())
- return alarm
+ with db.atomic():
+ alarm = (Alarm.select()
+ .where(Alarm.alarm_id == alarm_id)
+ .get())
+ return alarm
def save_alarm(self, name, threshold, operation, severity, statistic, metric_name, vdur_name,
vnf_member_index, nsr_id) -> Alarm:
"""Saves alarm."""
# TODO: Add uuid optional param and check if exists to handle updates (see self.save_credentials)
- alarm = Alarm()
- alarm.uuid = str(uuid.uuid4())
- alarm.name = name
- alarm.threshold = threshold
- alarm.operation = operation
- alarm.severity = severity
- alarm.statistic = statistic
- alarm.monitoring_param = metric_name
- alarm.vdur_name = vdur_name
- alarm.vnf_member_index = vnf_member_index
- alarm.nsr_id = nsr_id
- alarm.save()
- return alarm
+ with db.atomic():
+ alarm = Alarm()
+ alarm.uuid = str(uuid.uuid4())
+ alarm.name = name
+ alarm.threshold = threshold
+ alarm.operation = operation
+ alarm.severity = severity
+ alarm.statistic = statistic
+ alarm.monitoring_param = metric_name
+ alarm.vdur_name = vdur_name
+ alarm.vnf_member_index = vnf_member_index
+ alarm.nsr_id = nsr_id
+ alarm.save()
+ return alarm
def delete_alarm(self, alarm_uuid) -> None:
- alarm = (Alarm.select()
- .where(Alarm.uuid == alarm_uuid)
- .get())
- alarm.delete_instance()
+ with db.atomic():
+ alarm = (Alarm.select()
+ .where(Alarm.uuid == alarm_uuid)
+ .get())
+ alarm.delete_instance()
def get_vim_type(self, vim_account_id) -> str:
"""Get the vim type that is required by the message."""
diff --git a/osm_mon/tests/collector/test_collector.py b/osm_mon/tests/collector/test_collector.py
index 9159f35..c386ed2 100644
--- a/osm_mon/tests/collector/test_collector.py
+++ b/osm_mon/tests/collector/test_collector.py
@@ -25,7 +25,7 @@
from unittest import mock
from osm_mon.collector.collector import Collector
-from osm_mon.collector.collectors.openstack import OpenstackCollector
+from osm_mon.collector.vnf_collectors.openstack import OpenstackCollector
from osm_mon.core.database import DatabaseManager, db