Add tempest init command to tempest cli

This commit adds a new 'tempest init' command to the unified cli.
This command tempest init will be the first step of the new workflow
for running tempest. It is used to initilize a local working directory
to run tempest from. The idea being you can setup different local
working dirs for different tempest envs to test against several
different clouds.

The basic idea for this new workflow after installing tempest is
something like:

 1. mkdir tempest-newcloud
 2. cd tempest-newcloud
 3. tempest init
 4. edit local config file
 5. tempest run

The next step after this is to start working on the 'tempest run'
command. (which will include the hooks for the tempest plugin
interface) But, until that is added a test runner can be called
directly inside a local tempest working directory.

Partially Implements bp tempest-cli-improvements

Change-Id: I572267e61ba8ca86f92299e174864a7a89597207
This commit is contained in:
Matthew Treinish 2015-06-30 15:32:34 -04:00
parent 54451b48d8
commit f610aca040
No known key found for this signature in database
GPG Key ID: FD12A0F214C9E177
3 changed files with 167 additions and 1 deletions

View File

@ -32,7 +32,8 @@ console_scripts =
tempest-cleanup = tempest.cmd.cleanup:main
tempest-account-generator = tempest.cmd.account_generator:main
tempest = tempest.cmd.main:main
tempest.cm =
init = tempest.cmd.init:TempestInit
oslo.config.opts =
tempest.config = tempest.config:list_opts

99
tempest/cmd/init.py Normal file
View File

@ -0,0 +1,99 @@
# Copyright 2015 Hewlett-Packard Development Company, L.P.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import os
import shutil
import subprocess
from cliff import command
from oslo_log import log as logging
from six import moves
LOG = logging.getLogger(__name__)
TESTR_CONF = """[DEFAULT]
test_command=OS_STDOUT_CAPTURE=${OS_STDOUT_CAPTURE:-1} \\
OS_STDERR_CAPTURE=${OS_STDERR_CAPTURE:-1} \\
OS_TEST_TIMEOUT=${OS_TEST_TIMEOUT:-500} \\
${PYTHON:-python} -m subunit.run discover -t %s %s $LISTOPT $IDOPTION
test_id_option=--load-list $IDFILE
test_list_option=--list
group_regex=([^\.]*\.)*
"""
class TempestInit(command.Command):
"""Setup a local working environment for running tempest"""
def get_parser(self, prog_name):
parser = super(TempestInit, self).get_parser(prog_name)
parser.add_argument('dir', nargs='?', default=os.getcwd())
parser.add_argument('--config-dir', '-c', default='/etc/tempest')
return parser
def generate_testr_conf(self, local_path):
testr_conf_path = os.path.join(local_path, '.testr.conf')
top_level_path = os.path.dirname(os.path.dirname(__file__))
discover_path = os.path.join(top_level_path, 'test_discover')
testr_conf = TESTR_CONF % (top_level_path, discover_path)
with open(testr_conf_path, 'w+') as testr_conf_file:
testr_conf_file.write(testr_conf)
def update_local_conf(self, conf_path, lock_dir, log_dir):
config_parse = moves.configparser.SafeConfigParser()
config_parse.optionxform = str
with open(conf_path, 'w+') as conf_file:
config_parse.readfp(conf_file)
# Set local lock_dir in tempest conf
if not config_parse.has_section('oslo_concurrency'):
config_parse.add_section('oslo_concurrency')
config_parse.set('oslo_concurrency', 'lock_path', lock_dir)
# Set local log_dir in tempest conf
config_parse.set('DEFAULT', 'log_dir', log_dir)
# Set default log filename to tempest.log
config_parse.set('DEFAULT', 'log_file', 'tempest.log')
def copy_config(self, etc_dir, config_dir):
shutil.copytree(config_dir, etc_dir)
def create_working_dir(self, local_dir, config_dir):
# Create local dir if missing
if not os.path.isdir(local_dir):
LOG.debug('Creating local working dir: %s' % local_dir)
os.mkdir(local_dir)
lock_dir = os.path.join(local_dir, 'tempest_lock')
etc_dir = os.path.join(local_dir, 'etc')
config_path = os.path.join(etc_dir, 'tempest.conf')
log_dir = os.path.join(local_dir, 'logs')
testr_dir = os.path.join(local_dir, '.testrepository')
# Create lock dir
if not os.path.isdir(lock_dir):
LOG.debug('Creating lock dir: %s' % lock_dir)
os.mkdir(lock_dir)
# Create log dir
if not os.path.isdir(log_dir):
LOG.debug('Creating log dir: %s' % log_dir)
os.mkdir(log_dir)
# Create and copy local etc dir
self.copy_config(etc_dir, config_dir)
# Update local confs to reflect local paths
self.update_local_conf(config_path, lock_dir, log_dir)
# Generate a testr conf file
self.generate_testr_conf(local_dir)
# setup local testr working dir
if not os.path.isdir(testr_dir):
subprocess.call(['testr', 'init'], cwd=local_dir)
def take_action(self, parsed_args):
self.create_working_dir(parsed_args.dir, parsed_args.config_dir)

View File

@ -0,0 +1,66 @@
# Copyright 2015 Hewlett-Packard Development Company, L.P.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import os
import fixtures
from tempest.cmd import init
from tempest.tests import base
class TestTempestInit(base.TestCase):
def test_generate_testr_conf(self):
# Create fake conf dir
conf_dir = self.useFixture(fixtures.TempDir())
init_cmd = init.TempestInit(None, None)
init_cmd.generate_testr_conf(conf_dir.path)
# Generate expected file contents
top_level_path = os.path.dirname(os.path.dirname(init.__file__))
discover_path = os.path.join(top_level_path, 'test_discover')
testr_conf_file = init.TESTR_CONF % (top_level_path, discover_path)
conf_path = conf_dir.join('.testr.conf')
conf_file = open(conf_path, 'r')
self.addCleanup(conf_file.close)
self.assertEqual(conf_file.read(), testr_conf_file)
def test_create_working_dir(self):
fake_local_dir = self.useFixture(fixtures.TempDir())
fake_local_conf_dir = self.useFixture(fixtures.TempDir())
# Create a fake conf file
fake_file = fake_local_conf_dir.join('conf_file.conf')
open(fake_file, 'w').close()
init_cmd = init.TempestInit(None, None)
init_cmd.create_working_dir(fake_local_dir.path,
fake_local_conf_dir.path)
# Assert directories are created
lock_path = os.path.join(fake_local_dir.path, 'tempest_lock')
etc_dir = os.path.join(fake_local_dir.path, 'etc')
log_dir = os.path.join(fake_local_dir.path, 'logs')
testr_dir = os.path.join(fake_local_dir.path, '.testrepository')
self.assertTrue(os.path.isdir(lock_path))
self.assertTrue(os.path.isdir(etc_dir))
self.assertTrue(os.path.isdir(log_dir))
self.assertTrue(os.path.isdir(testr_dir))
# Assert file creation
fake_file_moved = os.path.join(etc_dir, 'conf_file.conf')
local_conf_file = os.path.join(etc_dir, 'tempest.conf')
local_testr_conf = os.path.join(fake_local_dir.path, '.testr.conf')
self.assertTrue(os.path.isfile(fake_file_moved))
self.assertTrue(os.path.isfile(local_conf_file))
self.assertTrue(os.path.isfile(local_testr_conf))