shaker/shaker/engine/config.py

318 lines
14 KiB
Python

# Copyright (c) 2015 Mirantis Inc.
#
# 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 copy
import datetime
import os
import re
import tempfile
import yaml
from oslo_config import cfg
from oslo_config import types
from shaker.engine import utils
IMAGE_BUILDER_TEMPLATES = 'shaker/resources/image_builder_templates/'
REPORT_TEMPLATES = 'shaker/resources/report_templates/'
SCENARIOS = 'shaker/scenarios/'
SCHEMAS = 'shaker/resources/schemas/'
DEFAULT_POLLING_INTERVAL = 10
class Endpoint(types.String):
def __call__(self, value):
value = str(value)
if not re.match('\S+:\d+', value):
raise ValueError('Wrong value of server_endpoint, '
'expected <host>:<port>, but got: %s' % value)
return value
def __repr__(self):
return "Endpoint <host:port>"
class Yaml(types.String):
def __call__(self, value):
value = str(value)
try:
value = yaml.safe_load(value)
except Exception:
raise ValueError('YAML value is expected, but got: %s' % value)
return value
def __repr__(self):
return "YAML data"
def generate_output_name():
file_name = "shaker_%s.json" % utils.strict(str(datetime.datetime.now()))
return os.path.join(tempfile.gettempdir(), file_name)
COMMON_OPTS = [
cfg.Opt('server-endpoint',
default=utils.env('SHAKER_SERVER_ENDPOINT'),
required=True,
type=Endpoint(),
help='Address for server connections (host:port), '
'defaults to env[SHAKER_SERVER_ENDPOINT].'),
cfg.IntOpt('polling-interval',
default=(utils.env('SHAKER_POLLING_INTERVAL') or
DEFAULT_POLLING_INTERVAL),
help='How frequently the agent polls server, in seconds')
]
OPENSTACK_OPTS = [
cfg.StrOpt('os-auth-url', metavar='<auth-url>',
default=utils.env('OS_AUTH_URL'),
sample_default='',
help='Authentication URL, defaults to env[OS_AUTH_URL].'),
cfg.StrOpt('os-tenant-name', metavar='<auth-tenant-name>',
default=utils.env('OS_TENANT_NAME'),
sample_default='',
help='Authentication tenant name, defaults to '
'env[OS_TENANT_NAME].'),
cfg.StrOpt('os-project-name', metavar='<auth-project-name>',
default=utils.env('OS_PROJECT_NAME'),
sample_default='',
help='Authentication project name. This option is '
'mutually exclusive with --os-tenant-name. '
'Defaults to env[OS_PROJECT_NAME].'),
cfg.StrOpt('os-project-domain-name', metavar='<auth-project-domain-name>',
default=utils.env('OS_PROJECT_DOMAIN_NAME'),
sample_default='Default',
help='Authentication project domain name. '
'Defaults to env[OS_PROJECT_DOMAIN_NAME].'),
cfg.StrOpt('os-username', metavar='<auth-username>',
default=utils.env('OS_USERNAME'),
sample_default='',
help='Authentication username, defaults to env[OS_USERNAME].'),
cfg.StrOpt('os-user-domain-name', metavar='<auth-user-domain-name>',
default=utils.env('OS_USER_DOMAIN_NAME'),
sample_default='',
help='Authentication username. Defaults to '
'env[OS_USER_DOMAIN_NAME].'),
cfg.StrOpt('os-identity-api-version', metavar='<identity-api-version>',
default=utils.env('OS_IDENTITY_API_VERSION'),
sample_default='3',
help='Identity API version, defaults to '
'env[OS_IDENTITY_API_VERSION].'),
cfg.StrOpt('os-password', metavar='<auth-password>',
default=utils.env('OS_PASSWORD'),
sample_default='',
help='Authentication password, defaults to env[OS_PASSWORD].'),
cfg.StrOpt('os-cacert', metavar='<auth-cacert>',
default=utils.env('OS_CACERT'),
sample_default='',
help='Location of CA Certificate, defaults to env[OS_CACERT].'),
cfg.BoolOpt('os-insecure',
default=(utils.env('OS_INSECURE') or False),
help='When using SSL in connections to the registry server, '
'do not require validation via a certifying authority, '
'defaults to env[OS_INSECURE].'),
cfg.StrOpt('os-region-name', metavar='<auth-region-name>',
default=utils.env('OS_REGION_NAME') or 'RegionOne',
help='Authentication region name, defaults to '
'env[OS_REGION_NAME].'),
cfg.StrOpt('os-interface', metavar='<os-interface>',
default=utils.env('OS_INTERFACE'),
sample_default='',
help='Interface type. Valid options are public, '
'admin and internal. defaults to '
'env[OS_INTERFACE].'),
cfg.StrOpt('os-profile', metavar='<hmac-key>',
default=utils.env('OS_PROFILE'),
sample_default='',
help='HMAC key for encrypting profiling context data, '
'defaults to env[OS_PROFILE].'),
cfg.StrOpt('external-net',
default=utils.env('SHAKER_EXTERNAL_NET'),
help='Name or ID of external network, defaults to '
'env[SHAKER_EXTERNAL_NET]. If no value provided then '
'Shaker picks any of available external networks.'),
cfg.ListOpt('dns-nameservers',
default=['8.8.8.8', '8.8.4.4'],
help='Comma-separated list of IPs of the DNS nameservers '
'for the subnets. If no value is provided defaults to '
' Google Public DNS.'),
cfg.StrOpt('image-name',
default=utils.env('SHAKER_IMAGE') or 'shaker-image',
help='Name of image to use. The default is created by '
'shaker-image-builder.'),
cfg.StrOpt('flavor-name',
default=utils.env('SHAKER_FLAVOR') or 'shaker-flavor',
help='Name of image flavor. The default is created by '
'shaker-image-builder.'),
cfg.BoolOpt('cleanup-on-error',
default=(utils.env('SHAKER_CLEANUP_ON_ERROR') or True),
help='Clean up the heat-stack upon any error occurred during '
'scenario execution.'),
]
SERVER_AGENT_OPTS = [
cfg.IntOpt('agent-loss-timeout',
default=utils.env('SHAKER_AGENT_LOSS_TIMEOUT') or 60,
help='Timeout to treat agent as lost in seconds, '
'defaults to env[SHAKER_AGENT_LOSS_TIMEOUT]'),
cfg.IntOpt('agent-join-timeout',
default=utils.env('SHAKER_AGENT_JOIN_TIMEOUT') or 600,
help='Timeout to treat agent as join failed in seconds, '
'defaults to env[SHAKER_AGENT_JOIN_TIMEOUT] (time '
'between stack deployment and start of scenario '
'execution).'),
]
SCENARIO_OPTS = [
cfg.ListOpt('scenario',
default=utils.env('SHAKER_SCENARIO'),
required=True,
help=utils.make_help_options(
'Comma-separated list of scenarios to play. Each entity '
'can be a file name or one of aliases: '
'%s. Defaults to env[SHAKER_SCENARIO].', SCENARIOS,
type_filter=lambda x: (x.endswith('.yaml')
and not x.startswith('test/')))),
cfg.Opt('matrix',
default=utils.env('SHAKER_MATRIX'),
type=Yaml(),
help='Set the matrix of parameters for the scenario. The value '
'is specified in YAML format. E.g. to override the scenario '
'duration one may provide: "{time: 10}", or to override list '
'of hosts: "{host:[ping.online.net, iperf.eenet.ee]}". When '
'several parameters are overridden all combinations are '
'tested'),
cfg.StrOpt('output',
default=utils.env('SHAKER_OUTPUT') or generate_output_name(),
sample_default='',
help='File for output in JSON format, '
'defaults to env[SHAKER_OUTPUT]. If it is empty, then '
'output will be saved to '
'/tmp/shaker_<time_now>.json'),
cfg.StrOpt('artifacts-dir', default=utils.env('SHAKER_ARTIFACTS_DIR'),
help='If specified, directs Shaker to store there all its '
'artifacts (output, report, subunit and book). '
'Defaults to env[SHAKER_ARTIFACTS_DIR].'),
cfg.BoolOpt('no-report-on-error',
deprecated_for_removal=True,
default=(utils.env('SHAKER_NO_REPORT_ON_ERROR') or False),
help='Do not generate report for failed scenarios'),
cfg.ListOpt('scenario_availability_zone',
default=utils.env('SCENARIO_AVAILABILITY_ZONE'),
help='Comma-separated list of availability_zone. If specified '
'this setting will override the availability_zone '
'accomodation setting in the scenario test definition.'
'Defaults to SCENARIO_AVAILABILITY_ZONE'),
cfg.IntOpt('scenario_compute_nodes',
default=utils.env('SCENARIO_COMPUTE_NODES'),
help='Number of compute_nodes. If specified this setting will '
'override the compute_nodes accomodation setting in the '
'scenario test definition. '
'Defaults to SCENARIO_COMPUTE_NODES'),
]
SERVER_OPTS = SCENARIO_OPTS + SERVER_AGENT_OPTS
REPORT_OPTS = [
cfg.StrOpt('report-template',
default=(utils.env('SHAKER_REPORT_TEMPLATE') or 'interactive'),
help=utils.make_help_options(
'Template for report. Can be a file name or one of '
'aliases: %s. Defaults to "interactive".',
REPORT_TEMPLATES)),
cfg.StrOpt('report',
default=utils.env('SHAKER_REPORT'),
help='Report file name, defaults to env[SHAKER_REPORT]. '),
cfg.StrOpt('subunit',
default=utils.env('SHAKER_SUBUNIT'),
help='Subunit stream file name, defaults to '
'env[SHAKER_SUBUNIT].'),
cfg.StrOpt('book',
default=utils.env('SHAKER_BOOK'),
help='Generate report in ReST format and store it into the '
'specified folder, defaults to env[SHAKER_BOOK]. '),
]
INPUT_OPTS = [
cfg.ListOpt('input',
default=utils.env('SHAKER_INPUT'),
required=True,
help='File or list of files to read test results from, '
'defaults to env[SHAKER_INPUT].'),
]
AGENT_OPTS = [
cfg.StrOpt('agent-id',
default=utils.env('SHAKER_AGENT_ID'),
help='Agent unique id, defaults to MAC of primary interface.'),
]
IMAGE_BUILDER_OPTS = [
cfg.StrOpt('image-builder-template',
default=(utils.env('SHAKER_IMAGE_BUILDER_TEMPLATE') or
'ubuntu'),
help=utils.make_help_options(
'Heat template containing receipt of building the image. '
'Can be a file name or one of aliases: %s. '
'Defaults to "ubuntu".', IMAGE_BUILDER_TEMPLATES)),
cfg.IntOpt('flavor-ram',
default=utils.env('SHAKER_FLAVOR_RAM') or 512,
help='Shaker image RAM size in MB, defaults to '
'env[SHAKER_FLAVOR_RAM]'),
cfg.IntOpt('flavor-vcpus',
default=utils.env('SHAKER_FLAVOR_VCPUS') or 1,
help='Number of cores to allocate for Shaker image, '
'defaults to env[SHAKER_FLAVOR_VCPUS]'),
cfg.IntOpt('flavor-disk',
default=utils.env('SHAKER_FLAVOR_DISK') or 3,
help='Shaker image disk size in GB, defaults to '
'env[SHAKER_FLAVOR_DISK]'),
cfg.StrOpt('image-builder-mode',
default=utils.env('SHAKER_IMAGE_BUILDER_MODE'),
choices=['heat', 'dib'],
help='Image building mode: "heat" - using Heat template '
'(requires Glance v1 for base image upload); '
'"dib" - using diskimage-builder elements '
'(requires qemu-utils and debootstrap). If not set, '
'switches to "dib" if Glance v1 is not available. '
'Can be specified as env[SHAKER_IMAGE_BUILDER_MODE]'),
cfg.StrOpt('image-builder-distro',
default=(utils.env('SHAKER_IMAGE_BUILDER_DISTRO') or
'ubuntu'),
choices=['ubuntu', 'centos7'],
help='Operating System Distribution for shaker image '
'when using diskimage-builder, defaults to ubuntu'),
]
CLEANUP_OPTS = [
cfg.BoolOpt('cleanup',
default=(utils.env('SHAKER_CLEANUP') or True),
help='Cleanup the image and the flavor.'),
]
def list_opts():
all_opts = (COMMON_OPTS + OPENSTACK_OPTS + SERVER_OPTS + REPORT_OPTS +
INPUT_OPTS + AGENT_OPTS + IMAGE_BUILDER_OPTS + CLEANUP_OPTS)
yield (None, copy.deepcopy(all_opts))