shaker/shaker/engine/config.py

255 lines
10 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 re
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/'
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"
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 10,
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='Another way to specify tenant name. This option is '
'mutually exclusive with --os-tenant-name. '
'Defaults to env[OS_PROJECT_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-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('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 seperated 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 occured 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.StrOpt('scenario',
default=utils.env('SHAKER_SCENARIO'),
required=True,
help=utils.make_help_options(
'Scenario to play. Can be a file name or one of aliases: '
'%s. Defaults to env[SHAKER_SCENARIO].', SCENARIOS,
type_filter=lambda x: x.endswith('.yaml'))),
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'),
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_execution>.json'),
cfg.BoolOpt('no-report-on-error',
default=(utils.env('SHAKER_NO_REPORT_ON_ERROR') or False),
help='Do not generate report for failed scenarios'),
]
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.StrOpt('input',
default=utils.env('SHAKER_INPUT'),
required=True,
help='File 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]'),
]
CLEANUP_OPTS = [
cfg.BoolOpt('cleanup',
default=(utils.env('SHAKER_CLEANUP') or True),
help='Cleanup the image and the flavor.'),
]
# very specific, should not be listed in list_opts()
ALL_IN_ONE_OPTS = [
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].'),
]
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))