diff --git a/cloudpulse/TestManager/TestManager.py b/cloudpulse/TestManager/TestManager.py index 5b6c7c8..b8ae2d1 100644 --- a/cloudpulse/TestManager/TestManager.py +++ b/cloudpulse/TestManager/TestManager.py @@ -111,7 +111,7 @@ class TestManager(object): result = func() if result[0] == 200: Test['state'] = 'success' - Test['result'] = 'success' + Test['result'] = textwrap.fill(str(result[1]), 40) else: Test['state'] = 'failed' Test['result'] = textwrap.fill(str(result[1]), 40) @@ -124,7 +124,7 @@ class TestManager(object): func = self.command_ref[Test['name']] result = func() if result[0] == 200: - Test['result'] = 'success' + Test['result'] = textwrap.fill(str(result[1]), 40) else: Test['state'] = 'failed' Test['result'] = textwrap.fill(str(result[1]), 40) diff --git a/cloudpulse/operator/ansible/ansible_runner.py b/cloudpulse/operator/ansible/ansible_runner.py index f2ccc1e..06e2f44 100644 --- a/cloudpulse/operator/ansible/ansible_runner.py +++ b/cloudpulse/operator/ansible/ansible_runner.py @@ -22,12 +22,12 @@ TMP_LOCATION = "/tmp/sec_hc/" class ansible_runner(object): + def __init__(self, os_node_list=[]): self.openstack_node = os_node_list # print self.openstack_node self.remote_user = None - self.remote_pass = None self.inventory = None def execute_cmd(self, command, file_list=[], ips=[], roles=[]): @@ -57,16 +57,14 @@ class ansible_runner(object): def set_ansible_inventory(self, inv): self.inventory = inv - def set_credential(self, user, passwd): + def set_credential(self, user): self.remote_user = user - self.remote_pass = passwd def init_ansible_inventory(self, os_node_list): ip_list = [] for os_node in self.openstack_node: ip_list.append(os_node.getIp()) self.remote_user = os_node.getUser() - self.remote_pass = os_node.getPassword() # print ip_list inventory = ansible.inventory.Inventory(ip_list) return inventory @@ -92,7 +90,6 @@ class ansible_runner(object): module_name='copy', module_args='src=%s dest=%s' % (src, dest), remote_user=self.remote_user, - remote_pass=self.remote_pass, inventory=self.inventory, ) out = runner.run() @@ -103,7 +100,6 @@ class ansible_runner(object): module_name='fetch', module_args='src=%s dest=%s flat=%s' % (src, dest, flat), remote_user=self.remote_user, - remote_pass=self.remote_pass, inventory=self.inventory, ) out = runner.run() @@ -116,7 +112,6 @@ class ansible_runner(object): module_name='shell', module_args=command, remote_user=self.remote_user, - remote_pass=self.remote_pass, inventory=self.inventory, ) out = runner.run() @@ -136,6 +131,45 @@ class ansible_runner(object): 'output/' + f + TMP_LOCATION + 'output') return result + def validate_results(self, results, checks=None): + results['status'] = 'PASS' + failed_hosts = [] + + if results['dark']: + failed_hosts.append(results['dark'].keys()) + results['status'] = 'FAIL' + results['status_message'] = '' + + for node in results['contacted'].keys(): + if 'failed' in results['contacted'][node]: + if results['contacted'][node]['failed'] is True: + results['status'] = 'FAIL' + results['status_message'] = '' + + for node in results['contacted'].keys(): + rc = results['contacted'][node].get('rc', None) + if rc is not None and rc != 0: + failed_hosts.append(node) + results['status'] = 'FAIL' + results['status_message'] = results[ + 'contacted'][node].get('stderr', None) + + if checks is None: + # print "No additional checks validated" + return results, failed_hosts + + for check in checks: + key = check.keys()[0] + value = check.values()[0] + for node in results['contacted'].keys(): + if key in results['contacted'][node].keys(): + if results['contacted'][node][key] != value: + failed_hosts.append(node) + results['status'] = 'FAIL' + results['status_message'] = '' + + return (results, failed_hosts) + """ if __name__ == '__main__': os_node_info_obj = openstack_node_info_reader("/home/ubuntu/ diff --git a/cloudpulse/operator/ansible/openstack_node_info_reader.py b/cloudpulse/operator/ansible/openstack_node_info_reader.py index 2bf5d2f..85bc09f 100644 --- a/cloudpulse/operator/ansible/openstack_node_info_reader.py +++ b/cloudpulse/operator/ansible/openstack_node_info_reader.py @@ -1,64 +1,74 @@ -# Copyright 2010-2011 OpenStack Foundation -# Copyright (c) 2013 Hewlett-Packard Development Company, L.P. -# -# 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. - -from __future__ import print_function -from openstack_node import openstack_node_obj -import yaml - - -class openstack_node_info_reader(object): - - def __init__(self, os_node_file): - self.hostYamlObj = None - try: - fp = open(os_node_file) - except IOError as e: - print ("Error while opening the file...%s", e) - return - try: - self.hostYamlObj = yaml.load(fp) - except yaml.error.YAMLError as perr: - print ("Error while parsing...%s", perr) - return - - def get_host_list(self): - openstack_host_list = [] - for key in self.hostYamlObj.keys(): - name = key - ip = self.hostYamlObj[key]["ip"] - hostname = key - username = self.hostYamlObj[key]["user"] - password = self.hostYamlObj[key]["password"] - role = self.hostYamlObj[key]["role"] - node_obj = openstack_node_obj(hostname, ip, username, - password, role, name) - openstack_host_list.append(node_obj) - return openstack_host_list - - """ - def get_host_list(self): - return self.openstack_host_list - """ - - def printHostList(self, openstack_host_list): - for hostObj in openstack_host_list: - print ("%s - %s - %s", hostObj.getIp(), - hostObj.getHost(), hostObj.getUser()) - -""" -if __name__ == '__main__': - os_node_info_obj = openstack_node_info_reader() - os_node_info_obj.get_host_list() -""" +# Copyright 2010-2011 OpenStack Foundation +# Copyright (c) 2013 Hewlett-Packard Development Company, L.P. +# +# 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. + +from __future__ import print_function +from openstack_node import openstack_node_obj +import yaml + + +class openstack_node_info_reader(object): + + def __init__(self, os_node_file): + self.hostYamlObj = None + try: + fp = open(os_node_file) + except IOError as e: + print ("Error while opening the file...%s", e) + return + try: + self.hostYamlObj = yaml.load(fp) + except yaml.error.YAMLError as perr: + print ("Error while parsing...%s", perr) + return + + def get_host_list(self): + openstack_host_list = [] + for key in self.hostYamlObj.keys(): + name = key + ip = self.hostYamlObj[key]["ip"] + hostname = key + username = self.hostYamlObj[key]["user"] + password = self.hostYamlObj[key]["password"] + role = self.hostYamlObj[key]["role"] + node_obj = openstack_node_obj(hostname, ip, username, + password, role, name) + openstack_host_list.append(node_obj) + return openstack_host_list + + """ + def get_host_list(self): + return self.openstack_host_list + """ + + def printHostList(self, openstack_host_list): + for hostObj in openstack_host_list: + print ("%s - %s - %s", hostObj.getIp(), + hostObj.getHost(), hostObj.getUser()) + + def get_galera_details(self): + galera = {} + print(self.hostYamlObj) + for key in self.hostYamlObj.keys(): + if 'galerauser' in self.hostYamlObj[key].keys(): + + galera['username'] = self.hostYamlObj[key]['galerauser'] + galera['password'] = self.hostYamlObj[key]['galerapassword'] + return galera + +""" +if __name__ == '__main__': + os_node_info_obj = openstack_node_info_reader() + os_node_info_obj.get_host_list() +""" diff --git a/cloudpulse/scenario/plugins/operator_tests/__init__.py b/cloudpulse/scenario/plugins/operator_tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/cloudpulse/scenario/plugins/operator_tests/operator.py b/cloudpulse/scenario/plugins/operator_tests/operator.py new file mode 100644 index 0000000..3976069 --- /dev/null +++ b/cloudpulse/scenario/plugins/operator_tests/operator.py @@ -0,0 +1,122 @@ +# 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. + +from __future__ import print_function +from cloudpulse.operator.ansible.ansible_runner import ansible_runner +from cloudpulse.operator.ansible.openstack_node_info_reader import \ + openstack_node_info_reader +from cloudpulse.scenario import base +from oslo_config import cfg +import re + +TESTS_OPTS = [ + cfg.StrOpt('operator_setup_file', + default='/etc/cloudpulse/openstack_config.yaml', + help='Setup File for the operator'), + cfg.BoolOpt('containerized', + default=True, + help='enable if the processes are running as containers'), + cfg.StrOpt('rabbit_container', + default='rabbitmq_v1', + help='name of the rabitmq container'), + cfg.StrOpt('galera_container', + default='mariadb_v1', + help='name of the galera cluster container'), + +] + +PERIODIC_TESTS_OPTS = [ + cfg.IntOpt('rabbitmq_check', + default=0, + help='The rabbitmq periodic check'), + cfg.IntOpt('galera_check', + default=0, + help='The galera periodic check') +] + +CONF = cfg.CONF + +operator_test_group = cfg.OptGroup(name='operator_test', + title='Options for the Operators') +CONF.register_group(operator_test_group) +CONF.register_opts(TESTS_OPTS, operator_test_group) + +periodic_test_group = cfg.OptGroup(name='periodic_tests', + title='Periodic tests to be run') +CONF.register_opts(PERIODIC_TESTS_OPTS, periodic_test_group) + + +class operator_scenario(base.Scenario): + + def load(self): + self.os_node_info_obj = openstack_node_info_reader( + cfg.CONF.operator_test.operator_setup_file) + openstack_node_list = self.os_node_info_obj.get_host_list() + self.ans_runner = ansible_runner(openstack_node_list) + inventory = self.ans_runner.init_ansible_inventory(openstack_node_list) + self.ans_runner.set_ansible_inventory(inventory) + + @base.scenario(admin_only=False, operator=True) + def rabbitmq_check(self): + self.load() + cmd = "rabbitmqctl cluster_status -q" + + is_containerized = cfg.CONF.operator_test.containerized + if is_containerized: + rabbit_container = cfg.CONF.operator_test.rabbit_container + cmd = ("docker exec %s %s" % (rabbit_container, cmd)) + + out = self.ans_runner.execute(cmd) + res, output = self.ans_runner.validate_results(out) + + node_status = res['contacted'][res['contacted'].keys()[0]]['stdout'] + node_status_string = node_status.replace('\n', '') + mathobj = re.search( + r'running_nodes,(.*?)}', node_status_string, re.M | re.I) + nodes = mathobj.group(1) + + if res['status'] is 'PASS': + return (200, "Active Nodes : %s" % nodes, + ['RabbitMQ-server Running']) + else: + return (404, ("RabbitMQ-server test failed :%s" % + res['status_message']), []) + + @base.scenario(admin_only=False, operator=True) + def galera_check(self): + self.load() + galera = self.os_node_info_obj.get_galera_details() + + cmd = (r"mysql -u %s -e 'SHOW STATUS;'|grep wsrep_incoming_addresses" % + (galera['username'])) + + is_containerized = cfg.CONF.operator_test.containerized + if is_containerized: + galera_container = cfg.CONF.operator_test.galera_container + cmd = ("docker exec %s %s" % (galera_container, cmd)) + + out = self.ans_runner.execute(cmd) + results, failed_hosts = self.ans_runner.validate_results(out) + + galera_status = results['contacted'][ + results['contacted'].keys()[0]]['stdout'] + galera_status_string = galera_status.replace('\n', '') + mathobj = re.search(r'wsrep_incoming_addresses\s+(.*?)$', + galera_status_string, re.M | re.I) + nodes = mathobj.group(1) + + if results['status'] is 'PASS': + return (200, "Active Nodes : %s" % nodes, + ['Galera Cluster Test Passed']) + else: + return (404, ("Galera Cluster Test Failed: %s" % + results['status_message']), [])