X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=yardstick%2Fcommon%2Fansible_common.py;h=dee7044a5e9a9043eb768a1cfd23c7496fbb471b;hb=8cfab92068853fa79a46c12b44624c6d788e1da8;hp=be262c215829e1a66d708c9d840be92c20055bf4;hpb=639981d1a2c30a3501749dfe4a7a50609e05cb0b;p=yardstick.git diff --git a/yardstick/common/ansible_common.py b/yardstick/common/ansible_common.py index be262c215..dee7044a5 100644 --- a/yardstick/common/ansible_common.py +++ b/yardstick/common/ansible_common.py @@ -12,8 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -from __future__ import absolute_import - import cgitb import collections import contextlib as cl @@ -23,14 +21,15 @@ import os from collections import Mapping, MutableMapping, Iterable, Callable, deque from functools import partial from itertools import chain -from subprocess import CalledProcessError, Popen, PIPE -from tempfile import NamedTemporaryFile +import subprocess +import tempfile import six -import six.moves.configparser as ConfigParser +from six.moves import configparser import yaml from six import StringIO from chainmap import ChainMap +from oslo_serialization import jsonutils from yardstick.common.utils import Timer from yardstick.common import constants as consts @@ -133,10 +132,9 @@ class CustomTemporaryFile(object): else: self.data_types = self.DEFAULT_DATA_TYPES # must open "w+" so unicode is encoded correctly - self.creator = partial(NamedTemporaryFile, mode="w+", delete=False, - dir=directory, - prefix=prefix, - suffix=self.suffix) + self.creator = partial( + tempfile.NamedTemporaryFile, mode="w+", delete=False, + dir=directory, prefix=prefix, suffix=self.suffix) def make_context(self, data, write_func, descriptor='data'): return TempfileContext(data, write_func, descriptor, self.data_types, @@ -190,8 +188,8 @@ class FileNameGenerator(object): if not prefix.endswith('_'): prefix += '_' - temp_file = NamedTemporaryFile(delete=False, dir=directory, - prefix=prefix, suffix=suffix) + temp_file = tempfile.NamedTemporaryFile(delete=False, dir=directory, + prefix=prefix, suffix=suffix) with cl.closing(temp_file): return temp_file.name @@ -473,7 +471,7 @@ class AnsibleCommon(object): prefix = '_'.join([self.prefix, prefix, 'inventory']) ini_temp_file = IniMapTemporaryFile(directory=directory, prefix=prefix) - inventory_config = ConfigParser.ConfigParser(allow_no_value=True) + inventory_config = configparser.ConfigParser(allow_no_value=True) # disable default lowercasing inventory_config.optionxform = str return ini_temp_file.make_context(self.inventory_dict, write_func, @@ -508,6 +506,58 @@ class AnsibleCommon(object): timeout = 1200.0 return timeout + def _generate_ansible_cfg(self, directory): + parser = configparser.ConfigParser() + parser.add_section('defaults') + parser.set('defaults', 'host_key_checking', 'False') + + cfg_path = os.path.join(directory, 'ansible.cfg') + with open(cfg_path, 'w') as f: + parser.write(f) + + def get_sut_info(self, directory, sut_dir='sut'): + if not os.path.isdir(directory): + raise OSError('No such directory: %s' % directory) + + self._generate_ansible_cfg(directory) + + prefix = 'tmp' + self.gen_inventory_ini_dict() + ini_file = self._gen_ansible_inventory_file(directory, prefix=prefix) + with ini_file as f: + inventory_path = str(f) + + self._exec_get_sut_info_cmd(directory, inventory_path, sut_dir) + + sut_dir = os.path.join(directory, sut_dir) + sut_info = self._gen_sut_info_dict(sut_dir) + + return sut_info + + def _exec_get_sut_info_cmd(self, directory, inventory_path, sut_dir): + cmd = ['ansible', 'all', '-m', 'setup', '-i', + inventory_path, '--tree', sut_dir] + + proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, cwd=directory) + output, _ = proc.communicate() + retcode = proc.wait() + LOG.debug("exit status = %s", retcode) + if retcode != 0: + raise subprocess.CalledProcessError(retcode, cmd, output) + + def _gen_sut_info_dict(self, sut_dir): + sut_info = {} + + if os.path.isdir(sut_dir): + root, _, files = next(os.walk(sut_dir)) + for filename in files: + abs_path = os.path.join(root, filename) + with open(abs_path) as f: + data = jsonutils.load(f) + sut_info[filename] = data + + return sut_info + def execute_ansible(self, playbooks, directory, timeout=None, extra_vars=None, ansible_check=False, prefix='tmp', verbose=False): @@ -564,12 +614,13 @@ class AnsibleCommon(object): # 'timeout': timeout / 2, }) with Timer() as timer: - proc = Popen(cmd, stdout=PIPE, **exec_args) + proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, + **exec_args) output, _ = proc.communicate() retcode = proc.wait() LOG.debug("exit status = %s", retcode) if retcode != 0: - raise CalledProcessError(retcode, cmd, output) + raise subprocess.CalledProcessError(retcode, cmd, output) timeout -= timer.total_seconds() cmd.remove("--syntax-check") @@ -579,10 +630,10 @@ class AnsibleCommon(object): # TODO: add timeout support of use subprocess32 backport # 'timeout': timeout, }) - proc = Popen(cmd, stdout=PIPE, **exec_args) + proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, **exec_args) output, _ = proc.communicate() retcode = proc.wait() LOG.debug("exit status = %s", retcode) if retcode != 0: - raise CalledProcessError(retcode, cmd, output) + raise subprocess.CalledProcessError(retcode, cmd, output) return output