From 7e83d0876ddb84a45e130eeba28bc40ef53c074b Mon Sep 17 00:00:00 2001 From: Yaron Yogev Date: Thu, 27 Jul 2017 09:02:54 +0300 Subject: Calipso initial release for OPNFV Change-Id: I7210c244b0c10fa80bfa8c77cb86c9d6ddf8bc88 Signed-off-by: Yaron Yogev --- app/monitoring/setup/__init__.py | 10 + app/monitoring/setup/monitoring_check_handler.py | 54 +++ app/monitoring/setup/monitoring_handler.py | 485 +++++++++++++++++++++ app/monitoring/setup/monitoring_host.py | 91 ++++ .../setup/monitoring_link_vnic_vconnector.py | 37 ++ app/monitoring/setup/monitoring_otep.py | 34 ++ app/monitoring/setup/monitoring_pnic.py | 21 + app/monitoring/setup/monitoring_setup_manager.py | 84 ++++ app/monitoring/setup/monitoring_simple_object.py | 25 ++ app/monitoring/setup/monitoring_vedge.py | 19 + app/monitoring/setup/monitoring_vnic.py | 20 + app/monitoring/setup/monitoring_vservice.py | 23 + 12 files changed, 903 insertions(+) create mode 100644 app/monitoring/setup/__init__.py create mode 100644 app/monitoring/setup/monitoring_check_handler.py create mode 100644 app/monitoring/setup/monitoring_handler.py create mode 100644 app/monitoring/setup/monitoring_host.py create mode 100644 app/monitoring/setup/monitoring_link_vnic_vconnector.py create mode 100644 app/monitoring/setup/monitoring_otep.py create mode 100644 app/monitoring/setup/monitoring_pnic.py create mode 100644 app/monitoring/setup/monitoring_setup_manager.py create mode 100644 app/monitoring/setup/monitoring_simple_object.py create mode 100644 app/monitoring/setup/monitoring_vedge.py create mode 100644 app/monitoring/setup/monitoring_vnic.py create mode 100644 app/monitoring/setup/monitoring_vservice.py (limited to 'app/monitoring/setup') diff --git a/app/monitoring/setup/__init__.py b/app/monitoring/setup/__init__.py new file mode 100644 index 0000000..1e85a2a --- /dev/null +++ b/app/monitoring/setup/__init__.py @@ -0,0 +1,10 @@ +############################################################################### +# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) # +# 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 # +############################################################################### + diff --git a/app/monitoring/setup/monitoring_check_handler.py b/app/monitoring/setup/monitoring_check_handler.py new file mode 100644 index 0000000..1c9a013 --- /dev/null +++ b/app/monitoring/setup/monitoring_check_handler.py @@ -0,0 +1,54 @@ +############################################################################### +# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) # +# 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 monitoring.setup.monitoring_handler import MonitoringHandler +from utils.inventory_mgr import InventoryMgr +from utils.special_char_converter import SpecialCharConverter + + +class MonitoringCheckHandler(MonitoringHandler, SpecialCharConverter): + + def __init__(self, env): + super().__init__(env) + + # add monitoring setup on remote host for given object + def create_monitoring_for_object(self, o, values): + self.replacements.update(self.env_monitoring_config) + self.replacements.update(values) + if 'host' in o: + host = self.inv.get_by_id(self.env, o['host']) + if host and 'ip_address' in host: + self.replacements['client_ip'] = host['ip_address'] + type_str = o['type'] if 'type' in o else 'link_' + o['link_type'] + file_type = 'client_check_' + type_str + '.json' + host = o['host'] + sub_dir = '/host/' + host + content = self.prepare_config_file( + file_type, + {'side': 'client', 'type': file_type}) + # need to put this content inside client.json file + client_file = 'client.json' + host = o['host'] + client_file_content = self.get_config_from_db(host, client_file) + # merge checks attribute from current content into client.json + checks = client_file_content['config']['checks'] \ + if (client_file_content and + 'checks' in client_file_content['config']) \ + else {} + checks.update(content.get('config', {}).get('checks', {})) + if client_file_content: + client_file_content['config']['checks'] = checks + else: + client_file_content = { + 'config': { + 'checks': checks + } + } + content = client_file_content + self.write_config_file(client_file, sub_dir, host, content) diff --git a/app/monitoring/setup/monitoring_handler.py b/app/monitoring/setup/monitoring_handler.py new file mode 100644 index 0000000..5b7cae0 --- /dev/null +++ b/app/monitoring/setup/monitoring_handler.py @@ -0,0 +1,485 @@ +############################################################################### +# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) # +# 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 # +############################################################################### +# handle specific setup of monitoring + +import os +import json +import subprocess +from socket import * + +import copy +import pymongo +import shutil +import stat +from boltons.iterutils import remap + +from discover.configuration import Configuration +from discover.fetchers.cli.cli_access import CliAccess +from utils.binary_converter import BinaryConverter +from utils.deep_merge import remerge +from utils.inventory_mgr import InventoryMgr +from utils.logging.full_logger import FullLogger +from utils.mongo_access import MongoAccess +from utils.ssh_conn import SshConn +from utils.ssh_connection import SshConnection + + +class MonitoringHandler(MongoAccess, CliAccess, BinaryConverter): + PRODUCTION_CONFIG_DIR = '/etc/sensu/conf.d' + APP_SCRIPTS_FOLDER = 'monitoring/checks' + REMOTE_SCRIPTS_FOLDER = '/etc/sensu/plugins' + TMP_SSL_FOLDER = '/tmp/monitoring_ssl_files' + + provision_levels = { + 'none': 0, + 'db': 1, + 'files': 2, + 'deploy': 3 + } + + pending_changes = {} + + fetch_ssl_files = [] + + def __init__(self, env): + super().__init__() + self.log = FullLogger() + self.configuration = Configuration() + self.mechanism_drivers = \ + self.configuration.environment['mechanism_drivers'] + self.env = env + self.monitoring_config = self.db.monitoring_config_templates + try: + self.env_monitoring_config = self.configuration.get('Monitoring') + except IndexError: + self.env_monitoring_config = {} + self.local_host = self.env_monitoring_config.get('server_ip', '') + self.scripts_prepared_for_host = {} + self.replacements = self.env_monitoring_config + self.inv = InventoryMgr() + self.config_db = self.db[self.inv.get_coll_name('monitoring_config')] + self.provision = self.provision_levels['none'] + if self.env_monitoring_config: + provision = self.env_monitoring_config.get('provision', 'none') + provision = str.lower(provision) + self.provision =\ + self.provision_levels.get(provision, + self.provision_levels['none']) + + # create a directory if it does not exist + @staticmethod + def make_directory(directory): + if not os.path.exists(directory): + os.makedirs(directory) + return directory + + def get_config_dir(self, sub_dir=''): + config_folder = self.env_monitoring_config['config_folder'] + \ + (os.sep + sub_dir if sub_dir else '') + return self.make_directory(config_folder).rstrip(os.sep) + + def prepare_config_file(self, file_type, base_condition): + condition = base_condition + condition['type'] = file_type + sort = [('order', pymongo.ASCENDING)] + docs = self.monitoring_config.find(condition, sort=sort) + content = {} + for doc in docs: + if not self.check_env_condition(doc): + return {} + content.update(doc) + self.replacements['app_path'] = \ + self.configuration.environment['app_path'] + config = self.content_replace({'config': content.get('config', {})}) + return config + + def check_env_condition(self, doc): + if 'condition' not in doc: + return True + condition = doc['condition'] + if 'mechanism_drivers' not in condition: + return True + required_mechanism_drivers = condition['mechanism_drivers'] + if not isinstance(required_mechanism_drivers, list): + required_mechanism_drivers = [required_mechanism_drivers] + intersection = [val for val in required_mechanism_drivers + if val in self.mechanism_drivers] + return bool(intersection) + + def content_replace(self, content): + content_remapped = remap(content, visit=self.fill_values) + return content_remapped + + def format_string(self, val): + formatted = val if not isinstance(val, str) or '{' not in val \ + else val.format_map(self.replacements) + return formatted + + def fill_values(self, path, key, value): + if not path: + return key, value + key_formatted = self.format_string(key) + value_formatted = self.format_string(value) + return key_formatted, value_formatted + + def get_config_from_db(self, host, file_type): + find_tuple = { + 'environment': self.env, + 'host': host, + 'type': file_type + } + doc = self.config_db.find_one(find_tuple) + if not doc: + return {} + doc.pop("_id", None) + return self.decode_mongo_keys(doc) + + def write_config_to_db(self, host, config, file_type): + find_tuple = { + 'environment': self.env, + 'host': host, + 'type': file_type + } + doc = copy.copy(find_tuple) + doc['config'] = config + doc = self.encode_mongo_keys(doc) + if not doc: + return {} + self.config_db.update_one(find_tuple, {'$set': doc}, upsert=True) + + def merge_config(self, host, file_type, content): + """ + merge current monitoring config of host + with newer content. + return the merged config + """ + doc = self.get_config_from_db(host, file_type) + config = remerge([doc['config'], content.get('config')]) if doc \ + else content.get('config', {}) + self.write_config_to_db(host, config, file_type) + return config + + def write_config_file(self, file_name, sub_dir, host, content, + is_container=False, is_server=False): + """ + apply environment definitions to the config, + e.g. replace {server_ip} with the IP or host name for the server + """ + # save the config to DB first, and while doing that + # merge it with any existing config on same host + content = self.merge_config(host, file_name, content) + + if self.provision == self.provision_levels['db']: + self.log.debug('Monitoring setup kept only in DB') + return + # now dump the config to the file + content_json = json.dumps(content.get('config', content), + sort_keys=True, indent=4) + content_json += '\n' + # always write the file locally first + local_dir = self.make_directory(os.path.join(self.get_config_dir(), + sub_dir.strip(os.path.sep))) + local_path = os.path.join(local_dir, file_name) + self.write_to_local_host(local_path, content_json) + self.track_setup_changes(host, is_container, file_name, local_path, + sub_dir, is_server=is_server) + + def add_changes_for_all_clients(self): + """ + to debug deployment, add simulated track changes entries. + no need to add for server, as these are done by server_setup() + """ + docs = self.config_db.find({'environment': self.env}) + for doc in docs: + host = doc['host'] + sub_dir = os.path.join('host', host) + file_name = doc['type'] + config_folder = self.env_monitoring_config['config_folder'] + local_path = os.path.join(config_folder, sub_dir, file_name) + if host == self.env_monitoring_config['server_ip']: + continue + self.track_setup_changes(host, False, file_name, local_path, + sub_dir) + + def get_ssh(self, host, is_container=False, for_sftp=False): + ssh = SshConnection.get_ssh(host, for_sftp) + if not ssh: + if is_container: + conf = self.env_monitoring_config + host = conf['server_ip'] + port = int(conf['ssh_port']) + user = conf['ssh_user'] + pwd = conf['ssh_password'] + ssh = SshConnection(host, user, _pwd=pwd, _port=port, + for_sftp=for_sftp) + else: + ssh = SshConn(host, for_sftp=for_sftp) + return ssh + + def track_setup_changes(self, host=None, is_container=False, file_name=None, + local_path=None, sub_dir=None, + is_server=False, + target_mode=None, + target_path=PRODUCTION_CONFIG_DIR): + if host not in self.pending_changes: + self.pending_changes[host] = {} + if file_name not in self.pending_changes[host]: + self.pending_changes[host][file_name] = { + "host": host, + "is_container": is_container, + "is_server": is_server, + "file_name": file_name, + "local_path": local_path, + "sub_dir": sub_dir, + "target_path": target_path, + "target_mode": target_mode + } + + def handle_pending_setup_changes(self): + if self.provision < self.provision_levels['files']: + if self.provision == self.provision_levels['db']: + self.log.info('Monitoring config applied only in DB') + return + self.log.info('applying monitoring setup') + hosts = {} + scripts_to_hosts = {} + for host, host_changes in self.pending_changes.items(): + self.handle_pending_host_setup_changes(host_changes, hosts, + scripts_to_hosts) + if self.provision < self.provision_levels['deploy']: + return + if self.fetch_ssl_files: + self.deploy_ssl_files(list(scripts_to_hosts.keys())) + for host in scripts_to_hosts.values(): + self.deploy_scripts_to_host(host) + for host in hosts.values(): + self.deploy_config_to_target(host) + self.log.info('done applying monitoring setup') + + def handle_pending_host_setup_changes(self, host_changes, hosts, + scripts_to_hosts): + if self.provision < self.provision_levels['deploy']: + self.log.info('Monitoring config not deployed to remote host') + for file_type, changes in host_changes.items(): + host = changes['host'] + is_container = changes['is_container'] + is_server = changes['is_server'] + local_dir = changes['local_path'] + if local_dir == "scripts": + scripts_to_hosts[host] = {'host': host, 'is_server': is_server} + continue + self.log.debug('applying monitoring setup changes ' + + 'for host ' + host + ', file type: ' + file_type) + is_local_host = host == self.local_host + file_path = os.path.join(self.PRODUCTION_CONFIG_DIR, file_type) + if not is_server and host not in hosts: + hosts[host] = { + 'host': host, + 'local_dir': local_dir, + 'is_local_host': is_local_host, + 'is_container': is_container, + 'is_server': is_server + } + if is_server: + remote_path = self.PRODUCTION_CONFIG_DIR + if os.path.isfile(local_dir): + remote_path += os.path.sep + os.path.basename(local_dir) + self.write_to_server(local_dir, + remote_path=remote_path, + is_container=is_container) + elif is_local_host: + # write to production configuration directory on local host + self.make_directory(self.PRODUCTION_CONFIG_DIR) + shutil.copy(changes['local_path'], file_path) + else: + # write to remote host prepare dir - use sftp + if self.provision < self.provision_levels['deploy']: + continue + self.write_to_remote_host(host, changes['local_path']) + + def prepare_scripts(self, host, is_server): + if self.scripts_prepared_for_host.get(host, False): + return + gateway_host = SshConn.get_gateway_host(host) + # copy scripts to host + scripts_dir = os.path.join(self.env_monitoring_config['app_path'], + self.APP_SCRIPTS_FOLDER) + script_files = [f for f in os.listdir(scripts_dir) + if os.path.isfile(os.path.join(scripts_dir, f))] + script_mode = stat.S_IRWXU | stat.S_IRGRP | stat.S_IXGRP | \ + stat.S_IROTH | stat.S_IXOTH + target_host = host if is_server else gateway_host + self.make_remote_dir(target_host, self.REMOTE_SCRIPTS_FOLDER) + for file_name in script_files: + remote_path = os.path.join(self.REMOTE_SCRIPTS_FOLDER, file_name) + local_path = os.path.join(scripts_dir, file_name) + if not os.path.isfile(local_path): + continue + if is_server: + ssh = self.get_ssh(target_host, for_sftp=True) + ssh.copy_file(local_path, remote_path, mode=script_mode) + else: + self.copy_to_remote_host(target_host, local_path, remote_path, + mode=script_mode, + make_remote_dir=False) + self.scripts_prepared_for_host[host] = True + + def deploy_ssl_files(self, hosts: list): + monitoring_server = self.env_monitoring_config['server_ip'] + gateway_host = SshConn.get_gateway_host(hosts[0]) + self.make_directory(self.TMP_SSL_FOLDER) + for file_path in self.fetch_ssl_files: + # copy SSL files from the monitoring server + file_name = os.path.basename(file_path) + local_path = os.path.join(self.TMP_SSL_FOLDER, file_name) + self.get_file(monitoring_server, file_path, local_path) + # first copy the files to the gateway + self.write_to_remote_host(gateway_host, local_path, + remote_path=file_path) + ssl_path = os.path.commonprefix(self.fetch_ssl_files) + for host in hosts: + self.copy_from_gateway_to_host(host, ssl_path, ssl_path) + # remove files from temporary folder + for file_path in self.fetch_ssl_files: + tmp_path = os.path.join(self.TMP_SSL_FOLDER, + os.path.basename(file_path)) + if os.path.exists(tmp_path): + os.remove(tmp_path) # remove files from temporary folder + + def deploy_scripts_to_host(self, host_details): + host = host_details['host'] + is_server = host_details['is_server'] + self.prepare_scripts(host, is_server) + remote_path = self.REMOTE_SCRIPTS_FOLDER + local_path = remote_path + os.path.sep + '*.py' + if is_server: + return # this was done earlier + self.copy_from_gateway_to_host(host, local_path, remote_path) + + def restart_service(self, host: str = None, + service: str = 'sensu-client', + is_server: bool = False, + msg: str =None): + ssh = self.get_ssh(host) + cmd = 'sudo /etc/init.d/{} restart'.format(service) + log_msg = msg if msg else 'deploying config to host {}'.format(host) + self.log.info(log_msg) + if is_server: + ssh.exec(cmd) + else: + self.run(cmd, ssh_to_host=host, ssh=ssh) + + def deploy_config_to_target(self, host_details): + host = host_details['host'] + is_local_host = host_details['is_local_host'] + is_container = host_details['is_container'] + is_server = host_details['is_server'] + local_dir = host_details['local_dir'] + if is_container or is_server or not is_local_host: + local_dir = os.path.dirname(local_dir) + if not is_server: + self.move_setup_files_to_remote_host(host, local_dir) + # restart the Sensu client on the remote host, + # so it takes the new setup + self.restart_service(host) + + def run_cmd_locally(self, cmd): + try: + subprocess.popen(cmd.split(), + shell=True, + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + except subprocess.CalledProcessError as e: + print("Error running command: " + cmd + + ", output: " + self.binary2str(e.output) + "\n") + + def move_setup_files_to_remote_host(self, host, local_dir): + if self.provision < self.provision_levels['deploy']: + self.log.info('Monitoring config not written to remote host') + return + # need to scp the files from the gateway host to the target host + remote_path = self.PRODUCTION_CONFIG_DIR + self.copy_from_gateway_to_host(host, local_dir, remote_path) + + def copy_from_gateway_to_host(self, host, local_dir, remote_path): + ssh = self.get_ssh(host) + what_to_copy = local_dir if '*' in local_dir else local_dir + '/*' + if ssh.is_gateway_host(host): + # on gateway host, perform a simple copy + # make sure the source and destination are not the same + local_dir_base = local_dir[:local_dir.rindex('/*')] \ + if '/*' in local_dir else local_dir + if local_dir_base.strip('/*') == remote_path.strip('/*'): + return # same directory - nothing to do + cmd = 'cp {} {}'.format(what_to_copy, remote_path) + self.run(cmd, ssh=ssh) + return + self.make_remote_dir(host, remote_path) + remote_path = ssh.get_user() + '@' + host + ':' + \ + remote_path + os.sep + self.run_on_gateway('scp {} {}'.format(what_to_copy, remote_path), + enable_cache=False, + use_sudo=None) + + def make_remote_dir_on_host(self, ssh, host, path, path_is_file=False): + # make sure we have write permissions in target directories + dir_path = path + if path_is_file: + dir_path = os.path.dirname(dir_path) + cmd = 'sudo mkdir -p ' + dir_path + try: + self.run(cmd, ssh_to_host=host, ssh=ssh) + except timeout: + self.log.error('timed out trying to create directory {} on host {}' + .format(dir_path, host)) + return + cmd = 'sudo chown -R ' + ssh.get_user() + ' ' + dir_path + self.run(cmd, ssh_to_host=host, ssh=ssh) + + def make_remote_dir(self, host, path, path_is_file=False): + ssh = self.get_ssh(host, for_sftp=True) + self.make_remote_dir_on_host(ssh, host, path, path_is_file) + + def copy_to_remote_host(self, host, local_path, remote_path, mode=None, + make_remote_dir=True): + # copy the local file to the preparation folder for the remote host + # on the gateway host + ssh = self.get_ssh(host) + gateway_host = ssh.get_gateway_host(host) + if make_remote_dir: + self.make_remote_dir(gateway_host, remote_path, path_is_file=True) + ftp_ssh = self.get_ssh(gateway_host, for_sftp=True) + ftp_ssh.copy_file(local_path, remote_path, mode) + + def write_to_remote_host(self, host, local_path=None, remote_path=None): + remote_path = remote_path if remote_path else local_path + self.copy_to_remote_host(host, local_path, remote_path) + + def write_to_server(self, local_path, remote_path=None, is_container=False): + host = self.env_monitoring_config['server_ip'] + ssh = self.get_ssh(host, is_container=is_container) + remote_path = remote_path if remote_path else local_path + self.make_remote_dir_on_host(ssh, host, remote_path, True) + # copy to config dir first + ftp_ssh = self.get_ssh(host, is_container=is_container, for_sftp=True) + ftp_ssh.copy_file(local_path, remote_path) + + @staticmethod + def write_to_local_host(file_path, content): + f = open(file_path, "w") + f.write(content) + f.close() + return file_path + + def get_file(self, host, remote_path, local_path): + ftp_ssh = self.get_ssh(host, for_sftp=True) + ftp_ssh.copy_file_from_remote(remote_path, local_path) + diff --git a/app/monitoring/setup/monitoring_host.py b/app/monitoring/setup/monitoring_host.py new file mode 100644 index 0000000..800b5a2 --- /dev/null +++ b/app/monitoring/setup/monitoring_host.py @@ -0,0 +1,91 @@ +############################################################################### +# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) # +# 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 copy +import os +from os.path import join, sep + +from monitoring.setup.monitoring_handler import MonitoringHandler + +RABBITMQ_CONFIG_FILE = 'rabbitmq.json' +RABBITMQ_CONFIG_ATTR = 'rabbitmq' + +RABBITMQ_CERT_FILE_ATTR = 'cert_chain_file' +RABBITMQ_PK_FILE_ATTR = 'private_key_file' +TMP_FILES_DIR = '/tmp' + + +class MonitoringHost(MonitoringHandler): + + def __init__(self, env): + super().__init__(env) + + # add monitoring setup for remote host + def create_setup(self, o): + sensu_host_files = [ + 'transport.json', + 'rabbitmq.json', + 'client.json' + ] + server_ip = self.env_monitoring_config['server_ip'] + host_id = o['host'] + sub_dir = join('/host', host_id) + config = copy.copy(self.env_monitoring_config) + env_name = self.configuration.env_name + client_name = env_name + '-' + o['id'] + client_ip = o['ip_address'] if 'ip_address' in o else o['id'] + self.replacements.update(config) + self.replacements.update({ + 'server_ip': server_ip, + 'client_name': client_name, + 'client_ip': client_ip, + 'env_name': env_name + }) + + # copy configuration files + for file_name in sensu_host_files: + content = self.prepare_config_file(file_name, {'side': 'client'}) + self.get_ssl_files(host_id, file_name, content) + self.write_config_file(file_name, sub_dir, host_id, content) + + if self.provision < self.provision_levels['deploy']: + return + + self.track_setup_changes(host_id, False, "", "scripts", None) + + # mark this environment as prepared + self.configuration.update_env({'monitoring_setup_done': True}) + + def get_ssl_files(self, host, file_type, content): + if self.fetch_ssl_files: + return # already got names of SSL files + if file_type != RABBITMQ_CONFIG_FILE: + return + if not isinstance(content, dict): + self.log.warn('invalid content of {}'.format(RABBITMQ_CONFIG_FILE)) + return + config = content['config'] + if not config: + self.log.warn('invalid content of {}'.format(RABBITMQ_CONFIG_FILE)) + return + if RABBITMQ_CONFIG_ATTR not in config: + self.log.warn('invalid content of {}'.format(RABBITMQ_CONFIG_FILE)) + return + ssl_conf = config.get(RABBITMQ_CONFIG_ATTR).get('ssl') + if not ssl_conf: + return # SSL not used + + for path_attr in [RABBITMQ_CERT_FILE_ATTR, RABBITMQ_PK_FILE_ATTR]: + path = ssl_conf.get(path_attr) + if not path: + self.log.error('missing SSL path {}'.format(path_attr)) + return + # this configuration requires SSL + # keep the path of the files for later use + self.fetch_ssl_files.append(path) diff --git a/app/monitoring/setup/monitoring_link_vnic_vconnector.py b/app/monitoring/setup/monitoring_link_vnic_vconnector.py new file mode 100644 index 0000000..18f04e4 --- /dev/null +++ b/app/monitoring/setup/monitoring_link_vnic_vconnector.py @@ -0,0 +1,37 @@ +############################################################################### +# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) # +# 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 monitoring.setup.monitoring_check_handler import MonitoringCheckHandler + + +class MonitoringLinkVnicVconnector(MonitoringCheckHandler): + + def __init__(self, env): + super().__init__(env) + + # add monitoring setup for remote host + def create_setup(self, link): + vnic = self.inv.get_by_id(self.env, link['source_id']) + if not vnic: + self.log.error('could not find vnic for vnic-vconnector link') + return + if 'mac_address' not in vnic: + self.log.error('could not find MAC address in vNIC: ' + vnic['id']) + return + vconnector = self.inv.get_by_id(self.env, link['target_id']) + if not vnic: + self.log.error('could not find vconnector for vnic-vconnector link') + return + values = { + 'linktype': 'vnic-vconnector', + 'fromobjid': self.encode_special_characters(vnic['id']), + 'toobjid': vconnector['id'], + 'bridge': vconnector['object_name'], + 'mac_address': vnic['mac_address']} + self.create_monitoring_for_object(link, values) diff --git a/app/monitoring/setup/monitoring_otep.py b/app/monitoring/setup/monitoring_otep.py new file mode 100644 index 0000000..366bd77 --- /dev/null +++ b/app/monitoring/setup/monitoring_otep.py @@ -0,0 +1,34 @@ +############################################################################### +# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) # +# 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 monitoring.setup.monitoring_check_handler import MonitoringCheckHandler + + +class MonitoringOtep(MonitoringCheckHandler): + + def __init__(self, env): + super().__init__(env) + + # add monitoring setup for remote host + def create_setup(self, o): + if o['ports']: + for port in o['ports'].values(): + self.create_monitoring_for_otep_port(o, port) + + def create_monitoring_for_otep_port(self, o, port): + if port['type'] not in ['vxlan', 'gre']: + return # we only handle vxlan and gre + opt = port['options'] + values = { + "objtype": "otep", + "objid": o['id'], + "portid": port['name'], + "otep_src_ip": opt['local_ip'], + "otep_dest_ip": opt['remote_ip']} + self.create_monitoring_for_object(o, values) diff --git a/app/monitoring/setup/monitoring_pnic.py b/app/monitoring/setup/monitoring_pnic.py new file mode 100644 index 0000000..d64c8ff --- /dev/null +++ b/app/monitoring/setup/monitoring_pnic.py @@ -0,0 +1,21 @@ +############################################################################### +# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) # +# 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 monitoring.setup.monitoring_simple_object import MonitoringSimpleObject + + +class MonitoringPnic(MonitoringSimpleObject): + + def __init__(self, env): + super().__init__(env) + + # add monitoring setup for remote host + def create_setup(self, o): + if o.get("pnic_type") != "switch": + self.setup('pnic', o) diff --git a/app/monitoring/setup/monitoring_setup_manager.py b/app/monitoring/setup/monitoring_setup_manager.py new file mode 100644 index 0000000..d6ada33 --- /dev/null +++ b/app/monitoring/setup/monitoring_setup_manager.py @@ -0,0 +1,84 @@ +############################################################################### +# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) # +# 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 # +############################################################################### +# handle adding of monitoring setup as needed + +from monitoring.setup.monitoring_handler import MonitoringHandler +from monitoring.setup.monitoring_host import MonitoringHost +from monitoring.setup.monitoring_link_vnic_vconnector \ + import MonitoringLinkVnicVconnector +from monitoring.setup.monitoring_pnic import MonitoringPnic +from monitoring.setup.monitoring_otep import MonitoringOtep +from monitoring.setup.monitoring_vedge import MonitoringVedge +from monitoring.setup.monitoring_vnic import MonitoringVnic +from monitoring.setup.monitoring_vservice import MonitoringVservice + + +class MonitoringSetupManager(MonitoringHandler): + + object_handlers = None + + def __init__(self, env): + super().__init__(env) + self.object_handlers = { + "host": MonitoringHost(env), + "otep": MonitoringOtep(env), + "vedge": MonitoringVedge(env), + "pnic": MonitoringPnic(env), + "vnic": MonitoringVnic(env), + "vservice": MonitoringVservice(env), + "vnic-vconnector": MonitoringLinkVnicVconnector(env)} + + # add monitoring setup to Sensu server + def server_setup(self): + if self.provision == self.provision_levels['none']: + self.log.debug('Monitoring config setup skipped') + return + sensu_server_files = [ + 'transport.json', + 'client.json', + 'rabbitmq.json', + 'handlers.json', + 'redis.json', + 'api.json' + ] + conf = self.env_monitoring_config + is_container = bool(conf.get('ssh_user', '')) + server_host = conf['server_ip'] + sub_dir = 'server' + self.replacements.update(conf) + for file_name in sensu_server_files: + content = self.prepare_config_file(file_name, {'side': 'server'}) + self.write_config_file(file_name, sub_dir, server_host, content, + is_container=is_container, is_server=True) + # restart sensu server and Uchiwa services + # so it takes the new setup + self.restart_service(host=server_host, service='sensu-server', + is_server=True, + msg='restart sensu-server on {}' + .format(server_host)) + self.restart_service(host=server_host, service='uchiwa', + is_server=True, + msg='restart uchiwa on {}' + .format(server_host)) + self.configuration.update_env({'monitoring_setup_done': True}) + + # add setup for inventory object + def create_setup(self, o): + if self.provision == self.provision_levels['none']: + self.log.debug('Monitoring config setup skipped') + return + type_attribute = 'type' if 'type' in o else 'link_type' + type_value = o[type_attribute] + object_handler = self.object_handlers.get(type_value) + if object_handler: + object_handler.create_setup(o) + + def simulate_track_changes(self): + self.add_changes_for_all_clients() diff --git a/app/monitoring/setup/monitoring_simple_object.py b/app/monitoring/setup/monitoring_simple_object.py new file mode 100644 index 0000000..a66abe0 --- /dev/null +++ b/app/monitoring/setup/monitoring_simple_object.py @@ -0,0 +1,25 @@ +############################################################################### +# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) # +# 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 monitoring.setup.monitoring_check_handler import MonitoringCheckHandler + + +class MonitoringSimpleObject(MonitoringCheckHandler): + + def __init__(self, env): + super().__init__(env) + + # add monitoring setup for remote host + def setup(self, type: str, o: dict, values: dict = None): + if not values: + values = {} + values['objtype'] = type + objid = values.get('objid', o['id']) + values['objid'] = self.encode_special_characters(objid) + self.create_monitoring_for_object(o, values) diff --git a/app/monitoring/setup/monitoring_vedge.py b/app/monitoring/setup/monitoring_vedge.py new file mode 100644 index 0000000..144ee3a --- /dev/null +++ b/app/monitoring/setup/monitoring_vedge.py @@ -0,0 +1,19 @@ +############################################################################### +# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) # +# 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 monitoring.setup.monitoring_simple_object import MonitoringSimpleObject + + +class MonitoringVedge(MonitoringSimpleObject): + + def __init__(self, env): + super().__init__(env) + + def create_setup(self, o): + self.setup('vedge', o) diff --git a/app/monitoring/setup/monitoring_vnic.py b/app/monitoring/setup/monitoring_vnic.py new file mode 100644 index 0000000..7c229f8 --- /dev/null +++ b/app/monitoring/setup/monitoring_vnic.py @@ -0,0 +1,20 @@ +############################################################################### +# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) # +# 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 monitoring.setup.monitoring_simple_object import MonitoringSimpleObject + + +class MonitoringVnic(MonitoringSimpleObject): + + def __init__(self, env): + super().__init__(env) + + # add monitoring setup for remote host + def create_setup(self, o): + self.setup('vnic', o, values={'vnictype': o['vnic_type']}) diff --git a/app/monitoring/setup/monitoring_vservice.py b/app/monitoring/setup/monitoring_vservice.py new file mode 100644 index 0000000..8313b9b --- /dev/null +++ b/app/monitoring/setup/monitoring_vservice.py @@ -0,0 +1,23 @@ +############################################################################### +# Copyright (c) 2017 Koren Lev (Cisco Systems), Yaron Yogev (Cisco Systems) # +# 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 monitoring.setup.monitoring_simple_object import MonitoringSimpleObject + + +class MonitoringVservice(MonitoringSimpleObject): + + def __init__(self, env): + super().__init__(env) + + def create_setup(self, o): + values = { + 'local_service_id': o['local_service_id'], + 'service_type': o['service_type'] + } + self.setup('vservice', o, values=values) -- cgit 1.2.3-korg