From 9e36d918fef054b8d23692c0ec8c25d7b0640c07 Mon Sep 17 00:00:00 2001 From: dongwenjuan Date: Mon, 27 Nov 2017 17:42:17 +0800 Subject: support vitrage inspector for local installer JIRA: DOCTOR-122 Change-Id: I771f778767a204e809d892c70603e479c1ed2f5c Signed-off-by: dongwenjuan --- doctor_tests/common/constants.py | 6 ++ doctor_tests/inspector/__init__.py | 9 ++- doctor_tests/inspector/sample.py | 2 +- doctor_tests/inspector/vitrage.py | 38 +++++++++++++ doctor_tests/installer/common/vitrage.py | 98 ++++++++++++++++++++++++++++++++ doctor_tests/installer/local.py | 11 +++- doctor_tests/monitor/sample.py | 31 +++++----- doctor_tests/os_clients.py | 7 +++ requirements.txt | 1 + 9 files changed, 179 insertions(+), 24 deletions(-) create mode 100644 doctor_tests/inspector/vitrage.py create mode 100644 doctor_tests/installer/common/vitrage.py diff --git a/doctor_tests/common/constants.py b/doctor_tests/common/constants.py index 72d037af..088ff633 100644 --- a/doctor_tests/common/constants.py +++ b/doctor_tests/common/constants.py @@ -10,3 +10,9 @@ from collections import namedtuple Host = namedtuple('Host', ['name', 'ip']) + + +class Inspector(object): + CONGRESS = 'congress' + SAMPLE = 'sample' + VITRAGE = 'vitrage' diff --git a/doctor_tests/inspector/__init__.py b/doctor_tests/inspector/__init__.py index a9a86ece..31291baf 100644 --- a/doctor_tests/inspector/__init__.py +++ b/doctor_tests/inspector/__init__.py @@ -11,10 +11,12 @@ import os from oslo_config import cfg from oslo_utils import importutils +from doctor_tests.common.constants import Inspector + OPTS = [ cfg.StrOpt('type', - default=os.environ.get('INSPECTOR_TYPE', 'sample'), + default=os.environ.get('INSPECTOR_TYPE', Inspector.SAMPLE), choices=['sample', 'congress', 'vitrage'], help='the component of doctor inspector', required=True), @@ -34,8 +36,9 @@ OPTS = [ _inspector_name_class_mapping = { - 'sample': 'doctor_tests.inspector.sample.SampleInspector', - 'congress': 'doctor_tests.inspector.congress.CongressInspector', + Inspector.SAMPLE: 'doctor_tests.inspector.sample.SampleInspector', + Inspector.CONGRESS: 'doctor_tests.inspector.congress.CongressInspector', + Inspector.VITRAGE: 'doctor_tests.inspector.vitrage.VitrageInspector', } diff --git a/doctor_tests/inspector/sample.py b/doctor_tests/inspector/sample.py index 54328727..fe67a903 100644 --- a/doctor_tests/inspector/sample.py +++ b/doctor_tests/inspector/sample.py @@ -63,7 +63,7 @@ class SampleInspector(BaseInspector): self.log.info('can not get hostname from server=%s' % server) def get_inspector_url(self): - return 'http://%s:%s' % (self.conf.inspector.ip, self.conf.inspector.port) + return 'http://%s:%s/events' % (self.conf.inspector.ip, self.conf.inspector.port) def start(self): self.log.info('sample inspector start......') diff --git a/doctor_tests/inspector/vitrage.py b/doctor_tests/inspector/vitrage.py new file mode 100644 index 00000000..7d1dbc1c --- /dev/null +++ b/doctor_tests/inspector/vitrage.py @@ -0,0 +1,38 @@ +############################################################################## +# Copyright (c) 2017 ZTE Corporation and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## +from doctor_tests.identity_auth import get_identity_auth +from doctor_tests.identity_auth import get_session +from doctor_tests.os_clients import keystone_client +from doctor_tests.os_clients import vitrage_client + +from doctor_tests.inspector.base import BaseInspector + + +class VitrageInspector(BaseInspector): + + def __init__(self, conf, log): + super(VitrageInspector, self).__init__(conf, log) + self.auth = get_identity_auth() + self.keystone = keystone_client(get_session(auth=self.auth)) + self.vitrage = vitrage_client(self.conf.vitrage_version, + get_session(auth=self.auth)) + self.inspector_url = self.get_inspector_url() + + def get_inspector_url(self): + vitrage_endpoint = \ + self.keystone.session.get_endpoint( + service_type='rca', + interface='publicURL') + return '%s/v1/event' % vitrage_endpoint + + def start(self): + self.log.info('vitrage inspector start......') + + def stop(self): + self.log.info('vitrage inspector stop......') diff --git a/doctor_tests/installer/common/vitrage.py b/doctor_tests/installer/common/vitrage.py new file mode 100644 index 00000000..9ea32271 --- /dev/null +++ b/doctor_tests/installer/common/vitrage.py @@ -0,0 +1,98 @@ +############################################################################## +# Copyright (c) 2017 ZTE Corporation and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## +import os + + +vitrage_template_file = '/etc/vitrage/templates/vitrage_host_down_scenarios.yaml' + +template = """ +metadata: + name: host_down_scenarios + description: scenarios triggered by Doctor monitor 'compute.host.down' alarm +definitions: + entities: + - entity: + category: ALARM + name: compute.host.down + template_id: host_down_alarm + - entity: + category: ALARM + type: vitrage + name: Instance Down + template_id: instance_alarm + - entity: + category: RESOURCE + type: nova.instance + template_id: instance + - entity: + category: RESOURCE + type: nova.host + template_id: host + relationships: + - relationship: + source: host_down_alarm + relationship_type: on + target: host + template_id : host_down_alarm_on_host + - relationship: + source: host + relationship_type: contains + target: instance + template_id : host_contains_instance + - relationship: + source: instance_alarm + relationship_type: on + target: instance + template_id : alarm_on_instance +scenarios: + - scenario: + condition: host_down_alarm_on_host + actions: + - action: + action_type: set_state + action_target: + target: host + properties: + state: ERROR + - action: + action_type: mark_down + action_target: + target: host + - scenario: + condition: host_down_alarm_on_host and host_contains_instance + actions: + - action: + action_type: raise_alarm + action_target: + target: instance + properties: + alarm_name: Instance Down + severity: critical + - scenario: + condition: host_down_alarm_on_host and host_contains_instance and alarm_on_instance + actions: + - action: + action_type: add_causal_relationship + action_target: + source: host_down_alarm + target: instance_alarm + - action: + action_type: mark_down + action_target: + target: instance +""" + + +def set_vitrage_host_down_template(): + if os.path.isfile(vitrage_template_file): + print('Vitrage host_down template file: %s already exists.' % vitrage_template_file) + else: + print('Create Vitrage host_down template file:%s.' % vitrage_template_file) + with open(vitrage_template_file, 'w') as file: + file.write(template) diff --git a/doctor_tests/installer/local.py b/doctor_tests/installer/local.py index 7d0ae542..453755c2 100644 --- a/doctor_tests/installer/local.py +++ b/doctor_tests/installer/local.py @@ -11,6 +11,8 @@ import shutil import subprocess from doctor_tests.installer.base import BaseInstaller +from doctor_tests.installer.common.vitrage import set_vitrage_host_down_template +from doctor_tests.common.constants import Inspector from doctor_tests.common.utils import load_json_file from doctor_tests.common.utils import write_json_file @@ -43,13 +45,16 @@ class LocalInstaller(BaseInstaller): cmd = "getent hosts %s | awk '{ print $1 }'" % (hostname) server = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True) stdout, stderr = server.communicate() - host_ip = stdout.strip() + host_ip = stdout.strip().decode("utf-8") self.log.info('Get host_ip:%s from host_name:%s in local installer' % (host_ip, hostname)) return host_ip def set_apply_patches(self): self._set_nova_policy() + if self.conf.inspector.type == Inspector.VITRAGE: + set_vitrage_host_down_template() + os.system('sudo systemctl restart devstack@vitrage-graph.service') def restore_apply_patches(self): self._restore_nova_policy() @@ -94,7 +99,7 @@ class LocalInstaller(BaseInstaller): if self.policy_modified or self.add_policy_file: write_json_file(self.nova_policy_file, data) - os.system('screen -S stack -p n-api -X stuff "^C^M^[[A^M"') + os.system('sudo systemctl restart devstack@n-api.service') def _restore_nova_policy(self): if self.policy_modified: @@ -104,6 +109,6 @@ class LocalInstaller(BaseInstaller): os.remove(self.nova_policy_file) if self.add_policy_file or self.policy_modified: - os.system('screen -S stack -p n-api -X stuff "^C^M^[[A^M"') + os.system('sudo systemctl restart devstack@n-api.service') self.add_policy_file = False self.policy_modified = False diff --git a/doctor_tests/monitor/sample.py b/doctor_tests/monitor/sample.py index 7a463048..4dc5e603 100644 --- a/doctor_tests/monitor/sample.py +++ b/doctor_tests/monitor/sample.py @@ -13,6 +13,7 @@ import socket from threading import Thread import time +from doctor_tests.common.constants import Inspector from doctor_tests.identity_auth import get_session from doctor_tests.monitor.base import BaseMonitor @@ -38,19 +39,16 @@ class SampleMonitor(BaseMonitor): def report_error(self, hostname): self.log.info('sample monitor report error......') - data = [ - { - 'id': 'monitor_sample_id1', - 'time': datetime.now().isoformat(), - 'type': self.event_type, - 'details': { - 'hostname': hostname, - 'status': 'down', - 'monitor': 'monitor_sample', - 'monitor_event_id': 'monitor_sample_event1' - }, + data = { + 'time': datetime.now().isoformat(), + 'type': self.event_type, + 'details': { + 'hostname': hostname, + 'status': 'down', + 'monitor': 'monitor_sample', + 'monitor_event_id': 'monitor_sample_event1' }, - ] + } auth_token = self.session.get_token() if \ self.conf.inspector.type != 'sample' else None @@ -59,11 +57,10 @@ class SampleMonitor(BaseMonitor): 'Accept': 'application/json', 'X-Auth-Token': auth_token, } - - url = '%s%s' % (self.inspector_url, 'events') \ - if self.inspector_url.endswith('/') else \ - '%s%s' % (self.inspector_url, '/events') - requests.put(url, data=json.dumps(data), headers=headers) + if self.conf.inspector.type != Inspector.VITRAGE: + requests.put(self.inspector_url, data=json.dumps([data]), headers=headers) + else: + requests.post(self.inspector_url, data=json.dumps(data), headers=headers) class Pinger(Thread): diff --git a/doctor_tests/os_clients.py b/doctor_tests/os_clients.py index 44fa3aad..5606d40a 100644 --- a/doctor_tests/os_clients.py +++ b/doctor_tests/os_clients.py @@ -14,12 +14,14 @@ import glanceclient.client as glanceclient from keystoneclient.v2_0 import client as ks_client from neutronclient.v2_0 import client as neutronclient import novaclient.client as novaclient +import vitrageclient.client as vitrageclient OPTS = [ cfg.StrOpt('glance_version', default='2', help='glance version'), cfg.StrOpt('nova_version', default='2.34', help='Nova version'), cfg.StrOpt('aodh_version', default='2', help='aodh version'), + cfg.StrOpt('vitrage_version', default='1', help='vitrage version'), ] @@ -48,3 +50,8 @@ def aodh_client(version, session): def congress_client(session): return congressclient.Client(session=session, service_type='policy') + + +def vitrage_client(version, session): + return vitrageclient.Client(version=version, + session=session) diff --git a/requirements.txt b/requirements.txt index 289aae2d..0f4e88be 100644 --- a/requirements.txt +++ b/requirements.txt @@ -14,4 +14,5 @@ python-neutronclient>=6.3.0 # Apache-2.0 python-novaclient>=9.0.0 # Apache-2.0 python-congressclient<2000,>=1.3.0 # Apache-2.0 python-glanceclient>=2.8.0 # Apache-2.0 +python-vitrageclient>=1.2.0 # Apache-2.0 virtualenv>=13.1.0 # MIT -- cgit 1.2.3-korg