From 6932dfede2e7e6adfc63113b46a71d87757ae30d Mon Sep 17 00:00:00 2001 From: MinWookKim Date: Wed, 1 Nov 2017 17:42:28 +0900 Subject: [PATCH] Zabbix Plugin for Application Monitoring in Tacker VNF Manager Develop a Zabbix plugin in Tacker VNF manager to monitor application level parameters that can't be supported by current Tacker monitoring driver Change-Id: I25e871b8e8ddfb49a1f3f22e78c1ea8ba9835d74 Implements: blueprint zabbix-plugin --- doc/source/contributor/zabbix-plugin.rst | 193 ++++++++ .../notes/zabbix-plugin-da2f8867acafd405.yaml | 4 + .../vnfd/tosca-vnfd-zabbix-monitor.yaml | 136 ++++++ setup.cfg | 3 + .../vnfm/monitor_drivers/zabbix/__init__.py | 0 .../monitor_drivers/zabbix/test_zabbix.py | 54 +++ tacker/tosca/lib/tacker_defs.yaml | 106 +++++ tacker/tosca/lib/tacker_nfv_defs.yaml | 9 +- tacker/tosca/utils.py | 29 +- .../openstack/translate_template.py | 17 +- tacker/vnfm/monitor.py | 51 ++- .../vnfm/monitor_drivers/zabbix/__init__.py | 0 tacker/vnfm/monitor_drivers/zabbix/zabbix.py | 416 ++++++++++++++++++ .../vnfm/monitor_drivers/zabbix/zabbix_api.py | 214 +++++++++ tacker/vnfm/plugin.py | 11 +- 15 files changed, 1230 insertions(+), 13 deletions(-) create mode 100644 doc/source/contributor/zabbix-plugin.rst create mode 100644 releasenotes/notes/zabbix-plugin-da2f8867acafd405.yaml create mode 100644 samples/tosca-templates/vnfd/tosca-vnfd-zabbix-monitor.yaml create mode 100644 tacker/tests/unit/vnfm/monitor_drivers/zabbix/__init__.py create mode 100644 tacker/tests/unit/vnfm/monitor_drivers/zabbix/test_zabbix.py create mode 100644 tacker/vnfm/monitor_drivers/zabbix/__init__.py create mode 100644 tacker/vnfm/monitor_drivers/zabbix/zabbix.py create mode 100644 tacker/vnfm/monitor_drivers/zabbix/zabbix_api.py diff --git a/doc/source/contributor/zabbix-plugin.rst b/doc/source/contributor/zabbix-plugin.rst new file mode 100644 index 000000000..4ac8573b4 --- /dev/null +++ b/doc/source/contributor/zabbix-plugin.rst @@ -0,0 +1,193 @@ +.. + Copyright 2014-2017 OpenStack Foundation + All Rights Reserved. + + 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. + +======================== +How to use Zabbix Plugin +======================== + +This document explains how Tacker VNFM's Zabbix-plugin works with Zabbix +monitoring tool to provide application monitoring for VNF. + +VNF application monitoring requires three pre-installation or configuration +settings. You do not have to do a lot of work or complex settings. + +1. Zabbix-agent Installation and Setting in VNF. + +Zabbix-Agent must be installed in the VNF. And you need to set it up. The +necessary settings must be made in /etc/zabbix/zabbix_agentd.conf in the +VNF. Installation and The setting method is as follows. + +.. code-block:: console + + sudo apt-get update + sudo apt-get upgrade + sudo apt-get install zabbix-agent + sudo echo 'zabbix ALL=NOPASSWD: ALL' >> /etc/sudoers + +Then open the /etc/zabbix/zabbix_agentd.conf file and write for Server, +ServerActive Hostname, EnableRemoteCommands. However, this approach is +more difficult to manage as the number of VNFs increases. + +Therefore, to solve this problem, the method presented in this document +are as follows. After creating the VNF based on the TOSCA template, +the USER_DATA parameter is executed on the assumption that the VNF +is initialized. We can install and make the necessary settings +automatically. Here is an example of a User-data script. + +.. code-block:: console + + user_data: | + #!/bin/bash + sudo apt-get -y update + sudo apt-get -y upgrade + sudo apt-get -y install zabbix-agent + sudo sed -i "2s/.*/`ifconfig [Interface name in VNF] | grep ""\"inet addr:\"""| cut -d: -f2 | awk ""\"{ print $1 }\"""`/g" "/etc/hosts" + sudo sed -i "s/Bcast/`cat /etc/hostname`/g" "/etc/hosts" + sudo sed -i "3s/.*/[Zabbix Host IP Address]\tmonitor/g" "/etc/hosts" + sudo /etc/init.d/networking restart + sudo echo 'zabbix ALL=NOPASSWD: ALL' >> /etc/sudoers + sudo sed -i "s/# EnableRemoteCommands=0/EnableRemoteCommands=1/" "/etc/zabbix/zabbix_agentd.conf" + sudo sed -i "s/Server=127.0.0.1/Server=[Zabbix server's IP Address]/" "/etc/zabbix/zabbix_agentd.conf" + sudo sed -i "s/ServerActive=127.0.0.1/ServerActive=[Zabbix server's IP Address:Port]/" "/etc/zabbix/zabbix_agentd.conf" + sudo sed -i "s/Hostname=Zabbix server/Hostname=`cat /etc/hostname`/" "/etc/zabbix/zabbix_agentd.conf" + sudo service zabbix-agent restart + +Use the sed command to modify the information in the conf file. +The basic network interface finds the IP address for ens3, sets it, +and sets the hostname. The zabbix user also needs permissions to run +the monitoring script. EnablRemoteCommands can be set to 1 to enable +execution of action commands created by Zabbix-Server. + +2. Installing Zabbix Server + +Because Zabbix Server requires a lot of processes for monitoring +projects, it is recommended to build it as a separate physical +node if performance stability is required. Installation instructions +for Zabbix Server are detailed in the manual provided by Zabbix. +Examples of installation procedures are based on Ubuntu16.04 +and zabbix 3.2. + +.. code-block:: console + + sudo apt-get update + sudo apt-get upgrade + sudo apt-get install php7.0* libapache2-mod-php7.0 + sudo wget http://repo.zabbix.com/zabbix/3.2/ubuntu/pool/main/z/zabbix-release/zabbix-release_3.2-1+xenial_all.deb + sudo dpkg -i zabbix-release_3.2-1+xenial_all.deb + sudo apt-get install zabbix-server-mysql zabbix-frontend-php + +Install mysql to store Zabbix-server and monitoring data and +necessary information, and install Zabbix-frotend-php to +provide web pages. Database creation is as follows. + +.. code-block:: console + + shell> mysql -uroot -p[ROOT_PASSWORD] + mysql> create database zabbix character set utf8 collate utf8_bin; + mysql> grant all privileges on zabbix.* to zabbix@localhost identified by '[PASSWORD]'; + FLUSH PRIVILEGES; + mysql> quit; + cd /usr/share/doc/zabbix-server-mysql + zcat create.sql.gz | mysql -u root -p zabbix + +We must modify the vi /etc/zabbix/zabbix_server.conf file to +provide the Zabbix-server. + +.. code-block:: console + + DBHost=localhost + DBName=[DBName] + DBUser=[DBUser] + DBPassword=[PASSWORD] + +At the end of the next operation, we are now ready to use the +Zabbix-server to complete the finish operation. + +.. code-block:: console + + service zabbix-server start + update-rc.d zabbix-server enable + vi /etc/zabbix/apache.conf + =>php_value date.timezone [location/city] + service zabbix-server restart + service apache2 restart + +This installation method is based on manual, but it includes +additional explanation and installation part of dependency +file installation. + +3. Template + +The following templates are used for application monitoring. +If we create a VNFD by creating the template below and use it +to create a VNF, we can monitor the application without any +additional steps. If we want automatic configuration, it is +recommended to use USER_DATA parameter. + +If we enter Zabbix-related information in the template, you will +get a Token according to the internal workflow of Zabbix-plugin. +It it used to configure varitous monitoring functions. + +.. code-block:: console + + app_monitoring_policy: + name: zabbix + zabbix_username: [Zabbix user ID] + zabbix_password: [Zabbix user Password] + zabbix_server_ip: [Zabbix server IP] + zabbix_server_port: [Zabbix server Port] + parameters: + application: + app_name: [application-name] + app_port: [application-port] + ssh_username: [ssh username in VNF OS] + ssh_password: [ssh password in VNF OS] + app_status: + condition: [comparison,value] + actionname: [action name] + cmd-action: [Command to be executed in VNF] + app_memory: + condition: [comparison,value] + actionname: [action name] + cmd-action: [Command to be executed in VNF] + OS: + os_agent_info: + condition: [comparison,value] + actionname: [action name] + cmd-action: [Command to be executed in VNF] + os_proc_value: + condition: [comparison,value] + actionname: [action name] + cmd-action: [Command to be executed in VNF] + os_cpu_load: + condition: [comparison,value] + actionname: [action name] + cmd-action: [Command to be executed in VNF] + os_cpu_usage: + condition: [comparison,value] + actionname: [action name] + cmd-action: [Command to be executed in VNF] + +4. Actions +Currently, only cmd is supported as an action function. +Respawn and Scale Action will be updated with additional +proposals and corresponding functionality as more template +definitions and corresponding additional functions are required. + +References +========== +.. [#first] https://www.zabbix.com/documentation/3.2/manual + diff --git a/releasenotes/notes/zabbix-plugin-da2f8867acafd405.yaml b/releasenotes/notes/zabbix-plugin-da2f8867acafd405.yaml new file mode 100644 index 000000000..3f08dbcba --- /dev/null +++ b/releasenotes/notes/zabbix-plugin-da2f8867acafd405.yaml @@ -0,0 +1,4 @@ +--- +features: + - Added zabbix-pugin to monitor applications within VNF. + diff --git a/samples/tosca-templates/vnfd/tosca-vnfd-zabbix-monitor.yaml b/samples/tosca-templates/vnfd/tosca-vnfd-zabbix-monitor.yaml new file mode 100644 index 000000000..bf51eab33 --- /dev/null +++ b/samples/tosca-templates/vnfd/tosca-vnfd-zabbix-monitor.yaml @@ -0,0 +1,136 @@ +tosca_definitions_version: tosca_simple_profile_for_nfv_1_0_0 + +description: Monitoring for multiple vdus + +metadata: + template_name: tosca-vnfd-monitoir-multi-vdu + +topology_template: + node_templates: + VDU1: + type: tosca.nodes.nfv.VDU.Tacker + capabilities: + nfv_compute: + properties: + num_cpus: 2 + mem_size: 2048 MB + disk_size: 15 GB + properties: + name: VDU1 + image: ubuntu16.04 + availability_zone: nova + mgmt_driver: noop + config: | + param0: key1 + param1: key2 + user_data_format: RAW + user_data: | + #!/bin/bash + sudo apt-get -y update + sudo apt-get -y upgrade + sudo apt-get -y install zabbix-agent + sudo apt-get -y install apache2 + + sudo sed -i "2s/.*/`ifconfig [Interface name in VNF] | grep ""\"inet addr:\"""| cut -d: -f2 | awk ""\"{ print $1 }\"""`/g" "/etc/hosts" + sudo sed -i "s/Bcast/`cat /etc/hostname`/g" "/etc/hosts" + sudo sed -i "3s/.*/[Zabbix Host IP Address]\tmonitor/g" "/etc/hosts" + sudo /etc/init.d/networking restart + sudo echo 'zabbix ALL=NOPASSWD: ALL' >> /etc/sudoers + + sudo sed -i "s/# EnableRemoteCommands=0/EnableRemoteCommands=1/" "/etc/zabbix/zabbix_agentd.conf" + sudo sed -i "s/Server=127.0.0.1/Server=[Zabbix server's IP Address]/" "/etc/zabbix/zabbix_agentd.conf" + sudo sed -i "s/ServerActive=127.0.0.1/ServerActive=[Zabbix server's IP Address:Port]/" "/etc/zabbix/zabbix_agentd.conf" + sudo sed -i "s/Hostname=Zabbix server/Hostname=`cat /etc/hostname`/" "/etc/zabbix/zabbix_agentd.conf" + + sudo service apache2 restart + sudo service zabbix-agent restart + sudo echo 'ubuntu:ubuntu' | chpasswd + sudo echo 'root:root' | chpasswd + app_monitoring_policy: + name: zabbix + zabbix_username: Admin + zabbix_password: zabbix + zabbix_server_ip: 192.168.11.53 + zabbix_server_port: 80 + parameters: + application: + app_name: apache2 + app_port: 80 + ssh_username: ubuntu + ssh_password: ubuntu + app_status: + condition: [down] + actionname: cmd + cmd-action: sudo service apache2 restart + app_memory: + condition: [greater,22] + actionname: cmd + cmd-action: sudo service apache2 stop + OS: + os_agent_info: + condition: [down] + actionname: cmd + cmd-action: sudo service zabbix-agent restart + os_proc_value: + condition: [and less,22] + actionname: cmd + cmd-action: sudo reboot + os_cpu_load: + condition: [and greater,30] + actionname: cmd + cmd-action: sudo reboot + os_cpu_usage: + condition: [less,30] + actionname: cmd + cmd-action: sudo reboot + + CP11: + type: tosca.nodes.nfv.CP.Tacker + properties: + management: true + order: 0 + anti_spoofing_protection: false + requirements: + - virtualLink: + node: VL1 + - virtualBinding: + node: VDU1 + + CP12: + type: tosca.nodes.nfv.CP.Tacker + properties: + order: 1 + anti_spoofing_protection: false + requirements: + - virtualLink: + node: VL2 + - virtualBinding: + node: VDU1 + + CP13: + type: tosca.nodes.nfv.CP.Tacker + properties: + order: 2 + anti_spoofing_protection: false + requirements: + - virtualLink: + node: VL3 + - virtualBinding: + node: VDU1 + VL1: + type: tosca.nodes.nfv.VL + properties: + network_name: net_mgmt + vendor: Tacker + + VL2: + type: tosca.nodes.nfv.VL + properties: + network_name: net0 + vendor: Tacker + + VL3: + type: tosca.nodes.nfv.VL + properties: + network_name: net1 + vendor: Tacker diff --git a/setup.cfg b/setup.cfg index bde3a942b..2788d5a47 100644 --- a/setup.cfg +++ b/setup.cfg @@ -59,6 +59,8 @@ tacker.tacker.mgmt.drivers = tacker.tacker.monitor.drivers = ping = tacker.vnfm.monitor_drivers.ping.ping:VNFMonitorPing http_ping = tacker.vnfm.monitor_drivers.http_ping.http_ping:VNFMonitorHTTPPing +tacker.tacker.app_monitor.drivers = + zabbix = tacker.vnfm.monitor_drivers.zabbix.zabbix:VNFMonitorZabbix tacker.tacker.alarm_monitor.drivers = ceilometer = tacker.vnfm.monitor_drivers.ceilometer.ceilometer:VNFMonitorCeilometer tacker.tacker.policy.actions = @@ -81,6 +83,7 @@ oslo.config.opts = tacker.vnfm.monitor_drivers.http_ping.http_ping = tacker.vnfm.monitor_drivers.http_ping.http_ping:config_opts tacker.vnfm.monitor_drivers.ping.ping = tacker.vnfm.monitor_drivers.ping.ping:config_opts tacker.vnfm.monitor_drivers.ceilometer.ceilometer = tacker.vnfm.monitor_drivers.ceilometer.ceilometer:config_opts + tacker.vnfm.monitor_drivers.zabbix.zabbix = tacker.vnfm.monitor_drivers.zabbix.zabbix:config_opts tacker.alarm_receiver = tacker.alarm_receiver:config_opts mistral.actions = tacker.vim_ping_action = tacker.nfvo.workflows.vim_monitor.vim_ping_action:PingVimAction diff --git a/tacker/tests/unit/vnfm/monitor_drivers/zabbix/__init__.py b/tacker/tests/unit/vnfm/monitor_drivers/zabbix/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tacker/tests/unit/vnfm/monitor_drivers/zabbix/test_zabbix.py b/tacker/tests/unit/vnfm/monitor_drivers/zabbix/test_zabbix.py new file mode 100644 index 000000000..0bf499755 --- /dev/null +++ b/tacker/tests/unit/vnfm/monitor_drivers/zabbix/test_zabbix.py @@ -0,0 +1,54 @@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +import mock +from tacker.vnfm.monitor_drivers.zabbix import zabbix +import testtools + + +class TestVNFMonitorZabbix(testtools.TestCase): + + def setUp(self): + super(TestVNFMonitorZabbix, self).setUp() + zabbix.VNFMonitorZabbix.tacker_token = 'a1b2c3d4e5' + self.monitor_zabbix = zabbix.VNFMonitorZabbix() + + @mock.patch('tacker.vnfm.monitor_drivers.zabbix.zabbix.' + 'VNFMonitorZabbix.add_to_appmonitor') + def test_add_to_appmonitor(self, mock_ac): + mock_ac.return_value = None + + test_vnf = {'vnfd': {'tenant_id': u'd1e6919c73074d18ab6cd49a02e08391'}, + 'id': 'b9af3cb5-6e43-4b2c-a056-67bda3f71e1a'} + test_kwargs = {'vdus': {'VDU1': + {'parameters': + {'application': + {'app_name': 'apache2', + 'app_status': {'actionname': 'cmd', + 'cmd-action': 'sudo service \ + apache2 restart', + 'condition': ['down']}, + 'ssh_username': 'ubuntu', + 'app_port': 80, + 'ssh_password': 'ubuntu'}}, + 'name': 'zabbix', + 'zabbix_username': 'Admin', + 'zabbix_password': 'zabbix', + 'zabbix_server_ip': '192.168.11.53', + 'zabbix_server_port': 80, + 'mgmt_ip': '192.168.11.206'}}} + + monitor_return = self.monitor_zabbix.\ + add_to_appmonitor(test_kwargs, test_vnf) + self.assertEqual(None, monitor_return) diff --git a/tacker/tosca/lib/tacker_defs.yaml b/tacker/tosca/lib/tacker_defs.yaml index 4da9d8f58..c4c30f075 100644 --- a/tacker/tosca/lib/tacker_defs.yaml +++ b/tacker/tosca/lib/tacker_defs.yaml @@ -13,6 +13,89 @@ data_types: type: string required: false + tosca.datatypes.tacker.AppActionMap: + properties: + condition: + type: map + entry_schema: + type: string + required: false + actionname: + type: string + required: false + cmd-action: + type: string + required: false + + tosca.datatypes.tacker.AppInfoParams: + properties: + app_name: + type: string + required: true + app_port: + type: string + required: true + ssh_username: + type: string + required: false + ssh_password: + type: string + required: false + app_status: + type: tosca.dataypes.tacker.AppActionMap + required: false + app_memory: + type: tosca.dataypes.tacker.AppActionMap + required: false + + tosca.datatypes.tacker.OSInfoParams: + properties: + os_agent_info: + type: tosca.dataypes.tacker.AppActionMap + required: false + os_proc_value: + type: tosca.datatypes.tacker.AppActionMap + required: false + os_cpu_load: + type: tosca.datatypes.tacker.AppActionMap + required: false + os_cpu_usage: + type: tosca.datatypes.tacker.AppActionMap + required: false + + + tosca.datatypes.tacker.AppMonitoringParams: + properties: + application: + type: tosca.datatypes.tacker.AppInfoParams + required: false + OS: + type: tosca.datatypes.tacker.OSInfoParams + required: false + + tosca.datatypes.tacker.AppMonitoringType: + properties: + name: + type: string + required: true + zabbix_username: + type: string + required: true + zabbix_password: + type: string + required: true + zabbix_server_ip: + type: string + required: true + zabbix_server_port: + type: int + required: true + parameters: + type: tosca.datatypes.tacker.AppMonitoringParams + required: false + + + tosca.datatypes.tacker.MonitoringParams: properties: monitoring_delay: @@ -46,6 +129,8 @@ data_types: type: tosca.datatypes.tacker.MonitoringParams required: false + + tosca.datatypes.compute_properties: properties: num_cpus: @@ -83,6 +168,7 @@ data_types: required: false description: The mac address allowed to be paired with specific virtual IP. + policy_types: tosca.policies.tacker.Placement: derived_from: tosca.policies.Root @@ -121,6 +207,20 @@ policy_types: type: string required: true + tosca.policies.tacker.AppMonitoring: + derived_from: tosca.policies.Root + properties: + name: + type: string + required: true + parameters: + type: map + entry_schema: + type: string + required: false + + + tosca.policies.tacker.Monitoring.NoOp: derived_from: tosca.policies.tacker.Monitoring properties: @@ -136,6 +236,12 @@ policy_types: properties: name: http-ping + tosca.policies.tacker.Monitoring.Zabbix: + derived_from: tosca.policies.tacker.Appmonitoring + properties: + name: zabbix + + tosca.policies.tacker.Alarming: derived_from: tosca.policies.Monitoring triggers: diff --git a/tacker/tosca/lib/tacker_nfv_defs.yaml b/tacker/tosca/lib/tacker_nfv_defs.yaml index be4135cd1..b22be0816 100644 --- a/tacker/tosca/lib/tacker_nfv_defs.yaml +++ b/tacker/tosca/lib/tacker_nfv_defs.yaml @@ -163,7 +163,7 @@ node_types: type: string required: false image: -# type: tosca.artifacts.Deployment.Image.VM +# type: tosca.artifacts.Deployment.Image.VM type: string required: false flavor: @@ -186,6 +186,13 @@ node_types: # type: tosca.policies.tacker.Placement type: string required: false + app_monitoring_policy: +# type: tosca.policies.tacker.AppMonitoring +# type: tosca.datatypes.tacker.AppMonitoringType + type: map + required: false + + monitoring_policy: # type: tosca.policies.tacker.Monitoring diff --git a/tacker/tosca/utils.py b/tacker/tosca/utils.py index d504d0c3b..fdaea593d 100644 --- a/tacker/tosca/utils.py +++ b/tacker/tosca/utils.py @@ -17,15 +17,14 @@ import re import sys import yaml +from collections import OrderedDict from oslo_log import log as logging -from toscaparser import properties -from toscaparser.utils import yamlparser - from tacker.common import log from tacker.common import utils from tacker.extensions import vnfm +from toscaparser import properties +from toscaparser.utils import yamlparser -from collections import OrderedDict FAILURE = 'tosca.policies.tacker.Failure' LOG = logging.getLogger(__name__) @@ -160,6 +159,28 @@ def get_vdu_monitoring(template): return monitoring_dict +def get_vdu_applicationmonitoring(template): + tpl_temp = "topology_template" + n_temp = "node_templates" + poly = "app_monitoring_policy" + monitoring_dict = dict() + policy_dict = dict() + policy_dict['vdus'] = collections.OrderedDict() + node_list = template[tpl_temp][n_temp].keys() + for node in node_list: + nt = template[tpl_temp][n_temp][node] + if nt['type'] == TACKERVDU: + if poly in nt['properties'].keys(): + mon_policy = nt['properties'][poly] + if mon_policy != 'noop': + policy_dict['vdus'][node] = {} + policy_dict['vdus'][node] = mon_policy + del template[tpl_temp][n_temp][node]['properties'][poly] + if policy_dict.get('vdus'): + monitoring_dict = policy_dict + return monitoring_dict + + @log.log def get_vdu_metadata(template): metadata = dict() diff --git a/tacker/vnfm/infra_drivers/openstack/translate_template.py b/tacker/vnfm/infra_drivers/openstack/translate_template.py index f35ff2e05..27096d7c8 100644 --- a/tacker/vnfm/infra_drivers/openstack/translate_template.py +++ b/tacker/vnfm/infra_drivers/openstack/translate_template.py @@ -60,6 +60,7 @@ class TOSCAToHOT(object): self.nested_resources = dict() self.fields = None self.STACK_FLAVOR_EXTRA = cfg.CONF.openstack_vim.flavor_extra_specs + self.appmonitoring_dict = None @log.log def generate_hot(self): @@ -78,6 +79,9 @@ class TOSCAToHOT(object): if self.monitoring_dict: self.vnf['attributes']['monitoring_policy'] = jsonutils.dumps( self.monitoring_dict) + if self.appmonitoring_dict: + self.vnf['attributes']['app_monitoring_policy'] = \ + jsonutils.dumps(self.appmonitoring_dict) @log.log def _get_vnfd(self): @@ -250,11 +254,17 @@ class TOSCAToHOT(object): LOG.debug("Params not Well Formed: %s", str(e)) raise vnfm.ParamYAMLNotWellFormed(error_msg_details=str(e)) - block_storage_details = toscautils.get_block_storage_details(vnfd_dict) + appmonitoring_dict = \ + toscautils.get_vdu_applicationmonitoring(vnfd_dict) + + block_storage_details = toscautils.get_block_storage_details( + vnfd_dict) toscautils.updateimports(vnfd_dict) if 'substitution_mappings' in str(vnfd_dict): - toscautils.check_for_substitution_mappings(vnfd_dict, - parsed_params) + toscautils.check_for_substitution_mappings( + vnfd_dict, + parsed_params + ) try: tosca = tosca_template.ToscaTemplate(parsed_params=parsed_params, @@ -314,6 +324,7 @@ class TOSCAToHOT(object): self.heat_template_yaml = heat_template_yaml self.monitoring_dict = monitoring_dict self.metadata = metadata + self.appmonitoring_dict = appmonitoring_dict @log.log def represent_odict(self, dump, tag, mapping, flow_style=None): diff --git a/tacker/vnfm/monitor.py b/tacker/vnfm/monitor.py index bff0c220c..b8aa3dbc3 100644 --- a/tacker/vnfm/monitor.py +++ b/tacker/vnfm/monitor.py @@ -14,7 +14,7 @@ # License for the specific language governing permissions and limitations # under the License. - +import ast import inspect import threading import time @@ -24,7 +24,6 @@ from oslo_log import log as logging from oslo_serialization import jsonutils from oslo_utils import timeutils - from tacker.common import driver_manager from tacker import context as t_context from tacker.db.common_services import common_services_db_plugin @@ -43,7 +42,8 @@ CONF.register_opts(OPTS, group='monitor') def config_opts(): return [('monitor', OPTS), ('tacker', VNFMonitor.OPTS), - ('tacker', VNFAlarmMonitor.OPTS), ] + ('tacker', VNFAlarmMonitor.OPTS), + ('tacker', VNFAppMonitor.OPTS)] def _log_monitor_events(context, vnf_dict, evt_details): @@ -195,6 +195,49 @@ class VNFMonitor(object): vnf=vnf_dict, kwargs=kwargs) +class VNFAppMonitor(object): + """VNF App monitor""" + OPTS = [ + cfg.ListOpt( + 'app_monitor_driver', default=['zabbix'], + help=_('App monitoring driver to communicate with ' + 'Hosting VNF/logical service ' + 'instance tacker plugin will use')), + ] + cfg.CONF.register_opts(OPTS, 'tacker') + + def __init__(self): + self._application_monitor_manager = driver_manager.DriverManager( + 'tacker.tacker.app_monitor.drivers', + cfg.CONF.tacker.app_monitor_driver) + + def _create_app_monitoring_dict(self, dev_attrs, mgmt_url): + app_policy = 'app_monitoring_policy' + appmonitoring_dict = ast.literal_eval(dev_attrs[app_policy]) + vdulist = appmonitoring_dict['vdus'].keys() + + for vduname in vdulist: + temp = ast.literal_eval(mgmt_url) + appmonitoring_dict['vdus'][vduname]['mgmt_ip'] = temp[vduname] + return appmonitoring_dict + + def create_app_dict(self, context, vnf_dict): + dev_attrs = vnf_dict['attributes'] + mgmt_url = vnf_dict['mgmt_url'] + return self._create_app_monitoring_dict(dev_attrs, mgmt_url) + + def _invoke(self, driver, **kwargs): + method = inspect.stack()[1][3] + return self._application_monitor_manager.\ + invoke(driver, method, **kwargs) + + def add_to_appmonitor(self, applicationvnfdict, vnf_dict): + vdunode = applicationvnfdict['vdus'].keys() + driver = applicationvnfdict['vdus'][vdunode[0]]['name'] + kwargs = applicationvnfdict + return self._invoke(driver, vnf=vnf_dict, kwargs=kwargs) + + class VNFAlarmMonitor(object): """VNF Alarm monitor""" OPTS = [ @@ -262,7 +305,7 @@ class VNFAlarmMonitor(object): return alarm_url def process_alarm_for_vnf(self, vnf, trigger): - '''call in plugin''' + """call in plugin""" params = trigger['params'] mon_prop = trigger['trigger'] alarm_dict = dict() diff --git a/tacker/vnfm/monitor_drivers/zabbix/__init__.py b/tacker/vnfm/monitor_drivers/zabbix/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tacker/vnfm/monitor_drivers/zabbix/zabbix.py b/tacker/vnfm/monitor_drivers/zabbix/zabbix.py new file mode 100644 index 000000000..1c3bbc27e --- /dev/null +++ b/tacker/vnfm/monitor_drivers/zabbix/zabbix.py @@ -0,0 +1,416 @@ +# All Rights Reserved. +# +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import json +import requests +import time + +import copy +from oslo_log import log as logging +from tacker.vnfm.monitor_drivers import abstract_driver +from tacker.vnfm.monitor_drivers.zabbix import zabbix_api as zapi + + +LOG = logging.getLogger(__name__) + + +class VNFMonitorZabbix(abstract_driver.VNFMonitorAbstractDriver): + params = ['application', 'OS'] + + def __init__(self): + self.kwargs = None + self.vnf = None + self.vduname = [] + self.URL = None + self.hostinfo = {} + self.tenant_id = None + + def get_type(self): + """Return one of predefined type of the hosting vnf drivers.""" + plugin_type = 'zabbix' + return plugin_type + + def get_name(self): + """Return a symbolic name for the VNF Monitor plugin.""" + plugin_name = 'zabbix' + return plugin_name + + def get_description(self): + """Return description of VNF Monitor plugin.""" + plugin_descript = 'Tacker VNFMonitor Zabbix Driver' + return plugin_descript + + def monitor_get_config(self, plugin, context, vnf): + + """Return dict of monitor configuration data. + + :param plugin: + :param context: + :param vnf: + :returns: dict + :returns: dict of monitor configuration data + """ + return {} + + def monitor_url(self, plugin, context, vnf): + """Return the url of vnf to monitor. + + :param plugin: + :param context: + :param vnf: + :returns: string + :returns: url of vnf to monitor + """ + pass + + def send_post(self, query): + response = requests.post(self.URL, headers=zapi.HEADERS, + data=json.dumps(query)) + return dict(response.json()) + + @staticmethod + def check_error(response): + try: + if 'result' not in response: + raise ValueError + except ValueError: + LOG.error('Cannot request error : %s', response['error']['data']) + + def create_graph(self, itemid, name, nodename): + temp_graph_api = copy.deepcopy(zapi.dGRAPH_CREATE_API) + gitems = [{'itemid': itemid, 'color': '00AA00'}] + temp_graph_api['auth'] = \ + self.hostinfo[nodename]['zbx_info']['zabbix_token'] + temp_graph_api['params']['gitems'] = gitems + temp_graph_api['params']['name'] = name + response = self.send_post(temp_graph_api) + VNFMonitorZabbix.check_error(response) + + def create_action(self): + for vdu in self.vduname: + temp_action_api = copy.deepcopy(zapi.dACTION_CREATE_API) + temp_action_api['auth'] = \ + self.hostinfo[vdu]['zbx_info']['zabbix_token'] + tempname_api = temp_action_api['params']['operations'][0] + temp_filter = temp_action_api['params']['filter'] + for info in (self.hostinfo[vdu]['actioninfo']): + tempname_api['opcommand_hst'][0]['hostid'] = \ + self.hostinfo[vdu]['hostid'] + now = time.localtime() + rtime = str(now.tm_hour) + str(now.tm_min) + str(now.tm_sec) + temp_name = "Trigger Action " + \ + str( + vdu + rtime + " " + + info['item'] + " " + info['action'] + ) + temp_action_api['params']['name'] = temp_name + + if (info['action'] == 'cmd') and \ + (info['item'] != 'os_agent_info'): + + tempname_api['opcommand']['command'] = info['cmd-action'] + + elif (info['item'] == 'os_agent_info') \ + and (info['action'] == 'cmd'): + + tempname_api['opcommand']['authtype'] = 0 + tempname_api['opcommand']['username'] = \ + self.hostinfo[vdu]['appinfo']['ssh_username'] + tempname_api['opcommand']['password'] = \ + self.hostinfo[vdu]['appinfo']['ssh_password'] + tempname_api['opcommand']['type'] = 2 + tempname_api['opcommand']['command'] = info['cmd-action'] + tempname_api['opcommand']['port'] = 22 + + temp_filter['conditions'][0]['value'] = info['trigger_id'] + response = self.send_post(temp_action_api) + VNFMonitorZabbix.check_error(response) + continue + + temp_filter['conditions'][0]['value'] = info['trigger_id'] + response = self.send_post(temp_action_api) + VNFMonitorZabbix.check_error(response) + + def create_vdu_host(self): + for vdu in self.vduname: + temp_host_api = zapi.dHOST_CREATE_API + temp_group_api = zapi.dGROUP_GET_API + temp_host_api['auth'] = \ + self.hostinfo[vdu]['zbx_info']['zabbix_token'] + temp_group_api['auth'] = \ + self.hostinfo[vdu]['zbx_info']['zabbix_token'] + response = self.send_post(temp_group_api) + gid = response['result'][0]['groupid'] + temp_host_api['params']['host'] = str(vdu) + if type(self.hostinfo[vdu]['mgmt_ip']) is list: + for vduip in (self.hostinfo[vdu]['mgmt_ip']): + temp_host_api['params']['interfaces'][0]['ip'] = vduip + temp_host_api['params']['templates'][0]['templateid'] = \ + self.hostinfo[vdu]['template_id'][0] + temp_host_api['params']['groups'][0]['groupid'] = gid + response = self.send_post(temp_host_api) + else: + temp_host_api['params']['interfaces'][0]['ip'] = \ + self.hostinfo[vdu]['mgmt_ip'] + temp_host_api['params']['templates'][0]['templateid'] = \ + self.hostinfo[vdu]['template_id'][0] + temp_host_api['params']['groups'][0]['groupid'] = gid + response = self.send_post(temp_host_api) + if 'error' in response: + now = time.localtime() + rtime = str(now.tm_hour) + str(now.tm_min) + str(now.tm_sec) + temp_host_api['params']['host'] = str(vdu) + rtime + response = self.send_post(temp_host_api) + self.hostinfo[vdu]['hostid'] = response['result']['hostids'][0] + + def create_trigger(self, trigger_params, vduname): + temp_trigger_api = copy.deepcopy(zapi.dTRIGGER_CREATE_API) + temp_trigger_api['auth'] = \ + self.hostinfo[vduname]['zbx_info']['zabbix_token'] + temp_trigger_api['params'] = trigger_params + temp_trigger_api['templateid'] = \ + str( + self.hostinfo[vduname]['template_id'][0]) + response = self.send_post(temp_trigger_api) + VNFMonitorZabbix.check_error(response) + return response['result'] + + def _create_trigger(self): + + trigger_params = [] + trig_act_pa = [] + for vdu in self.vduname: + temp_trigger_list = copy.deepcopy(zapi.dTRIGGER_LIST) + + temp_vdu_name = self.hostinfo[vdu]['appinfo']['app_name'] + temp_vdu_port = self.hostinfo[vdu]['appinfo']['app_port'] + for para in VNFMonitorZabbix.params: + for item in self.hostinfo[vdu]['parameters'][para].keys(): + action_list = copy.deepcopy(zapi.dACTION_LIST) + temp_item = self.hostinfo[vdu]['parameters'][para][item] + + if ('app_name' != item)\ + and ('app_port' != item) \ + and ('ssh_username' != item) \ + and ('ssh_password' != item): + + if 'condition' \ + in temp_item.keys(): + temp_con = temp_item['condition'] + + if len(temp_con) == 2: + temp_comparrision = temp_con[0] + temp_comparrision_value = temp_con[1] + temp_trigger_list[item][0]['expression'] += \ + self.hostinfo[vdu]['template_name'] + ':'\ + + str( + zapi.dITEM_KEY_COMP[item].replace( + '*', str(temp_vdu_name))) \ + + str( + zapi.COMP_VALUE[temp_comparrision]) \ + + str( + temp_comparrision_value) + + else: + temp_comparrision = temp_con[0] + if 'os_agent_info' == item: + temp_trigger_list[item][0]['expression'] += \ + self.hostinfo[vdu]['template_name'] + ':' \ + + str(zapi.dITEM_KEY_COMP[item]) + + else: + temp_trigger_list[item][0]['expression'] += \ + self.hostinfo[vdu]['template_name'] + ':' \ + + str( + zapi.dITEM_KEY_COMP[item].replace( + '*', str(temp_vdu_port))) \ + + str( + zapi.COMP_VALUE[temp_comparrision]) + if 'actionname' in \ + temp_item.keys(): + + trig_act_pa.append(temp_trigger_list[item][0]) + response = self.create_trigger(trig_act_pa, vdu) + del trig_act_pa[:] + action_list['action'] = \ + temp_item['actionname'] + action_list['trigger_id'] = \ + response['triggerids'][0] + action_list['item'] = item + if 'cmd' == \ + temp_item['actionname']: + + action_list['cmd-action'] = \ + temp_item['cmd-action'] + self.hostinfo[vdu]['actioninfo'].append( + action_list) + + else: + trigger_params.append( + temp_trigger_list[item][0]) + + if len(trigger_params) != 0: + self.create_trigger(trigger_params, vdu) + del trigger_params[:] + + def create_item(self): + # Create _ITEM + for vdu in self.vduname: + temp_item_api = copy.deepcopy(zapi.dITEM_CREATE_API) + temp_item_api['auth'] = \ + self.hostinfo[vdu]['zbx_info']['zabbix_token'] + self.hostinfo[vdu]['appinfo'] = \ + copy.deepcopy(zapi.dAPP_INFO) + temp_app = self.hostinfo[vdu]['parameters']['application'] + temp_item_api['params']['hostid'] = \ + self.hostinfo[vdu]['template_id'][0] + + for para in VNFMonitorZabbix.params: + if 'application' == para: + for app_info in \ + temp_app.keys(): + self.hostinfo[vdu]['appinfo'][app_info] = \ + temp_app[app_info] + + for item in (self.hostinfo[vdu]['parameters'][para].keys()): + if ('app_name' != item) and ('app_port' != item) \ + and ('ssh_username' != item) \ + and ('ssh_password' != item): + + temp_item_api['params']['name'] = \ + zapi.dITEM_KEY_INFO[item]['name'] + temp_item_api['params']['value_type'] = \ + zapi.dITEM_KEY_INFO[item]['value_type'] + + if item == 'app_status': + temp = zapi.dITEM_KEY_INFO[item]['key_'] + temp_item_api['params']['key_'] = temp.replace( + '*', str( + self.hostinfo[vdu]['appinfo']['app_port'])) + + elif item == 'app_memory': + temp = zapi.dITEM_KEY_INFO[item]['key_'] + temp_item_api['params']['key_'] = temp.replace( + '*', + str( + self.hostinfo[vdu]['appinfo']['app_name'])) + + else: + temp_item_api['params']['key_'] = \ + zapi.dITEM_KEY_INFO[item]['key_'] + response = self.send_post(temp_item_api) + self.create_graph( + response['result']['itemids'][0], + temp_item_api['params']['name'], vdu) + VNFMonitorZabbix.check_error(response) + + def create_template(self): + temp_template_api = copy.deepcopy(zapi.dTEMPLATE_CREATE_API) + + for vdu in self.vduname: + temp_template_api['params']['host'] = "Tacker Template " + str(vdu) + temp_template_api['auth'] = \ + self.hostinfo[vdu]['zbx_info']['zabbix_token'] + response = self.send_post(temp_template_api) + + if 'error' in response: + if "already exists." in response['error']['data']: + now = time.localtime() + rtime = str(now.tm_hour) + str(now.tm_min) + str( + now.tm_sec) + temp_template_api['params']['host'] = \ + "Tacker Template " + str(vdu) + rtime + response = self.send_post(temp_template_api) + VNFMonitorZabbix.check_error(response) + self.hostinfo[vdu]['template_id'] = \ + response['result']['templateids'] + self.hostinfo[vdu]['template_name'] =\ + temp_template_api['params']['host'] + + def add_host_to_zabbix(self): + + self.create_template() + self.create_item() + self._create_trigger() + self.create_vdu_host() + self.create_action() + + def get_token_from_zbxserver(self, node): + + temp_auth_api = copy.deepcopy(zapi.dAUTH_API) + temp_auth_api['params']['user'] = \ + self.hostinfo[node]['zbx_info']['zabbix_user'] + temp_auth_api['params']['password'] = \ + self.hostinfo[node]['zbx_info']['zabbix_pass'] + zabbixip = \ + self.hostinfo[node]['zbx_info']['zabbix_ip'] + zabbixport = \ + self.hostinfo[node]['zbx_info']['zabbix_port'] + self.URL = "http://" + zabbixip + ":" + \ + str(zabbixport) + zapi.URL_ + response = requests.post( + self.URL, + headers=zapi.HEADERS, + data=json.dumps(temp_auth_api) + ) + response_dict = dict(response.json()) + VNFMonitorZabbix.check_error(response_dict) + LOG.info('Success Connect Zabbix Server') + return response_dict['result'] + + def set_zbx_info(self, node): + self.hostinfo[node]['zbx_info'] = \ + copy.deepcopy(zapi.dZBX_INFO) + self.hostinfo[node]['zbx_info']['zabbix_user'] = \ + self.kwargs['vdus'][node]['zabbix_username'] + self.hostinfo[node]['zbx_info']['zabbix_pass'] = \ + self.kwargs['vdus'][node]['zabbix_password'] + self.hostinfo[node]['zbx_info']['zabbix_ip'] = \ + self.kwargs['vdus'][node]['zabbix_server_ip'] + self.hostinfo[node]['zbx_info']['zabbix_port'] = \ + self.kwargs['vdus'][node]['zabbix_server_port'] + self.hostinfo[node]['zbx_info']['zabbix_token'] = \ + self.get_token_from_zbxserver(node) + + def set_vdu_info(self): + temp_vduname = self.kwargs['vdus'].keys() + for node in temp_vduname: + if 'application' in \ + self.kwargs['vdus'][node]['parameters'].keys() \ + and 'OS'\ + in self.kwargs['vdus'][node]['parameters'].keys(): + self.vduname.append(node) + self.hostinfo[node] = copy.deepcopy(zapi.dVDU_INFO) + self.set_zbx_info(node) + self.hostinfo[node]['mgmt_ip'] = \ + self.kwargs['vdus'][node]['mgmt_ip'] + self.hostinfo[node]['parameters'] = \ + self.kwargs['vdus'][node]['parameters'] + self.hostinfo[node]['vdu_id'] = self.vnf['id'] + + def add_to_appmonitor(self, vnf, kwargs): + + self.__init__() + self.kwargs = kwargs + self.vnf = vnf + self.set_vdu_info() + self.tenant_id = self.vnf['vnfd']['tenant_id'] + self.add_host_to_zabbix() + + def monitor_call(self, vnf, kwargs): + pass + + def monitor_app_driver(self, plugin, context, vnf, service_instance): + return self.get_name() diff --git a/tacker/vnfm/monitor_drivers/zabbix/zabbix_api.py b/tacker/vnfm/monitor_drivers/zabbix/zabbix_api.py new file mode 100644 index 000000000..760fab63b --- /dev/null +++ b/tacker/vnfm/monitor_drivers/zabbix/zabbix_api.py @@ -0,0 +1,214 @@ +# +# 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. +# +URL_ = "/zabbix/api_jsonrpc.php" + +HEADERS = {'Content-Type': 'application/json-rpc'} +dAUTH_API = {'jsonrpc': "2.0", + 'method': 'user.login', + 'params': {'user': None, + 'password': None}, + 'id': 1, + 'auth': None} + +COMP_VALUE = {'greater': '>', + 'less': '<', + 'and greater': '>=', + 'and less': '<=', + 'down': '=0'} + + +dTEMPLATE_CREATE_API = {'jsonrpc': "2.0", 'method': "template.create", + 'params': {'host': "", 'groups': {'groupid': 1}, + 'hosts': []}, + 'id': 1004, 'auth': None} + +dITEM_CREATE_API = {'jsonrpc': "2.0", + 'method': "item.create", + 'params': {'hostid': None, + 'interfaceid': 'NULL', + 'name': "", + 'key_': "", + 'type': 0, + 'value_type': 3, + 'delay': 1}, + 'id': 1, + 'auth': None} + + +dITEM_KEY_VALUE = {'os_agent_info': 'agent.ping', + 'os_cpu_usage': 'system.cpu.util[,iowait]', + 'os_cpu_load': 'system.cpu.load[percpu,avg1]', + 'os_proc_value': 'proc.num[,,run]', + 'app_status': 'net.tcp.port[ ,*]', + 'app_memory': 'proc.mem[*,root]'} + +dITEM_KEY_COMP = {'os_agent_info': str( + dITEM_KEY_VALUE['os_agent_info'] + '.nodata(15s)}=1'), + 'os_cpu_usage': str( + dITEM_KEY_VALUE['os_cpu_usage'] + '.avg(5s)}'), + 'os_cpu_load': str( + dITEM_KEY_VALUE['os_cpu_load'] + '.avg(5s)}'), + 'os_proc_value': str( + dITEM_KEY_VALUE['os_proc_value'] + '.avg(5s)}'), + 'app_status': str( + dITEM_KEY_VALUE['app_status'] + '.last(,5)}'), + 'app_memory': str( + dITEM_KEY_VALUE['app_memory'] + '.avg(5s)}')} + +dITEM_KEY_INFO = {'os_proc_value': {'name': 'process number', + 'key_': str( + dITEM_KEY_VALUE['os_proc_value']), + 'value_type': 3}, + 'os_cpu_load': {'name': 'cpu load', + 'key_': str( + dITEM_KEY_VALUE['os_cpu_load']), + 'value_type': 0}, + 'os_cpu_usage': {'name': 'cpu util usage', + 'key_': str( + dITEM_KEY_VALUE['os_cpu_usage']), + 'value_type': 0}, + 'os_agent_info': {'name': 'Zabbix agent status check', + 'key_': str( + dITEM_KEY_VALUE['os_agent_info']), + 'value_type': 0}, + 'app_status': {'name': ' service status check', + 'key_': str( + dITEM_KEY_VALUE['app_status']), + 'value_type': 3}, + 'app_memory': {'name': ' service memory usage', + 'key_': str( + dITEM_KEY_VALUE['app_memory']), + 'value_type': 3}} + + +dTRIGGER_CREATE_API = {'jsonrpc': "2.0", + 'method': "trigger.create", + 'templateid': None, + 'auth': None, + 'id': 1004} + +dTRIGGER_INFO = {'itemname': None, + 'cmdname': None, + 'cmd-action': None} + +dTRIGGER_LIST = {'os_agent_info': [{'description': 'Zabbix agent on ' + '{HOST.NAME} is ' + 'unreachable ' + 'for 15 seconds', + 'expression': '{', 'priority': 3}], + 'app_status': [{'description': 'Service is down ' + 'on {HOST.NAME}', + 'expression': '{', 'priority': 3}], + 'app_memory': [{'description': 'Process Memory ' + 'is lacking ' + 'on {HOST.NAME}', + 'expression': '{', 'priority': 3}], + 'os_cpu_usage': [{'description': 'Disk I/O is ' + 'overloaded ' + 'on {HOST.NAME}', + 'expression': '{', 'priority': 3}], + 'os_cpu_load': [{'description': 'Processor load ' + 'is too high ' + 'on {HOST.NAME}', + 'expression': '{', 'priority': 3}], + 'os_proc_value': [{'description': 'Too many ' + 'processes running ' + 'on {HOST.NAME}', + 'expression': '{', 'priority': 3}]} + +dACTION_CREATE_API = {'jsonrpc': "2.0", + 'method': "action.create", + 'params': {'name': '', + 'eventsource': 0, + 'status': 0, + 'esc_period': 120, + 'def_shortdata': "{TRIGGER.NAME}:" + "{TRIGGER.STATUS}", + 'def_longdata': "{TRIGGER.NAME}: " + "{TR`IGGER.STATUS}\r\n" + "Last value: " + "{ITEM.LASTVALUE]" + "\r\n\r\n{TRIGGER.URL}", + "filter": {"evaltype": 0, + "conditions": [{'conditiontype': 2, + 'operator': 0, + 'value': None}]}, + 'operations': [{'operationtype': 1, + 'esc_period': 0, + 'esc_step_from': 1, + 'esc_step_to': 2, + 'evaltype': 0, + 'opcommand': { + 'command': None, + 'type': 0, + 'execute_on': 0}, + 'opcommand_hst': [ + {'hostid': None}] + }]}, + 'auth': None, 'id': 1} + +dHOST_CREATE_API = {'jsonrpc': "2.0", + 'method': "host.create", + 'params': {'host': 'ubuntu', + 'interfaces': [ + {'type': 1, + 'main': 1, + 'useip': 1, + 'dns': "", + 'ip': None, + 'port': "10050"}], + 'templates': [{'templateid': None}], + 'groups': [{'groupid': None}]}, + 'id': 4, 'auth': None} + +dGROUP_GET_API = {'jsonrpc': "2.0", 'method': "hostgroup.get", + 'params': {'output': 'extend', + 'filter': {'name': ["Zabbix servers", ]}}, + 'id': 1, 'auth': None} + +dGRAPH_CREATE_API = {'jsonrpc': '2.0', 'method': 'graph.create', + 'params': {'name': None, + 'width': 900, + 'height': 200, + 'gitems': []}, + 'auth': None, 'id': 1004} + +dAPP_INFO = {'app_port': None, + 'app_name': None, + 'ssh_username': None, + 'ssh_password': None} + +dZBX_INFO = {'zabbix_user': None, + 'zabbix_pass': None, + 'zabbix_ip': None, + 'zabbix_port': None, + 'zabbix_token': None + } + +dACTION_LIST = {'item': None, + 'action': None, + 'trigger_id': None, + 'cmd-action': None} + +dVDU_INFO = {'template_id': None, + 'template_name': None, + 'hostid': None, + 'group_id': None, + 'mgmt_ip': None, + 'vdu_id': None, + 'parameters': None, + 'actioninfo': [], + 'appinfo': None, + 'zbx_info': None + } diff --git a/tacker/vnfm/plugin.py b/tacker/vnfm/plugin.py index ff13eeba4..94b5a2449 100644 --- a/tacker/vnfm/plugin.py +++ b/tacker/vnfm/plugin.py @@ -32,11 +32,11 @@ from tacker.common import utils from tacker.db.vnfm import vnfm_db from tacker.extensions import vnfm from tacker.plugins.common import constants +from tacker.tosca import utils as toscautils from tacker.vnfm.mgmt_drivers import constants as mgmt_constants from tacker.vnfm import monitor from tacker.vnfm import vim_client -from tacker.tosca import utils as toscautils LOG = logging.getLogger(__name__) CONF = cfg.CONF @@ -143,6 +143,7 @@ class VNFMPlugin(vnfm_db.VNFMPluginDb, VNFMMgmtMixin): cfg.CONF.tacker.policy_action) self._vnf_monitor = monitor.VNFMonitor(self.boot_wait) self._vnf_alarm_monitor = monitor.VNFAlarmMonitor() + self._vnf_app_monitor = monitor.VNFAppMonitor() def spawn_n(self, function, *args, **kwargs): self._pool.spawn_n(function, *args, **kwargs) @@ -247,6 +248,10 @@ class VNFMPlugin(vnfm_db.VNFMPluginDb, VNFMMgmtMixin): vnf_dict['attributes'].update(alarm_url) break + def add_vnf_to_appmonitor(self, context, vnf_dict): + appmonitor = self._vnf_app_monitor.create_app_dict(context, vnf_dict) + self._vnf_app_monitor.add_to_appmonitor(appmonitor, vnf_dict) + def config_vnf(self, context, vnf_dict): config = vnf_dict['attributes'].get('config') if not config: @@ -392,6 +397,10 @@ class VNFMPlugin(vnfm_db.VNFMPluginDb, VNFMMgmtMixin): def create_vnf_wait(): self._create_vnf_wait(context, vnf_dict, vim_auth, infra_driver) + + if 'app_monitoring_policy' in vnf_dict['attributes']: + self.add_vnf_to_appmonitor(context, vnf_dict) + if vnf_dict['status'] is not constants.ERROR: self.add_vnf_to_monitor(context, vnf_dict) self.config_vnf(context, vnf_dict)