blob: 6e93d696091c34a443e406e6789e2ba044eef463 [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
Andrea Frittoli (andreaf)5a69e552015-07-31 18:40:17 +010017import sys
Matthew Treinishf610aca2015-06-30 15:32:34 -040018
19from cliff import command
Matthew Treinishbdef1c72016-06-21 18:06:49 -040020from oslo_config import generator
Matthew Treinishf610aca2015-06-30 15:32:34 -040021from oslo_log import log as logging
22from six import moves
Chandan Kumar8a4396e2017-09-15 12:18:10 +053023from stestr import commands
Matthew Treinishf610aca2015-06-30 15:32:34 -040024
Cao Xuan Hoang36fe23c2016-08-25 16:11:14 +070025from tempest.cmd import workspace
step682980c14ec2016-02-23 14:53:52 -050026
Matthew Treinishf610aca2015-06-30 15:32:34 -040027LOG = logging.getLogger(__name__)
28
Stephen Finucane7f4a6212018-07-06 13:58:21 +010029STESTR_CONF = r"""[DEFAULT]
Chandan Kumar8a4396e2017-09-15 12:18:10 +053030test_path=%s
31top_dir=%s
Matthew Treinishf610aca2015-06-30 15:32:34 -040032group_regex=([^\.]*\.)*
33"""
34
35
Andrea Frittoli (andreaf)5a69e552015-07-31 18:40:17 +010036def get_tempest_default_config_dir():
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +000037 """Get default config directory of tempest
38
Matthew Treinish3fe57b32016-06-21 14:39:00 -040039 There are 3 dirs that get tried in priority order. First is /etc/tempest,
40 if that doesn't exist it looks for a tempest dir in the XDG_CONFIG_HOME
41 dir (defaulting to ~/.config/tempest) and last it tries for a
42 ~/.tempest/etc directory. If none of these exist a ~/.tempest/etc
43 directory will be created.
Andrea Frittoli (andreaf)5a69e552015-07-31 18:40:17 +010044
45 :return: default config dir
46 """
Masayuki Igawa9e492ee2019-09-19 12:15:04 +090047 # NOTE: The default directory should be on a Linux box.
Ken'ichi Ohmichi0ce16522016-04-23 12:52:05 -070048 global_conf_dir = '/etc/tempest'
Matthew Treinish3fe57b32016-06-21 14:39:00 -040049 xdg_config = os.environ.get('XDG_CONFIG_HOME',
Masayuki Igawa9e492ee2019-09-19 12:15:04 +090050 os.path.expanduser(os.path.join('~',
51 '.config')))
Matthew Treinish3fe57b32016-06-21 14:39:00 -040052 user_xdg_global_path = os.path.join(xdg_config, 'tempest')
Masayuki Igawa9e492ee2019-09-19 12:15:04 +090053 user_global_path = os.path.join(os.path.expanduser('~'),
54 '.tempest', 'etc')
Matthew Treinish3fe57b32016-06-21 14:39:00 -040055 if os.path.isdir(global_conf_dir):
Ken'ichi Ohmichi0ce16522016-04-23 12:52:05 -070056 return global_conf_dir
Matthew Treinish3fe57b32016-06-21 14:39:00 -040057 elif os.path.isdir(user_xdg_global_path):
58 return user_xdg_global_path
59 elif os.path.isdir(user_global_path):
60 return user_global_path
Andrea Frittoli (andreaf)5a69e552015-07-31 18:40:17 +010061 else:
Matthew Treinish3fe57b32016-06-21 14:39:00 -040062 os.makedirs(user_global_path)
63 return user_global_path
Andrea Frittoli (andreaf)5a69e552015-07-31 18:40:17 +010064
65
Matthew Treinishf610aca2015-06-30 15:32:34 -040066class TempestInit(command.Command):
67 """Setup a local working environment for running tempest"""
68
69 def get_parser(self, prog_name):
70 parser = super(TempestInit, self).get_parser(prog_name)
Masayuki Igawa0670a2b2016-09-12 14:55:11 +090071 parser.add_argument('dir', nargs='?', default=os.getcwd(),
72 help="The path to the workspace directory. If you "
73 "omit this argument, the workspace directory is "
74 "your current directory")
Andrea Frittoli (andreaf)5a69e552015-07-31 18:40:17 +010075 parser.add_argument('--config-dir', '-c', default=None)
Matthew Treinish054f45d2016-04-23 16:30:29 -040076 parser.add_argument('--show-global-config-dir', '-s',
77 action='store_true', dest='show_global_dir',
78 help="Print the global config dir location, "
79 "then exit")
step682980c14ec2016-02-23 14:53:52 -050080 parser.add_argument('--name', help="The workspace name", default=None)
81 parser.add_argument('--workspace-path', default=None,
82 help="The path to the workspace file, the default "
Masayuki Igawa0670a2b2016-09-12 14:55:11 +090083 "is ~/.tempest/workspace.yaml")
Matthew Treinishf610aca2015-06-30 15:32:34 -040084 return parser
85
Chandan Kumar8a4396e2017-09-15 12:18:10 +053086 def generate_stestr_conf(self, local_path):
87 stestr_conf_path = os.path.join(local_path, '.stestr.conf')
Matthew Treinishf610aca2015-06-30 15:32:34 -040088 top_level_path = os.path.dirname(os.path.dirname(__file__))
89 discover_path = os.path.join(top_level_path, 'test_discover')
Chandan Kumar8a4396e2017-09-15 12:18:10 +053090 stestr_conf = STESTR_CONF % (discover_path, top_level_path)
91 with open(stestr_conf_path, 'w+') as stestr_conf_file:
92 stestr_conf_file.write(stestr_conf)
Matthew Treinishf610aca2015-06-30 15:32:34 -040093
Matthew Treinish3c39bb62016-08-09 14:44:44 -040094 def get_configparser(self, conf_path):
Janonymous8254a3f2016-09-15 10:38:48 +053095 config_parse = moves.configparser.ConfigParser()
Matthew Treinishf610aca2015-06-30 15:32:34 -040096 config_parse.optionxform = str
Matthew Treinish3c39bb62016-08-09 14:44:44 -040097 # get any existing values if a config file already exists
98 if os.path.isfile(conf_path):
99 # use read() for Python 2 and 3 compatibility
100 config_parse.read(conf_path)
101 return config_parse
102
103 def update_local_conf(self, conf_path, lock_dir, log_dir):
104 config_parse = self.get_configparser(conf_path)
105 # Set local lock_dir in tempest conf
106 if not config_parse.has_section('oslo_concurrency'):
107 config_parse.add_section('oslo_concurrency')
108 config_parse.set('oslo_concurrency', 'lock_path', lock_dir)
109 # Set local log_dir in tempest conf
110 config_parse.set('DEFAULT', 'log_dir', log_dir)
111 # Set default log filename to tempest.log
112 config_parse.set('DEFAULT', 'log_file', 'tempest.log')
113
114 # write out a new file with the updated configurations
115 with open(conf_path, 'w+') as conf_file:
ghanshyam0e1dd842016-04-27 07:59:23 +0900116 config_parse.write(conf_file)
Matthew Treinishf610aca2015-06-30 15:32:34 -0400117
118 def copy_config(self, etc_dir, config_dir):
Matthew Treinishd5cef952016-06-07 16:54:55 -0400119 if os.path.isdir(config_dir):
120 shutil.copytree(config_dir, etc_dir)
121 else:
Jordan Pittier525ec712016-12-07 17:51:26 +0100122 LOG.warning("Global config dir %s can't be found", config_dir)
Matthew Treinishf610aca2015-06-30 15:32:34 -0400123
Matthew Treinishbdef1c72016-06-21 18:06:49 -0400124 def generate_sample_config(self, local_dir):
125 conf_generator = os.path.join(os.path.dirname(__file__),
126 'config-generator.tempest.conf')
Masayuki Igawa9e492ee2019-09-19 12:15:04 +0900127 output_file = os.path.join(local_dir, 'etc', 'tempest.conf.sample')
Matthew Treinishbdef1c72016-06-21 18:06:49 -0400128 if os.path.isfile(conf_generator):
129 generator.main(['--config-file', conf_generator, '--output-file',
130 output_file])
Matthew Treinishd5cef952016-06-07 16:54:55 -0400131 else:
132 LOG.warning("Skipping sample config generation because global "
Jordan Pittier525ec712016-12-07 17:51:26 +0100133 "config file %s can't be found", conf_generator)
Matthew Treinishc8a39b42015-07-27 17:07:37 -0400134
Matthew Treinishf610aca2015-06-30 15:32:34 -0400135 def create_working_dir(self, local_dir, config_dir):
Jake Yip93464832016-06-18 00:57:40 +1000136 # make sure we are working with abspath however tempest init is called
137 local_dir = os.path.abspath(local_dir)
Matthew Treinishf610aca2015-06-30 15:32:34 -0400138 # Create local dir if missing
139 if not os.path.isdir(local_dir):
Jordan Pittier525ec712016-12-07 17:51:26 +0100140 LOG.debug('Creating local working dir: %s', local_dir)
Matthew Treinishf610aca2015-06-30 15:32:34 -0400141 os.mkdir(local_dir)
wangqi814a87c2018-04-19 02:31:40 +0000142 elif os.listdir(local_dir):
David Paterson0bf52d42015-04-13 21:55:58 -0400143 raise OSError("Directory you are trying to initialize already "
Marc Koderer090b5dc2015-11-04 10:35:48 +0100144 "exists and is not empty: %s" % local_dir)
David Paterson0bf52d42015-04-13 21:55:58 -0400145
Matthew Treinishf610aca2015-06-30 15:32:34 -0400146 lock_dir = os.path.join(local_dir, 'tempest_lock')
147 etc_dir = os.path.join(local_dir, 'etc')
148 config_path = os.path.join(etc_dir, 'tempest.conf')
149 log_dir = os.path.join(local_dir, 'logs')
Chandan Kumar8a4396e2017-09-15 12:18:10 +0530150 stestr_dir = os.path.join(local_dir, '.stestr')
Matthew Treinishf610aca2015-06-30 15:32:34 -0400151 # Create lock dir
152 if not os.path.isdir(lock_dir):
Jordan Pittier525ec712016-12-07 17:51:26 +0100153 LOG.debug('Creating lock dir: %s', lock_dir)
Matthew Treinishf610aca2015-06-30 15:32:34 -0400154 os.mkdir(lock_dir)
155 # Create log dir
156 if not os.path.isdir(log_dir):
Jordan Pittier525ec712016-12-07 17:51:26 +0100157 LOG.debug('Creating log dir: %s', log_dir)
Matthew Treinishf610aca2015-06-30 15:32:34 -0400158 os.mkdir(log_dir)
159 # Create and copy local etc dir
160 self.copy_config(etc_dir, config_dir)
Matthew Treinishc8a39b42015-07-27 17:07:37 -0400161 # Generate the sample config file
Matthew Treinishbdef1c72016-06-21 18:06:49 -0400162 self.generate_sample_config(local_dir)
Matthew Treinishf610aca2015-06-30 15:32:34 -0400163 # Update local confs to reflect local paths
164 self.update_local_conf(config_path, lock_dir, log_dir)
Chandan Kumar8a4396e2017-09-15 12:18:10 +0530165 # Generate a stestr conf file
166 self.generate_stestr_conf(local_dir)
167 # setup local stestr working dir
168 if not os.path.isdir(stestr_dir):
169 commands.init_command(repo_url=local_dir)
Matthew Treinishf610aca2015-06-30 15:32:34 -0400170
171 def take_action(self, parsed_args):
Cao Xuan Hoang36fe23c2016-08-25 16:11:14 +0700172 workspace_manager = workspace.WorkspaceManager(
173 parsed_args.workspace_path)
step682980c14ec2016-02-23 14:53:52 -0500174 name = parsed_args.name or parsed_args.dir.split(os.path.sep)[-1]
Andrea Frittoli (andreaf)5a69e552015-07-31 18:40:17 +0100175 config_dir = parsed_args.config_dir or get_tempest_default_config_dir()
Matthew Treinish054f45d2016-04-23 16:30:29 -0400176 if parsed_args.show_global_dir:
177 print("Global config dir is located at: %s" % config_dir)
178 sys.exit(0)
Andrea Frittoli (andreaf)5a69e552015-07-31 18:40:17 +0100179 self.create_working_dir(parsed_args.dir, config_dir)
Masayuki Igawaf8026412016-09-12 17:12:35 +0900180 workspace_manager.register_new_workspace(
181 name, parsed_args.dir, init=True)