cloudpulse/cloudpulse/operator/ansible/ansible_runner.py

314 lines
11 KiB
Python

# 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
import ansible.constants as CONST
import ansible.inventory
import ansible.runner
import cloudpulse
from cloudpulse.scenario.plugins.security_pulse.util.\
security_pulse_test_input import security_test_input_reader
import json
import os
def get_temp_path():
base_dir = os.path.dirname(cloudpulse.__file__)
try:
config_file = base_dir + '/scenario/plugins/security_pulse/config/' +\
'securityhealth_test_input.yaml'
input_reader = security_test_input_reader(config_file)
input_data = input_reader.process_security_input_file()
return input_data['global_data']['file_info_dir']
except Exception:
print ("Exception while getting temp path..")
return "/var/sec_hc/"
CONST.HOST_KEY_CHECKING = False
TMP_LOCATION = get_temp_path()
is_containerized = False
class ansible_runner(object):
def __init__(self, os_node_list=[]):
self.openstack_node = os_node_list
self.remote_user = None
self.inventory = None
def execute_cmd(self, command, file_list=[], ips=[], roles=[],
container_name=None):
inventory = None
filetered_os_list = []
if ips:
filetered_os_list = self.get_os_node_list(ip_list=ips)
elif roles:
filetered_os_list = self.get_os_node_list(role_list=roles)
else:
filetered_os_list = self.openstack_node
# print filetered_os_list
if filetered_os_list:
inventory = self.init_ansible_inventory(filetered_os_list)
if inventory:
self.inventory = inventory
if is_containerized:
self.execute("mkdir " + TMP_LOCATION,
container_name=container_name)
for f in file_list:
self.copy(f, TMP_LOCATION, container_name=container_name)
out = self.execute(command, container_name=container_name)
print (out)
# remove the files from containers
self.execute("rm -rf " + TMP_LOCATION,
container_name=container_name)
if is_containerized:
# remove the files from host
self.execute("rm -rf " + TMP_LOCATION)
return out
def set_ansible_inventory(self, inv):
self.inventory = inv
def set_credential(self, user):
self.remote_user = user
def init_ansible_inventory(self, os_node_list):
ip_list = []
for os_node in os_node_list:
ip_list.append(os_node.getIp())
self.remote_user = os_node.getUser()
inventory = ansible.inventory.Inventory(ip_list)
return inventory
def get_os_node_list(self, ip_list=[], role_list=[]):
filetered_list = []
if not ip_list and not role_list:
return self.openstack_node
if ip_list and self.openstack_node:
for ip in ip_list:
for os_node in self.openstack_node:
if ip == os_node.getIp():
filetered_list.append(os_node)
elif role_list and self.openstack_node:
for role in role_list:
for os_node in self.openstack_node:
if role == os_node.getRole():
filetered_list.append(os_node)
return filetered_list
def copy(self, src, dest, container_name=None):
runner = ansible.runner.Runner(
module_name='copy',
module_args='src=%s dest=%s' % (src, dest),
remote_user=self.remote_user,
inventory=self.inventory,
forks=1,
)
out = runner.run()
print (out)
# copy to container
if is_containerized:
con_runner = self.container_copy(src, dest, container_name)
out1 = con_runner.run()
print (out1)
return out
def container_copy(self, src, dest, container_name):
new_src = TMP_LOCATION + src.split('/')[-1]
dest = dest + src.split('/')[-1]
cmd = "docker exec -i %s sh -c 'cat > %s' < %s" \
% (container_name, dest, new_src)
runner = ansible.runner.Runner(
module_name='shell',
module_args=cmd,
remote_user=self.remote_user,
# remote_pass=self.remote_pass,
inventory=self.inventory,
forks=1,
)
print (cmd)
return runner
def fetch(self, src, dest, flat='yes'):
runner = ansible.runner.Runner(
module_name='fetch',
module_args='src=%s dest=%s flat=%s' % (src, dest, flat),
remote_user=self.remote_user,
inventory=self.inventory,
forks=1,
)
out = runner.run()
return out
# can perform all shell operations Ex: rm /tmp/output
def execute(self, command, container_name=None, roles=[]):
filetered_os_list = []
if roles:
filetered_os_list = self.get_os_node_list(role_list=roles)
self.inventory = self.init_ansible_inventory(filetered_os_list)
if is_containerized and container_name:
command = 'docker exec %s %s' % (container_name, command)
# print command
runner = ansible.runner.Runner(
module_name='shell',
module_args=command,
remote_user=self.remote_user,
inventory=self.inventory,
forks=1,
)
out = runner.run()
return out
def ping(self, container_name=None, roles=[]):
filetered_os_list = []
if roles:
filetered_os_list = self.get_os_node_list(role_list=roles)
self.inventory = self.init_ansible_inventory(filetered_os_list)
runner = ansible.runner.Runner(
module_name='ping',
remote_user=self.remote_user,
inventory=self.inventory,
timeout=30,
forks=1,
)
out = runner.run()
return out
def get_results(self):
result = {}
if not os.path.isdir(TMP_LOCATION + 'output/'):
return result
files = os.walk(TMP_LOCATION + 'output/').next()[1]
for f in files:
try:
result[f] = open(TMP_LOCATION + 'output/' +
f + TMP_LOCATION + 'output', 'r').read()
except IOError:
print ("Error opening the file : " + TMP_LOCATION +
'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'] = " ".join(
[("%s -> %s") % (key, results['dark'][key])
for key in results['dark']])
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)
def get_parsed_ansible_output(self, output_data):
if output_data:
return self.get_validated_data(output_data)
else:
msg = {
'message': 'No result from test execution',
'status': 'Fail'}
return (404, json.dumps([msg], []))
def get_validated_data(self, results):
print ("Inside get_validated_data", results)
# final_result = {}
output = []
status = 200 # 'PASS'
###################################################
# First validation is to make sure connectivity to
# all the hosts was ok.
###################################################
if results['dark']:
status = 404 # 'FAIL'
##################################################
# Now look for status 'failed'
##################################################
for node in results['contacted'].keys():
if 'failed' in results['contacted'][node]:
if results['contacted'][node]['failed'] is True:
status = 404 # 'FAIL'
msg = {
'node': node,
'status': 'Fail',
'message': 'Execution failed'}
output.append(msg)
#################################################
# Check for the return code 'rc' for each host.
#################################################
for node in results['contacted'].keys():
rc = results['contacted'][node].get('rc', None)
if rc is not None and rc != 0:
status = 404 # 'FAIL'
node_info = results['contacted'][node]
op = eval(node_info.get('stdout'))
if not op.get('OverallStatus'):
status = 404 # 'FAIL'
try:
res = op.get('result', [])
for tc in res:
tc.update({'node': node})
output.append(tc)
except Exception:
print ("Exception while getting the result" +
" from the ansible output")
return (status, json.dumps(output), [])
"""
if __name__ == '__main__':
os_node_info_obj = openstack_node_info_reader("/home/ubuntu/
sasi/cpulse/cloudpulse/plugins/security_pulse/config/
openstack_config.yaml")
openstack_node_list = os_node_info_obj.get_host_list()
print openstack_node_list
flist=["/home/ubuntu/sasi/cpulse/cloudpulse/plugins/
security_pulse/testcase/TLS_Enablement_Check.py"]
ans_runner = ansible_runner(openstack_node_list)
ans_runner.execute_cmd("python "+TMP_LOCATION+
"TLS_Enablement_Check.py",file_list=flist)
"""