blob: 77d62d34da02bd97c41c618e5b6e010a737b3c34 [file] [log] [blame]
Matthew Treinishf610aca2015-06-30 15:32:34 -04001# 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
15import os
16import shutil
17import subprocess
Andrea Frittoli (andreaf)5a69e552015-07-31 18:40:17 +010018import sys
Matthew Treinishf610aca2015-06-30 15:32:34 -040019
20from cliff import command
21from oslo_log import log as logging
22from six import moves
23
step682980c14ec2016-02-23 14:53:52 -050024from tempest.cmd.workspace import WorkspaceManager
25
Matthew Treinishf610aca2015-06-30 15:32:34 -040026LOG = logging.getLogger(__name__)
27
28TESTR_CONF = """[DEFAULT]
29test_command=OS_STDOUT_CAPTURE=${OS_STDOUT_CAPTURE:-1} \\
30 OS_STDERR_CAPTURE=${OS_STDERR_CAPTURE:-1} \\
31 OS_TEST_TIMEOUT=${OS_TEST_TIMEOUT:-500} \\
32 ${PYTHON:-python} -m subunit.run discover -t %s %s $LISTOPT $IDOPTION
33test_id_option=--load-list $IDFILE
34test_list_option=--list
35group_regex=([^\.]*\.)*
36"""
37
38
Andrea Frittoli (andreaf)5a69e552015-07-31 18:40:17 +010039def get_tempest_default_config_dir():
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +000040 """Get default config directory of tempest
41
42 Returns the correct default config dir to support both cases of
Andrea Frittoli (andreaf)5a69e552015-07-31 18:40:17 +010043 tempest being or not installed in a virtualenv.
44 Cases considered:
45 - no virtual env, python2: real_prefix and base_prefix not set
46 - no virtual env, python3: real_prefix not set, base_prefix set and
47 identical to prefix
48 - virtualenv, python2: real_prefix and prefix are set and different
49 - virtualenv, python3: real_prefix not set, base_prefix and prefix are
50 set and identical
51 - pyvenv, any python version: real_prefix not set, base_prefix and prefix
52 are set and different
53
54 :return: default config dir
55 """
56 real_prefix = getattr(sys, 'real_prefix', None)
57 base_prefix = getattr(sys, 'base_prefix', None)
58 prefix = sys.prefix
Ken'ichi Ohmichi0ce16522016-04-23 12:52:05 -070059 global_conf_dir = '/etc/tempest'
David Paterson0bf52d42015-04-13 21:55:58 -040060 if (real_prefix is None and
Ken'ichi Ohmichi0ce16522016-04-23 12:52:05 -070061 (base_prefix is None or base_prefix == prefix) and
62 os.path.isdir(global_conf_dir)):
David Paterson0bf52d42015-04-13 21:55:58 -040063 # Probably not running in a virtual environment.
Andrea Frittoli (andreaf)5a69e552015-07-31 18:40:17 +010064 # NOTE(andreaf) we cannot distinguish this case from the case of
65 # a virtual environment created with virtualenv, and running python3.
David Paterson0bf52d42015-04-13 21:55:58 -040066 # Also if it appears we are not in virtual env and fail to find
67 # global config: '/etc/tempest', fall back to
68 # '[sys.prefix]/etc/tempest'
Ken'ichi Ohmichi0ce16522016-04-23 12:52:05 -070069 return global_conf_dir
Andrea Frittoli (andreaf)5a69e552015-07-31 18:40:17 +010070 else:
Ken'ichi Ohmichi7e054d42016-04-23 13:00:08 -070071 conf_dir = os.path.join(prefix, 'etc/tempest')
72 if os.path.isdir(conf_dir):
73 return conf_dir
74 else:
75 # NOTE: The prefix is gotten from the path which pyconfig.h is
76 # installed under. Some envs contain it under /usr/include, not
77 # /user/local/include. Then prefix becomes /usr on such envs.
78 # However, etc/tempest is installed under /usr/local and the bove
79 # path logic mismatches. This is a workaround for such envs.
80 return os.path.join(prefix, 'local/etc/tempest')
Andrea Frittoli (andreaf)5a69e552015-07-31 18:40:17 +010081
82
Matthew Treinishf610aca2015-06-30 15:32:34 -040083class TempestInit(command.Command):
84 """Setup a local working environment for running tempest"""
85
86 def get_parser(self, prog_name):
87 parser = super(TempestInit, self).get_parser(prog_name)
88 parser.add_argument('dir', nargs='?', default=os.getcwd())
Andrea Frittoli (andreaf)5a69e552015-07-31 18:40:17 +010089 parser.add_argument('--config-dir', '-c', default=None)
Matthew Treinish054f45d2016-04-23 16:30:29 -040090 parser.add_argument('--show-global-config-dir', '-s',
91 action='store_true', dest='show_global_dir',
92 help="Print the global config dir location, "
93 "then exit")
step682980c14ec2016-02-23 14:53:52 -050094 parser.add_argument('--name', help="The workspace name", default=None)
95 parser.add_argument('--workspace-path', default=None,
96 help="The path to the workspace file, the default "
97 "is ~/.tempest/workspace")
Matthew Treinishf610aca2015-06-30 15:32:34 -040098 return parser
99
100 def generate_testr_conf(self, local_path):
101 testr_conf_path = os.path.join(local_path, '.testr.conf')
102 top_level_path = os.path.dirname(os.path.dirname(__file__))
103 discover_path = os.path.join(top_level_path, 'test_discover')
104 testr_conf = TESTR_CONF % (top_level_path, discover_path)
105 with open(testr_conf_path, 'w+') as testr_conf_file:
106 testr_conf_file.write(testr_conf)
107
108 def update_local_conf(self, conf_path, lock_dir, log_dir):
109 config_parse = moves.configparser.SafeConfigParser()
110 config_parse.optionxform = str
Masayuki Igawa63cb9a32016-04-27 06:23:36 +0900111 with open(conf_path, 'a+') as conf_file:
Matthew Treinishf610aca2015-06-30 15:32:34 -0400112 # Set local lock_dir in tempest conf
113 if not config_parse.has_section('oslo_concurrency'):
114 config_parse.add_section('oslo_concurrency')
115 config_parse.set('oslo_concurrency', 'lock_path', lock_dir)
116 # Set local log_dir in tempest conf
117 config_parse.set('DEFAULT', 'log_dir', log_dir)
118 # Set default log filename to tempest.log
119 config_parse.set('DEFAULT', 'log_file', 'tempest.log')
ghanshyam0e1dd842016-04-27 07:59:23 +0900120 config_parse.write(conf_file)
Matthew Treinishf610aca2015-06-30 15:32:34 -0400121
122 def copy_config(self, etc_dir, config_dir):
Matthew Treinishd5cef952016-06-07 16:54:55 -0400123 if os.path.isdir(config_dir):
124 shutil.copytree(config_dir, etc_dir)
125 else:
126 LOG.warning("Global config dir %s can't be found" % config_dir)
Matthew Treinishf610aca2015-06-30 15:32:34 -0400127
David Paterson0bf52d42015-04-13 21:55:58 -0400128 def generate_sample_config(self, local_dir, config_dir):
Matthew Treinishd5cef952016-06-07 16:54:55 -0400129 if os.path.isdir(config_dir):
130 conf_generator = os.path.join(config_dir,
131 'config-generator.tempest.conf')
David Paterson0bf52d42015-04-13 21:55:58 -0400132
Matthew Treinishd5cef952016-06-07 16:54:55 -0400133 subprocess.call(['oslo-config-generator', '--config-file',
134 conf_generator],
135 cwd=local_dir)
136 else:
137 LOG.warning("Skipping sample config generation because global "
138 "config dir %s can't be found" % config_dir)
Matthew Treinishc8a39b42015-07-27 17:07:37 -0400139
Matthew Treinishf610aca2015-06-30 15:32:34 -0400140 def create_working_dir(self, local_dir, config_dir):
141 # Create local dir if missing
142 if not os.path.isdir(local_dir):
143 LOG.debug('Creating local working dir: %s' % local_dir)
144 os.mkdir(local_dir)
Marc Koderer090b5dc2015-11-04 10:35:48 +0100145 elif not os.listdir(local_dir) == []:
David Paterson0bf52d42015-04-13 21:55:58 -0400146 raise OSError("Directory you are trying to initialize already "
Marc Koderer090b5dc2015-11-04 10:35:48 +0100147 "exists and is not empty: %s" % local_dir)
David Paterson0bf52d42015-04-13 21:55:58 -0400148
Matthew Treinishf610aca2015-06-30 15:32:34 -0400149 lock_dir = os.path.join(local_dir, 'tempest_lock')
150 etc_dir = os.path.join(local_dir, 'etc')
151 config_path = os.path.join(etc_dir, 'tempest.conf')
152 log_dir = os.path.join(local_dir, 'logs')
153 testr_dir = os.path.join(local_dir, '.testrepository')
154 # Create lock dir
155 if not os.path.isdir(lock_dir):
156 LOG.debug('Creating lock dir: %s' % lock_dir)
157 os.mkdir(lock_dir)
158 # Create log dir
159 if not os.path.isdir(log_dir):
160 LOG.debug('Creating log dir: %s' % log_dir)
161 os.mkdir(log_dir)
162 # Create and copy local etc dir
163 self.copy_config(etc_dir, config_dir)
Matthew Treinishc8a39b42015-07-27 17:07:37 -0400164 # Generate the sample config file
David Paterson0bf52d42015-04-13 21:55:58 -0400165 self.generate_sample_config(local_dir, config_dir)
Matthew Treinishf610aca2015-06-30 15:32:34 -0400166 # Update local confs to reflect local paths
167 self.update_local_conf(config_path, lock_dir, log_dir)
168 # Generate a testr conf file
169 self.generate_testr_conf(local_dir)
170 # setup local testr working dir
171 if not os.path.isdir(testr_dir):
172 subprocess.call(['testr', 'init'], cwd=local_dir)
173
174 def take_action(self, parsed_args):
step682980c14ec2016-02-23 14:53:52 -0500175 workspace_manager = WorkspaceManager(parsed_args.workspace_path)
176 name = parsed_args.name or parsed_args.dir.split(os.path.sep)[-1]
177 workspace_manager.register_new_workspace(
178 name, parsed_args.dir, init=True)
Andrea Frittoli (andreaf)5a69e552015-07-31 18:40:17 +0100179 config_dir = parsed_args.config_dir or get_tempest_default_config_dir()
Matthew Treinish054f45d2016-04-23 16:30:29 -0400180 if parsed_args.show_global_dir:
181 print("Global config dir is located at: %s" % config_dir)
182 sys.exit(0)
Andrea Frittoli (andreaf)5a69e552015-07-31 18:40:17 +0100183 self.create_working_dir(parsed_args.dir, config_dir)