blob: e3788abe3ee681451da0858c2c6f4df9823ba36f [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
Matthew Treinishbdef1c72016-06-21 18:06:49 -040021from oslo_config import generator
Matthew Treinishf610aca2015-06-30 15:32:34 -040022from oslo_log import log as logging
23from six import moves
24
step682980c14ec2016-02-23 14:53:52 -050025from tempest.cmd.workspace import WorkspaceManager
26
Matthew Treinishf610aca2015-06-30 15:32:34 -040027LOG = logging.getLogger(__name__)
28
29TESTR_CONF = """[DEFAULT]
30test_command=OS_STDOUT_CAPTURE=${OS_STDOUT_CAPTURE:-1} \\
31 OS_STDERR_CAPTURE=${OS_STDERR_CAPTURE:-1} \\
32 OS_TEST_TIMEOUT=${OS_TEST_TIMEOUT:-500} \\
33 ${PYTHON:-python} -m subunit.run discover -t %s %s $LISTOPT $IDOPTION
34test_id_option=--load-list $IDFILE
35test_list_option=--list
36group_regex=([^\.]*\.)*
37"""
38
39
Andrea Frittoli (andreaf)5a69e552015-07-31 18:40:17 +010040def get_tempest_default_config_dir():
Ken'ichi Ohmichi2e2ee192015-11-19 09:48:27 +000041 """Get default config directory of tempest
42
Matthew Treinish3fe57b32016-06-21 14:39:00 -040043 There are 3 dirs that get tried in priority order. First is /etc/tempest,
44 if that doesn't exist it looks for a tempest dir in the XDG_CONFIG_HOME
45 dir (defaulting to ~/.config/tempest) and last it tries for a
46 ~/.tempest/etc directory. If none of these exist a ~/.tempest/etc
47 directory will be created.
Andrea Frittoli (andreaf)5a69e552015-07-31 18:40:17 +010048
49 :return: default config dir
50 """
Ken'ichi Ohmichi0ce16522016-04-23 12:52:05 -070051 global_conf_dir = '/etc/tempest'
Matthew Treinish3fe57b32016-06-21 14:39:00 -040052 xdg_config = os.environ.get('XDG_CONFIG_HOME',
53 os.path.expanduser('~/.config'))
54 user_xdg_global_path = os.path.join(xdg_config, 'tempest')
55 user_global_path = os.path.join(os.path.expanduser('~'), '.tempest/etc')
56 if os.path.isdir(global_conf_dir):
Ken'ichi Ohmichi0ce16522016-04-23 12:52:05 -070057 return global_conf_dir
Matthew Treinish3fe57b32016-06-21 14:39:00 -040058 elif os.path.isdir(user_xdg_global_path):
59 return user_xdg_global_path
60 elif os.path.isdir(user_global_path):
61 return user_global_path
Andrea Frittoli (andreaf)5a69e552015-07-31 18:40:17 +010062 else:
Matthew Treinish3fe57b32016-06-21 14:39:00 -040063 os.makedirs(user_global_path)
64 return user_global_path
Andrea Frittoli (andreaf)5a69e552015-07-31 18:40:17 +010065
66
Matthew Treinishf610aca2015-06-30 15:32:34 -040067class TempestInit(command.Command):
68 """Setup a local working environment for running tempest"""
69
70 def get_parser(self, prog_name):
71 parser = super(TempestInit, self).get_parser(prog_name)
72 parser.add_argument('dir', nargs='?', default=os.getcwd())
Andrea Frittoli (andreaf)5a69e552015-07-31 18:40:17 +010073 parser.add_argument('--config-dir', '-c', default=None)
Matthew Treinish054f45d2016-04-23 16:30:29 -040074 parser.add_argument('--show-global-config-dir', '-s',
75 action='store_true', dest='show_global_dir',
76 help="Print the global config dir location, "
77 "then exit")
step682980c14ec2016-02-23 14:53:52 -050078 parser.add_argument('--name', help="The workspace name", default=None)
79 parser.add_argument('--workspace-path', default=None,
80 help="The path to the workspace file, the default "
81 "is ~/.tempest/workspace")
Matthew Treinishf610aca2015-06-30 15:32:34 -040082 return parser
83
84 def generate_testr_conf(self, local_path):
85 testr_conf_path = os.path.join(local_path, '.testr.conf')
86 top_level_path = os.path.dirname(os.path.dirname(__file__))
87 discover_path = os.path.join(top_level_path, 'test_discover')
88 testr_conf = TESTR_CONF % (top_level_path, discover_path)
89 with open(testr_conf_path, 'w+') as testr_conf_file:
90 testr_conf_file.write(testr_conf)
91
92 def update_local_conf(self, conf_path, lock_dir, log_dir):
93 config_parse = moves.configparser.SafeConfigParser()
94 config_parse.optionxform = str
Masayuki Igawa63cb9a32016-04-27 06:23:36 +090095 with open(conf_path, 'a+') as conf_file:
Matthew Treinishf610aca2015-06-30 15:32:34 -040096 # Set local lock_dir in tempest conf
97 if not config_parse.has_section('oslo_concurrency'):
98 config_parse.add_section('oslo_concurrency')
99 config_parse.set('oslo_concurrency', 'lock_path', lock_dir)
100 # Set local log_dir in tempest conf
101 config_parse.set('DEFAULT', 'log_dir', log_dir)
102 # Set default log filename to tempest.log
103 config_parse.set('DEFAULT', 'log_file', 'tempest.log')
ghanshyam0e1dd842016-04-27 07:59:23 +0900104 config_parse.write(conf_file)
Matthew Treinishf610aca2015-06-30 15:32:34 -0400105
106 def copy_config(self, etc_dir, config_dir):
Matthew Treinishd5cef952016-06-07 16:54:55 -0400107 if os.path.isdir(config_dir):
108 shutil.copytree(config_dir, etc_dir)
109 else:
110 LOG.warning("Global config dir %s can't be found" % config_dir)
Matthew Treinishf610aca2015-06-30 15:32:34 -0400111
Matthew Treinishbdef1c72016-06-21 18:06:49 -0400112 def generate_sample_config(self, local_dir):
113 conf_generator = os.path.join(os.path.dirname(__file__),
114 'config-generator.tempest.conf')
115 output_file = os.path.join(local_dir, 'etc/tempest.conf.sample')
116 if os.path.isfile(conf_generator):
117 generator.main(['--config-file', conf_generator, '--output-file',
118 output_file])
Matthew Treinishd5cef952016-06-07 16:54:55 -0400119 else:
120 LOG.warning("Skipping sample config generation because global "
Matthew Treinishbdef1c72016-06-21 18:06:49 -0400121 "config file %s can't be found" % conf_generator)
Matthew Treinishc8a39b42015-07-27 17:07:37 -0400122
Matthew Treinishf610aca2015-06-30 15:32:34 -0400123 def create_working_dir(self, local_dir, config_dir):
Jake Yip93464832016-06-18 00:57:40 +1000124 # make sure we are working with abspath however tempest init is called
125 local_dir = os.path.abspath(local_dir)
Matthew Treinishf610aca2015-06-30 15:32:34 -0400126 # Create local dir if missing
127 if not os.path.isdir(local_dir):
128 LOG.debug('Creating local working dir: %s' % local_dir)
129 os.mkdir(local_dir)
Marc Koderer090b5dc2015-11-04 10:35:48 +0100130 elif not os.listdir(local_dir) == []:
David Paterson0bf52d42015-04-13 21:55:58 -0400131 raise OSError("Directory you are trying to initialize already "
Marc Koderer090b5dc2015-11-04 10:35:48 +0100132 "exists and is not empty: %s" % local_dir)
David Paterson0bf52d42015-04-13 21:55:58 -0400133
Matthew Treinishf610aca2015-06-30 15:32:34 -0400134 lock_dir = os.path.join(local_dir, 'tempest_lock')
135 etc_dir = os.path.join(local_dir, 'etc')
136 config_path = os.path.join(etc_dir, 'tempest.conf')
137 log_dir = os.path.join(local_dir, 'logs')
138 testr_dir = os.path.join(local_dir, '.testrepository')
139 # Create lock dir
140 if not os.path.isdir(lock_dir):
141 LOG.debug('Creating lock dir: %s' % lock_dir)
142 os.mkdir(lock_dir)
143 # Create log dir
144 if not os.path.isdir(log_dir):
145 LOG.debug('Creating log dir: %s' % log_dir)
146 os.mkdir(log_dir)
147 # Create and copy local etc dir
148 self.copy_config(etc_dir, config_dir)
Matthew Treinishc8a39b42015-07-27 17:07:37 -0400149 # Generate the sample config file
Matthew Treinishbdef1c72016-06-21 18:06:49 -0400150 self.generate_sample_config(local_dir)
Matthew Treinishf610aca2015-06-30 15:32:34 -0400151 # Update local confs to reflect local paths
152 self.update_local_conf(config_path, lock_dir, log_dir)
153 # Generate a testr conf file
154 self.generate_testr_conf(local_dir)
155 # setup local testr working dir
156 if not os.path.isdir(testr_dir):
157 subprocess.call(['testr', 'init'], cwd=local_dir)
158
159 def take_action(self, parsed_args):
step682980c14ec2016-02-23 14:53:52 -0500160 workspace_manager = WorkspaceManager(parsed_args.workspace_path)
161 name = parsed_args.name or parsed_args.dir.split(os.path.sep)[-1]
162 workspace_manager.register_new_workspace(
163 name, parsed_args.dir, init=True)
Andrea Frittoli (andreaf)5a69e552015-07-31 18:40:17 +0100164 config_dir = parsed_args.config_dir or get_tempest_default_config_dir()
Matthew Treinish054f45d2016-04-23 16:30:29 -0400165 if parsed_args.show_global_dir:
166 print("Global config dir is located at: %s" % config_dir)
167 sys.exit(0)
Andrea Frittoli (andreaf)5a69e552015-07-31 18:40:17 +0100168 self.create_working_dir(parsed_args.dir, config_dir)