diff --git a/ansible/gather/dump_facts.j2 b/ansible/gather/dump_facts.j2 new file mode 100644 index 000000000..9b4819650 --- /dev/null +++ b/ansible/gather/dump_facts.j2 @@ -0,0 +1,12 @@ +{% for host in groups['controller'] %} +{{hostvars[host]| to_nice_json}} +{% endfor %} +{% for host in groups['compute'] %} +{{hostvars[host]| to_nice_json}} +{% endfor %} +{% for host in groups['undercloud'] %} +{{hostvars[host]| to_nice_json}} +{% endfor %} + + + diff --git a/ansible/gather/group_vars/all b/ansible/gather/group_vars/all new file mode 100644 index 000000000..ec4a0e633 --- /dev/null +++ b/ansible/gather/group_vars/all @@ -0,0 +1,12 @@ +--- +# Path of browbeat +browbeat_path: /home/stack/browbeat + +# Home directory on undercloud +home_dir: /home/stack + +# Login user for the remote hosts +host_remote_user: heat-admin + +# Login user for the local/jump machine +local_remote_user: stack diff --git a/ansible/gather/roles/compute/tasks/main.yml b/ansible/gather/roles/compute/tasks/main.yml new file mode 100644 index 000000000..b1315fdf5 --- /dev/null +++ b/ansible/gather/roles/compute/tasks/main.yml @@ -0,0 +1,13 @@ +--- +# +# Compute Tasks for gathering facts +# +- name: Get ovs version + shell: ovs-vswitchd --version | grep vSwitch | awk {'print$4'} + register: ovs_version + +- name: Set ovs version fact + set_fact: + openstack_ovs_version: "{{ ovs_version.stdout }}" + + diff --git a/ansible/gather/roles/keystone/tasks/main.yml b/ansible/gather/roles/keystone/tasks/main.yml new file mode 100644 index 000000000..e9dec64f2 --- /dev/null +++ b/ansible/gather/roles/keystone/tasks/main.yml @@ -0,0 +1,28 @@ +--- +# +# Tasks to set keystone facts +# + + - name: Get keystone provider + command: crudini --get /etc/keystone/keystone.conf token provider + register: keystone_provider + + - name: Set keystone provider fact + set_fact: + openstack_keystone_token_provider: "{{ keystone_provider.stdout }}" + + - name: Determine if Keystone is deployed in eventlet + shell: ps afx | grep "[Kk]eystone-all" -c + register: keystone_in_eventlet + changed_when: false + ignore_errors: True + + - name: Set keystone_deployment variable to httpd + set_fact: openstack_keystone_deployment='httpd' + when: keystone_in_eventlet.stdout|int == 0 + + - name: Set keystone_deployment variable to eventlet + set_fact: openstack_keystone_deployment='eventlet' + when: keystone_in_eventlet.stdout|int > 0 + + diff --git a/ansible/gather/roles/mysql/tasks/main.yml b/ansible/gather/roles/mysql/tasks/main.yml new file mode 100644 index 000000000..4d59dfa9d --- /dev/null +++ b/ansible/gather/roles/mysql/tasks/main.yml @@ -0,0 +1,21 @@ +# +# Get mysql facts +# + - name: Get max_connections on the database + shell: mysql -e "show variables like 'max_connections';" | grep max_connections | awk '{print $2}' + register: max_conn + ignore_errors: true + + - name: Set max database connections + set_fact: + openstack_mysql_max_connections: "{{ max_conn.stdout }}" + + - name : Get file descriptors for the mysql process + shell: cat /proc/$(pgrep mysqld_safe)/limits | grep "open files" | awk '{print $4}' + register: mysql_desc + + - name: Set file descriptors fact for mysql + set_fact: + openstack_mysql_file_descriptors: "{{ mysql_desc.stdout }}" + + diff --git a/ansible/gather/roles/neutron/tasks/main.yml b/ansible/gather/roles/neutron/tasks/main.yml new file mode 100644 index 000000000..73bdd9ab1 --- /dev/null +++ b/ansible/gather/roles/neutron/tasks/main.yml @@ -0,0 +1,101 @@ +--- +# +# Tasks to get neutron facts +# + - name: Get Neutron L3 conf + command: crudini --get /etc/neutron/neutron.conf DEFAULT router_distributed + register: dvr_stat + ignore_errors: true + + - name: Set L3 configuration fact + set_fact: + openstack_neutron_l3_dvr: "{{ dvr_stat.stdout }}" + when: dvr_stat.stdout != "" + + - name: Set L3 configauration fact + set_fact: + openstack_neutron_l3_dvr: false + when: dvr_stat.stdout == "" + + - name: Get Neutron Core Plugin + command: crudini --get /etc/neutron/neutron.conf DEFAULT core_plugin + register: core_plugin + ignore_errors: true + + - name: Set Core Plugin fact + set_fact: + openstack_neutron_core_plugin: "{{ core_plugin.stdout }}" + + - name: Get Neutron API Workers + command: crudini --get /etc/neutron/neutron.conf DEFAULT api_workers + register: neutron_api + ignore_errors: true + + - name: Set neutron API Workers fact + set_fact: + openstack_neutron_api_workers: "{{ facter_processorcount }}" + when: ( neutron_api.stdout == "" or neutron_api.stdout|int < 1) + + - name: Set neutron API Workers fact + set_fact: + openstack_neutron_api_workers: "{{ neutron_api.stdout }}" + when: (neutron_api.stdout != "" and neutron_api.stdout|int >= 1) + + - name: Get Neutron RPC Workers + command: crudini --get /etc/neutron/neutron.conf DEFAULT rpc_workers + register: neutron_rpc + ignore_errors: true + + - name: Set neutron RPC Workers fact + set_fact: + openstack_neutron_rpc_workers: 1 + when: (neutron_rpc.stdout == "" or neutron_rpc.stdout|int < 1) + + - name: Set neutron RPC Workers fact + set_fact: + openstack_neutron_rpc_workers: "{{ neutron_rpc.stdout }}" + when: (neutron_rpc.stdout != "" and neutron_rpc.stdout|int >= 1) + + - name: Get ml2 mechanism driver + command: crudini --get /etc/neutron/plugins/ml2/ml2_conf.ini ml2 mechanism_drivers + register: ml2 + when: openstack_neutron_core_plugin == "ml2" + ignore_errors: true + + - name: Set mechanism driver + set_fact: + openstack_neutron_ml2_driver: "{{ ml2.stdout }}" + + - name: Get firewall driver + command: crudini --get /etc/neutron/plugins/ml2/ml2_conf.ini securitygroup firewall_driver + register: firewall + ignore_errors: true + + - name: Set firewall driver fact + set_fact: + openstack_neutron_firewall_driver: "iptables_hybrid" + when: (firewall.stdout == "" and openstack_neutron_core_plugin == "ml2") + + - name: Set firewall driver fact + set_fact: + openstack_neutron_firewall_driver: "{{ firewall.stdout }}" + when: firewall.stdout != "" + + - name: Get ovs tunnel type + command: crudini --get /etc/neutron/plugins/ml2/openvswitch_agent.ini agent tunnel_types + register: tunnel_type + ignore_errors: true + + - name: Set ovs tunnel type fact + set_fact: + openstack_neutron_ovs_tunnel: "{{ tunnel_type.stdout }}" + when: "'openvswitch' in openstack_neutron_ml2_driver" + + - name: Get ovs version + shell: ovs-vswitchd --version | grep vSwitch | awk {'print$4'} + register: ovs_version + ignore_errors: true + + - name: Set ovs version fact + set_fact: + openstack_ovs_version: "{{ ovs_version.stdout }}" diff --git a/ansible/gather/roles/nova/tasks/main.yml b/ansible/gather/roles/nova/tasks/main.yml new file mode 100644 index 000000000..0eae13d2b --- /dev/null +++ b/ansible/gather/roles/nova/tasks/main.yml @@ -0,0 +1,50 @@ +--- +# +# Tasks to get nova facts +# + - name: Get Nova API Workers + command: crudini --get /etc/nova/nova.conf DEFAULT osapi_compute_workers + register: nova_api + ignore_errors: true + + - name: Set nova API Workers fact + set_fact: + openstack_nova_api_workers: "{{ facter_processorcount }}" + when: (nova_api.stdout =="" or nova_api.stdout|int < 1) + + - name: Set nova API Workers fact + set_fact: + openstack_nova_api_workers: "{{ nova_api.stdout }}" + when: (nova_api.stdout !="" and nova_api.stdout|int >= 1) + + - name: Get Nova conductor workers + command: crudini --get /etc/nova/nova.conf conductor workers + register: nova_conductor + ignore_errors: true + + - name: Set Nova conductor workers + set_fact: + openstack_nova_conductor_workers: "{{ facter_processorcount }}" + when: (nova_conductor.stdout == "" or nova_conductor.stdout|int < 1) + + - name: Set Nova conductor workers + set_fact: + openstack_nova_conductor_workers: "{{ nova_conductor.stdout }}" + when: (nova_conductor.stdout != "" and nova_conductor.stdout|int >= 1) + + - name: Get Nova metadata workers + command: crudini --get /etc/nova/nova.conf DEFAULT metadata_workers + register: nova_metadata + ignore_errors: true + + - name: Set Nova metadata workers + set_fact: + openstack_nova_metadata_workers: "{{ facter_processorcount }}" + when: (nova_metadata.stdout == "" or nova_metadata.stdout|int < 1) + + - name: Set Nova metadata workers + set_fact: + openstack_nova_metadata_workers: "{{ nova_metadata.stdout }}" + when: (nova_metadata.stdout != "" and nova_metadata.stdout|int >= 1) + + diff --git a/ansible/gather/roles/rabbitmq/tasks/main.yml b/ansible/gather/roles/rabbitmq/tasks/main.yml new file mode 100644 index 000000000..5d1e26141 --- /dev/null +++ b/ansible/gather/roles/rabbitmq/tasks/main.yml @@ -0,0 +1,14 @@ +--- +# +# Tasks to set rabbitmq facts for controllers +# + - name : Get rabbitmq file descriptors + shell: rabbitmqctl status | grep file_descriptors | awk -F',' '{print $3}' | sed 's/.$//' + register: rabbitmq_desc + ignore_errors: true + + - name: Set rabbitmq file descriptors + set_fact: + openstack_rabbitmq_file_descriptors: "{{ rabbitmq_desc.stdout }}" + + diff --git a/ansible/gather/roles/undercloud/tasks/main.yml b/ansible/gather/roles/undercloud/tasks/main.yml new file mode 100644 index 000000000..ae989c1e8 --- /dev/null +++ b/ansible/gather/roles/undercloud/tasks/main.yml @@ -0,0 +1,45 @@ +--- +# +# Tasks to set undercloud facts +# + - name: Get max_connections on the database + shell: mysql -e "show variables like 'max_connections';" | grep max_connections | awk '{print $2}' + register: max_conn + ignore_errors: true + + - name: Set max database connections + set_fact: + openstack_mysql_max_connections: "{{ max_conn.stdout }}" + + - name : Get file descriptors for the mysql process + shell: cat /proc/$(pgrep mysqld_safe)/limits | grep "open files" | awk '{print $4}' + register: mysql_desc + + - name: Set file descriptors fact for mysql + set_fact: + openstack_mysql_file_descriptors: "{{ mysql_desc.stdout }}" + + - name : Get rabbitmq file descriptors + shell: rabbitmqctl status | grep total_limit | awk -F',' '{print $2}' | sed 's/.$//' + register: rabbitmq_desc + ignore_errors: true + + - name: Set rabbitmq file descriptors + set_fact: + openstack_rabbitmq_file_descriptors: "{{ rabbitmq_desc.stdout }}" + + - name: Get Controller Nodes number + shell: source ~/stackrc; nova list | grep controller | grep ACTIVE | wc -l + register: controller_count + + - name : Set Controler number fact + set_fact: + osp_controllers_number: "{{ controller_count.stdout }}" + + - name: Get Compute Nodes number + shell: source ~/stackrc; nova list | grep compute | grep ACTIVE | wc -l + register: compute_count + + - name : Set Commpute number fact + set_fact: + osp_computes_number: "{{ compute_count.stdout }}" diff --git a/ansible/gather/site.yml b/ansible/gather/site.yml new file mode 100644 index 000000000..737cbd113 --- /dev/null +++ b/ansible/gather/site.yml @@ -0,0 +1,32 @@ +--- +- hosts: compute + remote_user: "{{ host_remote_user }}" + become: true + roles: + - compute + +- hosts: controller + remote_user: "{{ host_remote_user }}" + become: true + roles: + - nova + - neutron + - mysql + - rabbitmq + +- hosts: undercloud + remote_user: "{{ local_remote_user }}" + become: true + roles: + - undercloud + + +- hosts: localhost + become: true + tasks: + - name: Dump all vars + local_action: template src=dump_facts.j2 dest={{ browbeat_path }}/machine_facts.json + - name: Generate metadata jsons + shell : python {{ browbeat_path }}/lib/Metadata.py {{ browbeat_path }} + + diff --git a/lib/Metadata.py b/lib/Metadata.py new file mode 100644 index 000000000..9b99f5de6 --- /dev/null +++ b/lib/Metadata.py @@ -0,0 +1,97 @@ +import json +import re +import logging +import sys +import os + +class Metadata: + def __init__(self): + pass + + def load_file(self, filename): + json_str=None + try : + with open(filename) as data: + json_str = data.read() + except IOError: + print("Machine facts json is missing") + exit(1) + regex = re.compile(r"}\n{") + new_json = re.sub(r"}\n{",r"},\n{",json_str,re.M) + convert = "{ \"machines\": [" + new_json + "] }" + sys_data={} + sys_data['system_data']=json.loads(convert) + return sys_data + + + def get_hardware_metadata(self, sys_data): + hard_dict = {} + for item in sys_data['system_data']['machines']: + if not 'hardware_details' in hard_dict: + hard_dict['hardware_details']=[] + hardware_dict = {} + hardware_dict['label'] = item['inventory_hostname'] + hardware_dict['kernel'] = item['ansible_kernel'] + hardware_dict['total_mem'] = item['ansible_memory_mb']['real']['total'] + hardware_dict['total_logical_cores'] = item['facter_processorcount'] + hardware_dict['os_name'] = item['ansible_distribution']+item['ansible_distribution_version'] + hardware_dict['ip'] = item['ansible_default_ipv4']['address'] + hardware_dict['num_interface'] = len(item['ansible_interfaces']) + hardware_dict['machine_make'] = item['ansible_product_name'] + hard_dict['hardware_details'].append(hardware_dict) + return hard_dict + + + def get_environment_metadata(self, sys_data): + env_dict = {} + for item in sys_data['system_data']['machines']: + if not 'environment_setup' in env_dict: + env_dict['environment_setup']= {} + for key,value in item.items(): + if 'osp' in key: + env_dict['environment_setup'][key] = value + return env_dict + + def get_software_metadata(self, sys_data): + soft_all_dict = {} + for item in sys_data['system_data']['machines']: + if not 'software_details' in soft_all_dict: + soft_all_dict['software_details']={} + nodes = ['controller', 'undercloud', 'compute'] + if any(node in item['inventory_hostname'] for node in nodes): + if not 'openstack' in soft_all_dict['software_details']: + soft_all_dict['software_details']['openstack']={} + if not 'config' in soft_all_dict['software_details']['openstack']: + soft_all_dict['software_details']['openstack']['config']=[] + software_dict = {} + software_dict['node_name'] = item['inventory_hostname'] + for soft in item: + if 'openstack' in soft: + service = soft.split('_') + service_name = service[1] + if not service_name in software_dict: + software_dict[service_name]={} + if service_name in soft: + software_dict[service_name][soft]= item[soft] + soft_all_dict['software_details']['openstack']['config'].append(software_dict) + return soft_all_dict + + + def write_metadata_file(self, data, filename): + with open(filename, 'w') as json_file: + json.dump(data, json_file) + + +def main(): + _filename = os.path.join(sys.argv[1], 'machine_facts.json') + metadata = Metadata() + sysdata = metadata.load_file(_filename) + env_data = metadata.get_environment_metadata(sysdata) + metadata.write_metadata_file(env_data, os.path.join(sys.argv[1], 'environment-metadata.json')) + hardware_data = metadata.get_hardware_metadata(sysdata) + metadata.write_metadata_file(hardware_data, os.path.join(sys.argv[1], 'hardware-metadata.json')) + software_data = metadata.get_software_metadata(sysdata) + metadata.write_metadata_file(software_data, os.path.join(sys.argv[1], 'software-metadata.json')) + +if __name__ == '__main__': + sys.exit(main())