Matthew Treinish | f610aca | 2015-06-30 15:32:34 -0400 | [diff] [blame] | 1 | # Copyright 2015 Hewlett-Packard Development Company, L.P. |
| 2 | # |
| 3 | # Licensed under the Apache License, Version 2.0 (the "License"); you may |
| 4 | # not use this file except in compliance with the License. You may obtain |
| 5 | # a copy of the License at |
| 6 | # |
| 7 | # http://www.apache.org/licenses/LICENSE-2.0 |
| 8 | # |
| 9 | # Unless required by applicable law or agreed to in writing, software |
| 10 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| 11 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| 12 | # License for the specific language governing permissions and limitations |
| 13 | # under the License. |
| 14 | |
| 15 | import os |
| 16 | import shutil |
| 17 | import subprocess |
Andrea Frittoli (andreaf) | 5a69e55 | 2015-07-31 18:40:17 +0100 | [diff] [blame] | 18 | import sys |
Matthew Treinish | f610aca | 2015-06-30 15:32:34 -0400 | [diff] [blame] | 19 | |
| 20 | from cliff import command |
| 21 | from oslo_log import log as logging |
| 22 | from six import moves |
| 23 | |
| 24 | LOG = logging.getLogger(__name__) |
| 25 | |
| 26 | TESTR_CONF = """[DEFAULT] |
| 27 | test_command=OS_STDOUT_CAPTURE=${OS_STDOUT_CAPTURE:-1} \\ |
| 28 | OS_STDERR_CAPTURE=${OS_STDERR_CAPTURE:-1} \\ |
| 29 | OS_TEST_TIMEOUT=${OS_TEST_TIMEOUT:-500} \\ |
| 30 | ${PYTHON:-python} -m subunit.run discover -t %s %s $LISTOPT $IDOPTION |
| 31 | test_id_option=--load-list $IDFILE |
| 32 | test_list_option=--list |
| 33 | group_regex=([^\.]*\.)* |
| 34 | """ |
| 35 | |
| 36 | |
Andrea Frittoli (andreaf) | 5a69e55 | 2015-07-31 18:40:17 +0100 | [diff] [blame] | 37 | def get_tempest_default_config_dir(): |
Ken'ichi Ohmichi | 2e2ee19 | 2015-11-19 09:48:27 +0000 | [diff] [blame] | 38 | """Get default config directory of tempest |
| 39 | |
| 40 | Returns the correct default config dir to support both cases of |
Andrea Frittoli (andreaf) | 5a69e55 | 2015-07-31 18:40:17 +0100 | [diff] [blame] | 41 | tempest being or not installed in a virtualenv. |
| 42 | Cases considered: |
| 43 | - no virtual env, python2: real_prefix and base_prefix not set |
| 44 | - no virtual env, python3: real_prefix not set, base_prefix set and |
| 45 | identical to prefix |
| 46 | - virtualenv, python2: real_prefix and prefix are set and different |
| 47 | - virtualenv, python3: real_prefix not set, base_prefix and prefix are |
| 48 | set and identical |
| 49 | - pyvenv, any python version: real_prefix not set, base_prefix and prefix |
| 50 | are set and different |
| 51 | |
| 52 | :return: default config dir |
| 53 | """ |
| 54 | real_prefix = getattr(sys, 'real_prefix', None) |
| 55 | base_prefix = getattr(sys, 'base_prefix', None) |
| 56 | prefix = sys.prefix |
Ken'ichi Ohmichi | 0ce1652 | 2016-04-23 12:52:05 -0700 | [diff] [blame] | 57 | global_conf_dir = '/etc/tempest' |
David Paterson | 0bf52d4 | 2015-04-13 21:55:58 -0400 | [diff] [blame] | 58 | if (real_prefix is None and |
Ken'ichi Ohmichi | 0ce1652 | 2016-04-23 12:52:05 -0700 | [diff] [blame] | 59 | (base_prefix is None or base_prefix == prefix) and |
| 60 | os.path.isdir(global_conf_dir)): |
David Paterson | 0bf52d4 | 2015-04-13 21:55:58 -0400 | [diff] [blame] | 61 | # Probably not running in a virtual environment. |
Andrea Frittoli (andreaf) | 5a69e55 | 2015-07-31 18:40:17 +0100 | [diff] [blame] | 62 | # NOTE(andreaf) we cannot distinguish this case from the case of |
| 63 | # a virtual environment created with virtualenv, and running python3. |
David Paterson | 0bf52d4 | 2015-04-13 21:55:58 -0400 | [diff] [blame] | 64 | # Also if it appears we are not in virtual env and fail to find |
| 65 | # global config: '/etc/tempest', fall back to |
| 66 | # '[sys.prefix]/etc/tempest' |
Ken'ichi Ohmichi | 0ce1652 | 2016-04-23 12:52:05 -0700 | [diff] [blame] | 67 | return global_conf_dir |
Andrea Frittoli (andreaf) | 5a69e55 | 2015-07-31 18:40:17 +0100 | [diff] [blame] | 68 | else: |
Ken'ichi Ohmichi | 7e054d4 | 2016-04-23 13:00:08 -0700 | [diff] [blame^] | 69 | conf_dir = os.path.join(prefix, 'etc/tempest') |
| 70 | if os.path.isdir(conf_dir): |
| 71 | return conf_dir |
| 72 | else: |
| 73 | # NOTE: The prefix is gotten from the path which pyconfig.h is |
| 74 | # installed under. Some envs contain it under /usr/include, not |
| 75 | # /user/local/include. Then prefix becomes /usr on such envs. |
| 76 | # However, etc/tempest is installed under /usr/local and the bove |
| 77 | # path logic mismatches. This is a workaround for such envs. |
| 78 | return os.path.join(prefix, 'local/etc/tempest') |
Andrea Frittoli (andreaf) | 5a69e55 | 2015-07-31 18:40:17 +0100 | [diff] [blame] | 79 | |
| 80 | |
Matthew Treinish | f610aca | 2015-06-30 15:32:34 -0400 | [diff] [blame] | 81 | class TempestInit(command.Command): |
| 82 | """Setup a local working environment for running tempest""" |
| 83 | |
| 84 | def get_parser(self, prog_name): |
| 85 | parser = super(TempestInit, self).get_parser(prog_name) |
| 86 | parser.add_argument('dir', nargs='?', default=os.getcwd()) |
Andrea Frittoli (andreaf) | 5a69e55 | 2015-07-31 18:40:17 +0100 | [diff] [blame] | 87 | parser.add_argument('--config-dir', '-c', default=None) |
Matthew Treinish | f610aca | 2015-06-30 15:32:34 -0400 | [diff] [blame] | 88 | return parser |
| 89 | |
| 90 | def generate_testr_conf(self, local_path): |
| 91 | testr_conf_path = os.path.join(local_path, '.testr.conf') |
| 92 | top_level_path = os.path.dirname(os.path.dirname(__file__)) |
| 93 | discover_path = os.path.join(top_level_path, 'test_discover') |
| 94 | testr_conf = TESTR_CONF % (top_level_path, discover_path) |
| 95 | with open(testr_conf_path, 'w+') as testr_conf_file: |
| 96 | testr_conf_file.write(testr_conf) |
| 97 | |
| 98 | def update_local_conf(self, conf_path, lock_dir, log_dir): |
| 99 | config_parse = moves.configparser.SafeConfigParser() |
| 100 | config_parse.optionxform = str |
| 101 | with open(conf_path, 'w+') as conf_file: |
| 102 | config_parse.readfp(conf_file) |
| 103 | # Set local lock_dir in tempest conf |
| 104 | if not config_parse.has_section('oslo_concurrency'): |
| 105 | config_parse.add_section('oslo_concurrency') |
| 106 | config_parse.set('oslo_concurrency', 'lock_path', lock_dir) |
| 107 | # Set local log_dir in tempest conf |
| 108 | config_parse.set('DEFAULT', 'log_dir', log_dir) |
| 109 | # Set default log filename to tempest.log |
| 110 | config_parse.set('DEFAULT', 'log_file', 'tempest.log') |
| 111 | |
| 112 | def copy_config(self, etc_dir, config_dir): |
| 113 | shutil.copytree(config_dir, etc_dir) |
| 114 | |
David Paterson | 0bf52d4 | 2015-04-13 21:55:58 -0400 | [diff] [blame] | 115 | def generate_sample_config(self, local_dir, config_dir): |
| 116 | conf_generator = os.path.join(config_dir, |
| 117 | 'config-generator.tempest.conf') |
| 118 | |
Matthew Treinish | c8a39b4 | 2015-07-27 17:07:37 -0400 | [diff] [blame] | 119 | subprocess.call(['oslo-config-generator', '--config-file', |
David Paterson | 0bf52d4 | 2015-04-13 21:55:58 -0400 | [diff] [blame] | 120 | conf_generator], |
Matthew Treinish | c8a39b4 | 2015-07-27 17:07:37 -0400 | [diff] [blame] | 121 | cwd=local_dir) |
| 122 | |
Matthew Treinish | f610aca | 2015-06-30 15:32:34 -0400 | [diff] [blame] | 123 | def create_working_dir(self, local_dir, config_dir): |
| 124 | # Create local dir if missing |
| 125 | if not os.path.isdir(local_dir): |
| 126 | LOG.debug('Creating local working dir: %s' % local_dir) |
| 127 | os.mkdir(local_dir) |
Marc Koderer | 090b5dc | 2015-11-04 10:35:48 +0100 | [diff] [blame] | 128 | elif not os.listdir(local_dir) == []: |
David Paterson | 0bf52d4 | 2015-04-13 21:55:58 -0400 | [diff] [blame] | 129 | raise OSError("Directory you are trying to initialize already " |
Marc Koderer | 090b5dc | 2015-11-04 10:35:48 +0100 | [diff] [blame] | 130 | "exists and is not empty: %s" % local_dir) |
David Paterson | 0bf52d4 | 2015-04-13 21:55:58 -0400 | [diff] [blame] | 131 | |
Matthew Treinish | f610aca | 2015-06-30 15:32:34 -0400 | [diff] [blame] | 132 | lock_dir = os.path.join(local_dir, 'tempest_lock') |
| 133 | etc_dir = os.path.join(local_dir, 'etc') |
| 134 | config_path = os.path.join(etc_dir, 'tempest.conf') |
| 135 | log_dir = os.path.join(local_dir, 'logs') |
| 136 | testr_dir = os.path.join(local_dir, '.testrepository') |
| 137 | # Create lock dir |
| 138 | if not os.path.isdir(lock_dir): |
| 139 | LOG.debug('Creating lock dir: %s' % lock_dir) |
| 140 | os.mkdir(lock_dir) |
| 141 | # Create log dir |
| 142 | if not os.path.isdir(log_dir): |
| 143 | LOG.debug('Creating log dir: %s' % log_dir) |
| 144 | os.mkdir(log_dir) |
| 145 | # Create and copy local etc dir |
| 146 | self.copy_config(etc_dir, config_dir) |
Matthew Treinish | c8a39b4 | 2015-07-27 17:07:37 -0400 | [diff] [blame] | 147 | # Generate the sample config file |
David Paterson | 0bf52d4 | 2015-04-13 21:55:58 -0400 | [diff] [blame] | 148 | self.generate_sample_config(local_dir, config_dir) |
Matthew Treinish | f610aca | 2015-06-30 15:32:34 -0400 | [diff] [blame] | 149 | # Update local confs to reflect local paths |
| 150 | self.update_local_conf(config_path, lock_dir, log_dir) |
| 151 | # Generate a testr conf file |
| 152 | self.generate_testr_conf(local_dir) |
| 153 | # setup local testr working dir |
| 154 | if not os.path.isdir(testr_dir): |
| 155 | subprocess.call(['testr', 'init'], cwd=local_dir) |
| 156 | |
| 157 | def take_action(self, parsed_args): |
Andrea Frittoli (andreaf) | 5a69e55 | 2015-07-31 18:40:17 +0100 | [diff] [blame] | 158 | config_dir = parsed_args.config_dir or get_tempest_default_config_dir() |
| 159 | self.create_working_dir(parsed_args.dir, config_dir) |