Merge "Smoke and bvt tests"

This commit is contained in:
Jenkins 2016-10-10 09:58:54 +00:00 committed by Gerrit Code Review
commit c3447a069a
13 changed files with 1476 additions and 60 deletions

4
.gitmodules vendored Normal file
View File

@ -0,0 +1,4 @@
[submodule "plugin_test/fuel-qa"]
path = plugin_test/fuel-qa
url = https://github.com/openstack/fuel-qa
branch = stable/mitaka

14
plugin_test/__init__.py Normal file
View File

@ -0,0 +1,14 @@
"""Copyright 2016 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
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.
"""

1
plugin_test/fuel-qa Submodule

@ -0,0 +1 @@
Subproject commit 15681971a6ff4adc9a8fd0b567f7443a3db6ffab

View File

@ -0,0 +1,14 @@
"""Copyright 2016 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
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.
"""

View File

@ -0,0 +1,81 @@
"""Copyright 2016 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
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
from fuelweb_test.settings import get_var_as_bool
from fuelweb_test.settings import iface_alias
from fuelweb_test.settings import NEUTRON_SEGMENT_TYPE
HALF_MIN_WAIT = 30 # 30 seconds
WAIT_FOR_COMMAND = 60 * 3 # 3 minutes
WAIT_FOR_LONG_DEPLOY = 60 * 180 # 180 minutes
EXT_IP = '8.8.8.8' # Google DNS ^_^
PRIVATE_NET = os.environ.get('PRIVATE_NET', 'admin_internal_net')
ADMIN_NET = os.environ.get('ADMIN_NET', 'admin_floating_net')
DEFAULT_ROUTER_NAME = os.environ.get('DEFAULT_ROUTER_NAME', 'router04')
METADATA_IP = os.environ.get('METADATA_IP', '169.254.169.254')
VM_USER = 'cirros'
VM_PASS = 'cubswin:)'
AZ_VCENTER1 = 'vcenter'
AZ_VCENTER2 = 'vcenter2'
FLAVOR_NAME = 'm1.micro128'
PLUGIN_NAME = os.environ.get('PLUGIN_NAME', 'nsx-t')
NSXT_PLUGIN_PATH = os.environ.get('NSXT_PLUGIN_PATH')
NSXT_PLUGIN_VERSION = os.environ.get('NSXT_PLUGIN_VERSION', '1.0.0')
NSXT_MANAGERS_IP = os.environ.get('NSXT_MANAGERS_IP')
NSXT_USER = os.environ.get('NSXT_USER')
assigned_networks = {
iface_alias('eth0'): ['fuelweb_admin', 'private'],
iface_alias('eth1'): ['public'],
iface_alias('eth2'): ['storage'],
iface_alias('eth4'): ['management']
}
cluster_settings = {
'net_provider': 'neutron',
'assign_to_all_nodes': True,
'net_segment_type': NEUTRON_SEGMENT_TYPE
}
plugin_configuration = {
'insecure/value': get_var_as_bool(os.environ.get('NSXT_INSECURE'), True),
'nsx_api_managers/value': NSXT_MANAGERS_IP,
'nsx_api_user/value': NSXT_USER,
'nsx_api_password/value': os.environ.get('NSXT_PASSWORD'),
'default_overlay_tz_uuid/value': os.environ.get('NSXT_OVERLAY_TZ_UUID'),
'default_vlan_tz_uuid/value': os.environ.get('NSXT_VLAN_TZ_UUID'),
'default_tier0_router_uuid/value': os.environ.get(
'NSXT_TIER0_ROUTER_UUID'),
'default_edge_cluster_uuid/value': os.environ.get(
'NSXT_EDGE_CLUSTER_UUID'),
'uplink_profile_uuid/value': os.environ.get('NSXT_UPLINK_PROFILE_UUID'),
'controller_ip_pool_uuid/value': os.environ.get(
'NSXT_CONTROLLER_IP_POOL_UUID'),
'controller_pnics_pairs/value': os.environ.get(
'NSXT_CONTROLLER_PNICS_PAIRS'),
'compute_ip_pool_uuid/value': os.environ.get('NSXT_COMPUTE_IP_POOL_UUID'),
'compute_pnics_pairs/value': os.environ.get('NSXT_COMPUTE_PNICS_PAIRS'),
'floating_ip_range/value': os.environ.get('NSXT_FLOATING_IP_RANGE'),
'floating_net_cidr/value': os.environ.get('NSXT_FLOATING_NET_CIDR'),
'internal_net_cidr/value': os.environ.get('NSXT_INTERNAL_NET_CIDR'),
'floating_net_gw/value': os.environ.get('NSXT_FLOATING_NET_GW'),
'internal_net_dns/value': os.environ.get('NSXT_INTERNAL_NET_DNS')
}

View File

@ -0,0 +1,54 @@
"""Copyright 2016 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
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.
"""
from functools import wraps
from fuelweb_test import logger
def find_first(seq, predicate):
"""Find the first item of sequence for which predicate is performed."""
return next((x for x in seq if predicate(x)), None)
class ShowPos(object):
"""Print func name and its parameters for each call."""
@staticmethod
def deco(f):
"""Logger decorator."""
def wrapper(*args, **kwargs):
logger.debug("Call {0}({1}, {2})".format(f.__name__, args, kwargs))
return f(*args, **kwargs)
return wrapper
def __getattribute__(self, name):
"""Log by attributes."""
attr = object.__getattribute__(self, name)
if callable(attr):
return ShowPos.deco(attr)
else:
return attr
def show_pos(f):
"""Wrapper shows current POSition in debug output."""
@wraps(f)
def wrapper(*args, **kwargs):
logger.debug('Call {func}({args}, {kwargs})'.format(func=f.__name__,
args=args,
kwargs=kwargs))
return f(*args, **kwargs)
return wrapper

65
plugin_test/run_tests.py Normal file
View File

@ -0,0 +1,65 @@
"""Copyright 2016 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
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 re
import sys
from nose.plugins import Plugin
from paramiko.transport import _join_lingering_threads
class CloseSSHConnectionsPlugin(Plugin):
"""Closes all paramiko's ssh connections after each test case.
Plugin fixes proboscis disability to run cleanup of any kind.
'afterTest' calls _join_lingering_threads function from paramiko,
which stops all threads (set the state to inactive and join for 10s)
"""
name = 'closesshconnections'
def options(self, parser, env=os.environ):
super(CloseSSHConnectionsPlugin, self).options(parser, env=env)
def configure(self, options, conf):
super(CloseSSHConnectionsPlugin, self).configure(options, conf)
self.enabled = True
def afterTest(self, *args, **kwargs):
_join_lingering_threads()
def import_tests():
from tests import test_plugin_nsxt # noqa
def run_tests():
from proboscis import TestProgram # noqa
import_tests()
# Run Proboscis and exit.
TestProgram(addplugins=[CloseSSHConnectionsPlugin()]).run_and_exit()
if __name__ == '__main__':
sys.path.append(sys.path[0] + "/fuel-qa")
import_tests()
from fuelweb_test.helpers.patching import map_test
if any(re.search(r'--group=patching_master_tests', arg)
for arg in sys.argv):
map_test('master')
elif any(re.search(r'--group=patching.*', arg) for arg in sys.argv):
map_test('environment')
run_tests()

View File

@ -0,0 +1,209 @@
---
template:
devops_settings:
aliases:
dynamic_address_pool:
- &pool_default !os_env POOL_DEFAULT, 10.109.0.0/16:24
default_interface_model:
- &interface_model !os_env INTERFACE_MODEL, e1000
rack-01-slave-interfaces: &rack-01-slave-interfaces
- label: eth0
l2_network_device: admin # Libvirt bridge name. It is *NOT* Nailgun networks
interface_model: *interface_model
- label: eth1
l2_network_device: public
interface_model: *interface_model
- label: eth2
l2_network_device: management
interface_model: *interface_model
- label: eth3
l2_network_device: private
interface_model: *interface_model
- label: eth4
l2_network_device: storage
interface_model: *interface_model
rack-01-slave-network_config: &rack-01-slave-network_config
eth0:
networks:
- fuelweb_admin
eth1:
networks:
- public
eth2:
networks:
- management
eth3:
networks:
- private
eth4:
networks:
- storage
rack-01-slave-node-params: &rack-01-slave-node-params
vcpu: !os_env SLAVE_NODE_CPU, 4
memory: !os_env SLAVE_NODE_MEMORY, 8192
boot:
- network
- hd
volumes:
- name: system
capacity: !os_env NODE_VOLUME_SIZE, 55
format: qcow2
- name: cinder
capacity: !os_env NODE_VOLUME_SIZE, 55
format: qcow2
- name: swift
capacity: !os_env NODE_VOLUME_SIZE, 55
format: qcow2
interfaces: *rack-01-slave-interfaces
network_config: *rack-01-slave-network_config
rack-02-slave-node-params: &rack-02-slave-node-params
vcpu: !os_env SLAVE_NODE_CPU, 2
memory: !os_env SLAVE_NODE_MEMORY, 3072
boot:
- network
- hd
volumes:
- name: system
capacity: !os_env NODE_VOLUME_SIZE, 55
format: qcow2
- name: cinder
capacity: !os_env NODE_VOLUME_SIZE, 55
format: qcow2
- name: swift
capacity: !os_env NODE_VOLUME_SIZE, 55
format: qcow2
interfaces: *rack-01-slave-interfaces
network_config: *rack-01-slave-network_config
env_name: !os_env ENV_NAME
address_pools:
# Network pools used by the environment
fuelweb_admin-pool01:
net: *pool_default
params:
tag: 0
public-pool01:
net: *pool_default
params:
tag: 0
storage-pool01:
net: *pool_default
params:
tag: 101
management-pool01:
net: *pool_default
params:
tag: 102
private-pool01:
net: *pool_default
params:
tag: 103
groups:
- name: cat
driver:
name: devops.driver.libvirt.libvirt_driver
params:
connection_string: !os_env CONNECTION_STRING, qemu:///system
storage_pool_name: !os_env STORAGE_POOL_NAME, default
stp: True
hpet: False
use_host_cpu: !os_env DRIVER_USE_HOST_CPU, true
network_pools: # Address pools for OpenStack networks.
# Actual names should be used for keys
# (the same as in Nailgun, for example)
fuelweb_admin: fuelweb_admin-pool01
public: public-pool01
storage: storage-pool01
management: management-pool01
private: private-pool01
l2_network_devices: # Libvirt bridges. It is *NOT* Nailgun networks
admin:
address_pool: fuelweb_admin-pool01
dhcp: false
forward:
mode: nat
public:
address_pool: public-pool01
dhcp: false
forward:
mode: nat
storage:
address_pool: storage-pool01
dhcp: false
management:
address_pool: management-pool01
dhcp: false
private:
address_pool: private-pool01
dhcp: false
nodes:
- name: admin # Custom name of VM for Fuel admin node
role: fuel_master # Fixed role for Fuel master node properties
params:
vcpu: !os_env ADMIN_NODE_CPU, 2
memory: !os_env ADMIN_NODE_MEMORY, 8192
boot:
- hd
- cdrom # for boot from usb - without 'cdrom'
volumes:
- name: system
capacity: !os_env ADMIN_NODE_VOLUME_SIZE, 80
format: qcow2
- name: iso
source_image: !os_env ISO_PATH # if 'source_image' set, then volume capacity is calculated from it's size
format: raw
device: cdrom # for boot from usb - 'disk'
bus: ide # for boot from usb - 'usb'
interfaces:
- label: eth0
l2_network_device: admin # Libvirt bridge name. It is *NOT* a Nailgun network
interface_model: *interface_model
network_config:
eth0:
networks:
- fuelweb_admin
- name: slave-01
role: fuel_slave
params: *rack-01-slave-node-params
- name: slave-02
role: fuel_slave
params: *rack-01-slave-node-params
- name: slave-03
role: fuel_slave
params: *rack-01-slave-node-params
- name: slave-04
role: fuel_slave
params: *rack-02-slave-node-params
- name: slave-05
role: fuel_slave
params: *rack-02-slave-node-params
- name: slave-06
role: fuel_slave
params: *rack-02-slave-node-params
- name: slave-07
role: fuel_slave
params: *rack-02-slave-node-params
- name: slave-08
role: fuel_slave
params: *rack-02-slave-node-params
- name: slave-09
role: fuel_slave
params: *rack-02-slave-node-params

View File

@ -0,0 +1,14 @@
"""Copyright 2016 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
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.
"""

View File

@ -0,0 +1,98 @@
"""Copyright 2016 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
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
from proboscis.asserts import assert_true
from fuelweb_test import logger
from fuelweb_test.helpers import utils
from fuelweb_test.helpers.utils import pretty_log
from fuelweb_test.tests.base_test_case import TestBasic
from helpers import settings
class TestNSXtBase(TestBasic):
"""Base class for NSX-T plugin tests"""
def __init__(self):
super(TestNSXtBase, self).__init__()
self.default = settings
def install_nsxt_plugin(self):
"""Download and install NSX-T plugin on master node.
:return: None
"""
master_ip = self.ssh_manager.admin_ip
utils.upload_tarball(ip=master_ip,
tar_path=self.default.NSXT_PLUGIN_PATH,
tar_target='/var')
utils.install_plugin_check_code(
ip=master_ip,
plugin=os.path.basename(self.default.NSXT_PLUGIN_PATH))
def enable_plugin(self, cluster_id, settings=None):
"""Enable NSX-T plugin on cluster.
:param cluster_id: cluster id
:param settings: settings in dict format
:return: None
"""
msg = "Plugin couldn't be enabled. Check plugin version. Test aborted"
settings = settings if settings else {}
checker = self.fuel_web.check_plugin_exists(cluster_id,
self.default.PLUGIN_NAME)
assert_true(checker, msg)
logger.info('Configure cluster with '
'following parameters: \n{}'.format(pretty_log(settings)))
self.fuel_web.update_plugin_settings(
cluster_id,
self.default.PLUGIN_NAME,
self.default.NSXT_PLUGIN_VERSION,
dict(self.default.plugin_configuration, **settings))
def reconfigure_cluster_interfaces(self, cluster_id):
# clear network mapping enp0s6 for all deployed nodes
nodes = self.fuel_web.client.list_cluster_nodes(cluster_id)
for node in nodes:
self.fuel_web.update_node_networks(node['id'],
settings.assigned_networks)
def delete_nsxt_plugin(self, failover=False):
"""Delete NSX-T plugin
:param failover: True if we expect that plugin won't be deleted
:return:
"""
plugin_name = self.default.PLUGIN_NAME
plugin_vers = self.default.NSXT_PLUGIN_VERSION
tmp = "Plugin '{0}' {1} removed"
msg = tmp.format(plugin_name, 'was' if failover else "wasn't")
cmd = 'fuel plugins --remove {0}=={1}'.format(plugin_name, plugin_vers)
self.ssh_manager.check_call(
ip=self.ssh_manager.admin_ip,
command=cmd,
expected=[1 if failover else 0],
raise_on_err=not failover
)
output = self.ssh_manager.check_call(
ip=self.ssh_manager.admin_ip,
command='fuel2 plugins list -f value -c name'
).stdout[-1].split(' ')
assert_true(plugin_name in output != failover, msg)

View File

@ -0,0 +1,204 @@
"""Copyright 2016 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
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.
"""
from proboscis import test
from proboscis.asserts import assert_true
from fuelweb_test.helpers.decorators import log_snapshot_after_test
from fuelweb_test.settings import DEPLOYMENT_MODE
from fuelweb_test.tests.base_test_case import SetupEnvironment
from tests.base_plugin_test import TestNSXtBase
@test(groups=["plugins", "nsxt_plugin", 'nsxt_smoke_scenarios'])
class TestNSXtSmoke(TestNSXtBase):
"""Tests from test plan that have been marked as 'Automated'."""
@test(depends_on=[SetupEnvironment.prepare_slaves_1],
groups=["nsxt_install", 'nsxt_smoke'])
@log_snapshot_after_test
def nsxt_install(self):
"""Check that plugin can be installed.
Scenario:
1. Connect to the Fuel master node via ssh.
2. Upload NSX-T plugin.
3. Install NSX-T plugin.
4. Run command 'fuel plugins'.
5. Check name, version and package version of plugin.
Duration 30 min
"""
self.env.revert_snapshot('ready_with_1_slaves')
self.show_step(1)
self.show_step(2)
self.show_step(3)
self.install_nsxt_plugin()
self.show_step(4)
output = self.ssh_manager.execute_on_remote(
ip=self.ssh_manager.admin_ip, cmd='fuel plugins list'
)['stdout'].pop().split(' ')
self.show_step(5)
msg = "Plugin '{0}' is not installed.".format(self.default.PLUGIN_NAME)
# check name
assert_true(self.default.PLUGIN_NAME in output, msg)
# check version
assert_true(self.default.NSXT_PLUGIN_VERSION in output, msg)
self.env.make_snapshot("nsxt_install", is_make=True)
@test(depends_on=[nsxt_install],
groups=["nsxt_uninstall", 'nsxt_smoke'])
@log_snapshot_after_test
def nsxt_uninstall(self):
"""Check that NSX-T plugin can be removed.
Scenario:
1. Revert to snapshot nsxt_install
2. Remove NSX-T plugin.
3. Run command 'fuel plugins' to ensure the NSX-T plugin has
been removed.
Duration: 5 min
"""
self.show_step(1)
self.env.revert_snapshot("nsxt_install")
self.show_step(2)
cmd = 'fuel plugins --remove {0}=={1}'.format(
self.default.PLUGIN_NAME, self.default.NSXT_PLUGIN_VERSION)
self.ssh_manager.execute_on_remote(
ip=self.ssh_manager.admin_ip,
cmd=cmd,
err_msg='Can not remove plugin.')
self.show_step(3)
self.delete_nsxt_plugin()
@test(depends_on=[nsxt_install],
groups=['nsxt_kvm_smoke', 'nsxt_smoke'])
@log_snapshot_after_test
def nsxt_kvm_smoke(self):
"""Deploy a cluster with NSXt Plugin.
Scenario:
1. Upload the plugin to master node.
2. Create cluster.
3. Provision one controller node.
4. Configure NSXt for that cluster.
5. Deploy cluster with plugin.
6. Run 'smoke' OSTF.
Duration 90 min
"""
self.show_step(1)
self.env.revert_snapshot('nsxt_install')
self.show_step(2)
cluster_id = self.fuel_web.create_cluster(
name=self.__class__.__name__,
mode=DEPLOYMENT_MODE,
settings=self.default.cluster_settings,
configure_ssl=False)
self.show_step(3)
self.fuel_web.update_nodes(cluster_id, {'slave-01': ['controller']})
self.reconfigure_cluster_interfaces(cluster_id)
self.show_step(4)
self.enable_plugin(cluster_id)
self.show_step(5)
self.fuel_web.deploy_cluster_wait(cluster_id)
self.show_step(6)
self.fuel_web.run_ostf(cluster_id=cluster_id, test_sets=['smoke'])
@test(groups=["plugins", "nsxt_plugin", 'nsxt_bvt_scenarios'])
class TestNSXtBVT(TestNSXtBase):
"""NSX-t BVT scenarios"""
@test(depends_on=[SetupEnvironment.prepare_slaves_9],
groups=["nsxt_bvt"])
@log_snapshot_after_test
def nsxt_bvt(self):
"""Deploy cluster with plugin and vmware datastore backend.
Scenario:
1. Upload plugins to the master node.
2. Create cluster with vcenter.
3. Add 3 node with controller role, 3 ceph,
compute-vmware + cinder-vmware, compute.
4. Configure vcenter.
5. Configure NSXt for that cluster.
6. Deploy cluster.
7. Run OSTF.
Duration 3 hours
"""
self.env.revert_snapshot("ready_with_9_slaves")
self.show_step(1)
self.install_nsxt_plugin()
self.show_step(2)
settings = self.default.cluster_settings
settings["images_ceph"] = True
cluster_id = self.fuel_web.create_cluster(
name=self.__class__.__name__,
mode=DEPLOYMENT_MODE,
settings=settings,
configure_ssl=False)
self.show_step(3)
self.fuel_web.update_nodes(
cluster_id,
{'slave-01': ['controller'],
'slave-02': ['controller'],
'slave-03': ['controller'],
'slave-04': ['ceph-osd'],
'slave-05': ['ceph-osd'],
'slave-06': ['ceph-osd'],
'slave-07': ['compute-vmware', 'cinder-vmware'],
'slave-08': ['compute']}
)
self.reconfigure_cluster_interfaces(cluster_id)
self.show_step(4)
target_node_2 = \
self.fuel_web.get_nailgun_node_by_name('slave-07')['hostname']
self.fuel_web.vcenter_configure(cluster_id,
multiclusters=True,
target_node_2=target_node_2)
self.show_step(5)
self.enable_plugin(cluster_id)
self.show_step(6)
self.fuel_web.deploy_cluster_wait(cluster_id)
self.show_step(7)
self.fuel_web.run_ostf(
cluster_id=cluster_id, test_sets=['smoke', 'sanity', 'ha'])

View File

@ -0,0 +1,660 @@
#!/bin/sh
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
INVALIDOPTS_ERR=100
NOJOBNAME_ERR=101
NOISOPATH_ERR=102
NOTASKNAME_ERR=103
NOWORKSPACE_ERR=104
NOISOFOUND_ERR=107
CDWORKSPACE_ERR=110
ISODOWNLOAD_ERR=111
INVALIDTASK_ERR=112
# Defaults
export REBOOT_TIMEOUT=${REBOOT_TIMEOUT:-5000}
export ALWAYS_CREATE_DIAGNOSTIC_SNAPSHOT=${ALWAYS_CREATE_DIAGNOSTIC_SNAPSHOT:-true}
ShowHelp() {
cat << EOF
System Tests Script
It can perform several actions depending on Jenkins JOB_NAME it's ran from
or it can take names from exported environment variables or command line options
if you do need to override them.
-w (dir) - Path to workspace where fuelweb git repository was checked out.
Uses Jenkins' WORKSPACE if not set
-e (name) - Directly specify environment name used in tests
Uses ENV_NAME variable is set.
-j (name) - Name of this job. Determines ISO name, Task name and used by tests.
Uses Jenkins' JOB_NAME if not set
-v - Do not use virtual environment
-V (dir) - Path to python virtual environment
-i (file) - Full path to ISO file to build or use for tests.
Made from iso dir and name if not set.
-t (name) - Name of task this script should perform. Should be one of defined ones.
Taken from Jenkins' job's suffix if not set.
-o (str) - Allows you any extra command line option to run test job if you
want to use some parameters.
-a (str) - Allows you to path NOSE_ATTR to the test job if you want
to use some parameters.
-A (str) - Allows you to path NOSE_EVAL_ATTR if you want to enter attributes
as python expressions.
-m (name) - Use this mirror to build ISO from.
Uses 'srt' if not set.
-U - ISO URL for tests.
Null by default.
-r (yes/no) - Should built ISO file be placed with build number tag and
symlinked to the last build or just copied over the last file.
-b (num) - Allows you to override Jenkins' build number if you need to.
-l (dir) - Path to logs directory. Can be set by LOGS_DIR evironment variable.
Uses WORKSPACE/logs if not set.
-d - Dry run mode. Only show what would be done and do nothing.
Useful for debugging.
-k - Keep previously created test environment before tests run
-K - Keep test environment after tests are finished
-h - Show this help page
Most variables uses guesses from Jenkins' job name but can be overriden
by exported variable before script is run or by one of command line options.
You can override following variables using export VARNAME="value" before running this script
WORKSPACE - path to directory where Fuelweb repository was checked out by Jenkins or manually
JOB_NAME - name of Jenkins job that determines which task should be done and ISO file name.
If task name is "iso" it will make iso file
Other defined names will run Nose tests using previously built ISO file.
ISO file name is taken from job name prefix
Task name is taken from job name suffix
Separator is one dot '.'
For example if JOB_NAME is:
mytest.somestring.iso
ISO name: mytest.iso
Task name: iso
If ran with such JOB_NAME iso file with name mytest.iso will be created
If JOB_NAME is:
mytest.somestring.node
ISO name: mytest.iso
Task name: node
If script was run with this JOB_NAME node tests will be using ISO file mytest.iso.
First you should run mytest.somestring.iso job to create mytest.iso.
Then you can ran mytest.somestring.node job to start tests using mytest.iso and other tests too.
EOF
}
GlobalVariables() {
# where built iso's should be placed
# use hardcoded default if not set before by export
ISO_DIR="${ISO_DIR:=/var/www/fuelweb-iso}"
# name of iso file
# taken from jenkins job prefix
# if not set before by variable export
if [ -z "${ISO_NAME}" ]; then
ISO_NAME="${JOB_NAME%.*}.iso"
fi
# full path where iso file should be placed
# make from iso name and path to iso shared directory
# if was not overriden by options or export
if [ -z "${ISO_PATH}" ]; then
ISO_PATH="${ISO_DIR}/${ISO_NAME}"
fi
# what task should be ran
# it's taken from jenkins job name suffix if not set by options
if [ -z "${TASK_NAME}" ]; then
TASK_NAME="${JOB_NAME##*.}"
fi
# do we want to keep iso's for each build or just copy over single file
ROTATE_ISO="${ROTATE_ISO:=yes}"
# choose mirror to build iso from. Default is 'srt' for Saratov's mirror
# you can change mirror by exporting USE_MIRROR variable before running this script
USE_MIRROR="${USE_MIRROR:=srt}"
# only show what commands would be executed but do nothing
# this feature is useful if you want to debug this script's behaviour
DRY_RUN="${DRY_RUN:=no}"
VENV="${VENV:=yes}"
}
GetoptsVariables() {
while getopts ":w:j:i:t:o:a:A:m:U:r:b:V:l:dkKe:v:h" opt; do
case $opt in
w)
WORKSPACE="${OPTARG}"
;;
j)
JOB_NAME="${OPTARG}"
;;
i)
ISO_PATH="${OPTARG}"
;;
t)
TASK_NAME="${OPTARG}"
;;
o)
TEST_OPTIONS="${TEST_OPTIONS} ${OPTARG}"
;;
a)
NOSE_ATTR="${OPTARG}"
;;
A)
NOSE_EVAL_ATTR="${OPTARG}"
;;
m)
USE_MIRROR="${OPTARG}"
;;
U)
ISO_URL="${OPTARG}"
;;
r)
ROTATE_ISO="${OPTARG}"
;;
V)
VENV_PATH="${OPTARG}"
;;
l)
LOGS_DIR="${OPTARG}"
;;
k)
KEEP_BEFORE="yes"
;;
K)
KEEP_AFTER="yes"
;;
e)
ENV_NAME="${OPTARG}"
;;
d)
DRY_RUN="yes"
;;
v)
VENV="no"
;;
h)
ShowHelp
exit 0
;;
\?)
echo "Invalid option: -$OPTARG"
ShowHelp
exit $INVALIDOPTS_ERR
;;
:)
echo "Option -$OPTARG requires an argument."
ShowHelp
exit $INVALIDOPTS_ERR
;;
esac
done
}
CheckVariables() {
if [ -z "${JOB_NAME}" ]; then
echo "Error! JOB_NAME is not set!"
exit $NOJOBNAME_ERR
fi
if [ -z "${ISO_PATH}" ]; then
echo "Error! ISO_PATH is not set!"
exit $NOISOPATH_ERR
fi
if [ -z "${TASK_NAME}" ]; then
echo "Error! TASK_NAME is not set!"
exit $NOTASKNAME_ERR
fi
if [ -z "${WORKSPACE}" ]; then
echo "Error! WORKSPACE is not set!"
exit $NOWORKSPACE_ERR
fi
if [ -z "${POOL_PUBLIC}" ]; then
export POOL_PUBLIC='172.16.0.0/24:24'
fi
if [ -z "${POOL_MANAGEMENT}" ]; then
export POOL_MANAGEMENT='172.16.1.0/24:24'
fi
if [ -z "${POOL_PRIVATE}" ]; then
export POOL_PRIVATE='192.168.0.0/24:24'
fi
# vCenter variables
if [ -z "${DISABLE_SSL}" ]; then
export DISABLE_SSL="true"
fi
if [ -z "${VCENTER_USE}" ]; then
export VCENTER_USE="true"
fi
if [ -z "${VCENTER_IP}" ]; then
export VCENTER_IP="172.16.0.254"
fi
if [ -z "${VCENTER_USERNAME}" ]; then
export VCENTER_USERNAME="administrator@vsphere.local"
fi
if [ -z "${VCENTER_PASSWORD}" ]; then
echo "Error! VCENTER_PASSWORD is not set!"
exit 1
fi
if [ -z "${VC_DATACENTER}" ]; then
export VC_DATACENTER="Datacenter"
fi
if [ -z "${VC_DATASTORE}" ]; then
export VC_DATASTORE="nfs"
fi
if [ -z "${VCENTER_IMAGE_DIR}" ]; then
export VCENTER_IMAGE_DIR="/openstack_glance"
fi
if [ -z "${WORKSTATION_NODES}" ]; then
export WORKSTATION_NODES="esxi1 esxi2 esxi3 vcenter trusty nsx-edge"
fi
if [ -z "${WORKSTATION_IFS}" ]; then
export WORKSTATION_IFS="vmnet1 vmnet2 vmnet5"
fi
if [ -z "${VCENTER_CLUSTERS}" ]; then
export VCENTER_CLUSTERS="Cluster1,Cluster2"
fi
if [ -z "${WORKSTATION_SNAPSHOT}" ]; then
echo "Error! WORKSTATION_SNAPSHOT is not set!"
exit 1
fi
if [ -z "${WORKSTATION_USERNAME}" ]; then
echo "Error! WORKSTATION_USERNAME is not set!"
exit 1
fi
if [ -z "${WORKSTATION_PASSWORD}" ]; then
echo "Error! WORKSTATION_PASSWORD is not set!"
exit 1
fi
# NSXt variables
if [ -z "${NSXT_PLUGIN_PATH}" ]; then
echo "Error! NSXT_PLUGIN_PATH is not set!"
exit 1
fi
if [ -z "${NEUTRON_SEGMENT_TYPE}" ]; then
export NEUTRON_SEGMENT_TYPE="tun"
fi
if [ -z "${NSXT_INSECURE}" ]; then
export NSXT_INSECURE='true'
fi
if [ -z "${NSXT_MANAGERS_IP}" ]; then
export NSXT_MANAGERS_IP="172.16.0.249"
fi
if [ -z "${NSXT_USER}" ]; then
export NSXT_USER='admin'
fi
if [ -z "${NSXT_PASSWORD}" ]; then
echo "Error! NSXT_PASSWORD is not set!"
exit 1
fi
if [ -z "${NSXT_OVERLAY_TZ_UUID}" ]; then
export NSXT_OVERLAY_TZ_UUID='0eeb1b85-c826-403d-8762-6a9c23a4f132'
fi
if [ -z "${NSXT_VLAN_TZ_UUID}" ]; then
export NSXT_VLAN_TZ_UUID='8efe20d2-e71a-4d6e-acdd-f78a2ec2e90c'
fi
if [ -z "${NSXT_TIER0_ROUTER_UUID}" ]; then
export NSXT_TIER0_ROUTER_UUID='606acd01-c5f8-40ea-ae20-9a91eb7ebcb4'
fi
if [ -z "${NSXT_EDGE_CLUSTER_UUID}" ]; then
export NSXT_EDGE_CLUSTER_UUID='c53d602a-4010-47cc-a8b1-4ef11d0a3edd'
fi
if [ -z "${NSXT_UPLINK_PROFILE_UUID}" ]; then
export NSXT_UPLINK_PROFILE_UUID='99864272-b34f-46a5-89c8-5657fa7042ea'
fi
if [ -z "${NSXT_CONTROLLER_IP_POOL_UUID}" ]; then
export NSXT_CONTROLLER_IP_POOL_UUID='2e06fcb2-7c5b-4515-a7a9-98809c7b863a'
fi
if [ -z "${NSXT_CONTROLLER_PNICS_PAIRS}" ]; then
export NSXT_CONTROLLER_PNICS_PAIRS='enp0s6:uplink'
fi
if [ -z "${NSXT_COMPUTE_IP_POOL_UUID}" ]; then
export NSXT_COMPUTE_IP_POOL_UUID='2e06fcb2-7c5b-4515-a7a9-98809c7b863a'
fi
if [ -z "${NSXT_COMPUTE_PNICS_PAIRS}" ]; then
export NSXT_COMPUTE_PNICS_PAIRS='enp0s6:uplink'
fi
if [ -z "${NSXT_FLOATING_IP_RANGE}" ]; then
export NSXT_FLOATING_IP_RANGE='172.16.212.2-172.16.212.40'
fi
if [ -z "${NSXT_FLOATING_NET_CIDR}" ]; then
export NSXT_FLOATING_NET_CIDR='172.16.212.0/24'
fi
if [ -z "${NSXT_ROUTING_NET_CIDR}" ]; then
export NSXT_ROUTING_NET_CIDR='172.16.214.0/30'
fi
if [ -z "${NSXT_FLOATING_NET_GW}" ]; then
export NSXT_FLOATING_NET_GW='172.16.212.1'
fi
if [ -z "${NSXT_INTERNAL_NET_CIDR}" ]; then
export NSXT_INTERNAL_NET_CIDR='192.168.251.0/24'
fi
if [ -z "${NSXT_INTERNAL_NET_DNS}" ]; then
export NSXT_INTERNAL_NET_DNS='8.8.8.8'
fi
if [ ! -f "${DEVOPS_SETTINGS_TEMPLATE}" ]; then
if [ -z "${NODE_VOLUME_SIZE}" ]; then
export NODE_VOLUME_SIZE=350
fi
if [ -z "${ADMIN_NODE_MEMORY}" ]; then
export ADMIN_NODE_MEMORY=4096
fi
if [ -z "${ADMIN_NODE_CPU}" ]; then
export ADMIN_NODE_CPU=4
fi
if [ -z "${SLAVE_NODE_MEMORY}" ]; then
export SLAVE_NODE_MEMORY=4096
fi
if [ -z "${SLAVE_NODE_CPU}" ]; then
export SLAVE_NODE_CPU=4
fi
fi
}
CdWorkSpace() {
# chdir into workspace or fail if could not
if [ "${DRY_RUN}" != "yes" ]; then
cd "${WORKSPACE}"
ec=$?
if [ "${ec}" -gt "0" ]; then
echo "Error! Cannot cd to WORKSPACE!"
exit $CDWORKSPACE_ERR
fi
else
echo cd "${WORKSPACE}"
fi
}
RunTest() {
# Run test selected by task name
# check if iso file exists
if [ ! -f "${ISO_PATH}" ]; then
if [ -z "${ISO_URL}" -a "${DRY_RUN}" != "yes" ]; then
echo "Error! File ${ISO_PATH} not found and no ISO_URL (-U key) for downloading!"
exit $NOISOFOUND_ERR
else
if [ "${DRY_RUN}" = "yes" ]; then
echo wget -c ${ISO_URL} -O ${ISO_PATH}
else
echo "No ${ISO_PATH} found. Trying to download file."
wget -c ${ISO_URL} -O ${ISO_PATH}
rc=$?
if [ $rc -ne 0 ]; then
echo "Failed to fetch ISO from ${ISO_URL}"
exit $ISODOWNLOAD_ERR
fi
fi
fi
fi
if [ -z "${VENV_PATH}" ]; then
VENV_PATH="/home/jenkins/venv-nailgun-tests"
fi
# run python virtualenv
if [ "${VENV}" = "yes" ]; then
if [ "${DRY_RUN}" = "yes" ]; then
echo . $VENV_PATH/bin/activate
else
. $VENV_PATH/bin/activate
fi
fi
if [ "${ENV_NAME}" = "" ]; then
ENV_NAME="${JOB_NAME}_system_test"
fi
if [ "${LOGS_DIR}" = "" ]; then
LOGS_DIR="${WORKSPACE}/logs"
fi
if [ ! -f "$LOGS_DIR" ]; then
mkdir -p $LOGS_DIR
fi
export ENV_NAME
export LOGS_DIR
export ISO_PATH
if [ "${KEEP_BEFORE}" != "yes" ]; then
# remove previous environment
if [ "${DRY_RUN}" = "yes" ]; then
echo dos.py erase "${ENV_NAME}"
else
if dos.py list | grep -q "^${ENV_NAME}\$" ; then
dos.py erase "${ENV_NAME}"
fi
fi
fi
# gather additional option for this nose test run
OPTS=""
if [ -n "${NOSE_ATTR}" ]; then
OPTS="${OPTS} -a ${NOSE_ATTR}"
fi
if [ -n "${NOSE_EVAL_ATTR}" ]; then
OPTS="${OPTS} -A ${NOSE_EVAL_ATTR}"
fi
if [ -n "${TEST_OPTIONS}" ]; then
OPTS="${OPTS} ${TEST_OPTIONS}"
fi
clean_old_bridges
# run python test set to create environments, deploy and test product
if [ "${DRY_RUN}" = "yes" ]; then
echo export PYTHONPATH="${PYTHONPATH:+${PYTHONPATH}:}${WORKSPACE}"
echo python plugin_test/run_tests.py -q --nologcapture --with-xunit ${OPTS}
else
export PYTHONPATH="${PYTHONPATH:+${PYTHONPATH}:}${WORKSPACE}"
echo ${PYTHONPATH}
python plugin_test/run_tests.py -q --nologcapture --with-xunit ${OPTS} &
fi
SYSTEST_PID=$!
if ! ps -p $SYSTEST_PID > /dev/null
then
echo System tests exited prematurely, aborting
exit 1
fi
while [ "$(virsh net-list | grep -c $ENV_NAME)" -ne 5 ];do sleep 10
if ! ps -p $SYSTEST_PID > /dev/null
then
echo System tests exited prematurely, aborting
exit 1
fi
done
sleep 10
# Configre vcenter nodes and interfaces
setup_net $ENV_NAME
clean_iptables
setup_stt $ENV_NAME
setup_external_net
revert_ws "$WORKSTATION_NODES" || { echo "killing $SYSTEST_PID and its childs" && pkill --parent $SYSTEST_PID && kill $SYSTEST_PID && exit 1; }
echo waiting for system tests to finish
wait $SYSTEST_PID
export RES=$?
echo ENVIRONMENT NAME is $ENV_NAME
virsh net-dumpxml ${ENV_NAME}_admin | grep -P "(\d+\.){3}" -o | awk '{print "Fuel master node IP: "$0"2"}'
if [ "${KEEP_AFTER}" != "yes" ]; then
# remove environment after tests
if [ "${DRY_RUN}" = "yes" ]; then
echo dos.py destroy "${ENV_NAME}"
else
dos.py destroy "${ENV_NAME}"
fi
fi
exit "${RES}"
}
RouteTasks() {
# this selector defines task names that are recognised by this script
# and runs corresponding jobs for them
# running any jobs should exit this script
case "${TASK_NAME}" in
test)
RunTest
;;
*)
echo "Unknown task: ${TASK_NAME}!"
exit $INVALIDTASK_ERR
;;
esac
exit 0
}
add_interface_to_bridge() {
env=$1
net_name=$2
nic=$3
ip=$4
for net in $(virsh net-list |grep ${env}_${net_name} |awk '{print $1}');do
bridge=$(virsh net-info $net |grep -i bridge |awk '{print $2}')
setup_bridge $bridge $nic $ip && echo $net_name bridge $bridge ready
done
}
setup_bridge() {
bridge=$1
nic=$2
ip=$3
sudo /sbin/brctl stp $bridge off
sudo /sbin/brctl addif $bridge $nic
# set if with existing ip down
for itf in $(sudo ip -o addr show to $ip | cut -d' ' -f2); do
echo deleting $ip from $itf
sudo ip addr del dev $itf $ip
done
echo adding $ip to $bridge
sudo /sbin/ip addr add $ip dev $bridge
echo $nic added to $bridge
sudo /sbin/ip link set dev $bridge up
if sudo /sbin/iptables-save |grep $bridge | grep -i reject| grep -q FORWARD; then
sudo /sbin/iptables -D FORWARD -o $bridge -j REJECT --reject-with icmp-port-unreachable
sudo /sbin/iptables -D FORWARD -i $bridge -j REJECT --reject-with icmp-port-unreachable
fi
}
clean_old_bridges() {
for intf in $WORKSTATION_IFS; do
for br in $(/sbin/brctl show | grep -v "bridge name" | cut -f1 -d' '); do
/sbin/brctl show $br| grep -q $intf && sudo /sbin/brctl delif $br $intf \
&& sudo /sbin/ip link set dev $br down && echo $intf deleted from $br
done
done
}
clean_iptables() {
sudo /sbin/iptables -F
sudo /sbin/iptables -t nat -F
sudo /sbin/iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
}
revert_ws() {
for i in $1
do
vmrun -T ws-shared -h https://localhost:443/sdk -u $WORKSTATION_USERNAME -p $WORKSTATION_PASSWORD listRegisteredVM | grep -q $i || { echo "VM $i does not exist"; continue; }
echo vmrun: reverting $i to $WORKSTATION_SNAPSHOT
vmrun -T ws-shared -h https://localhost:443/sdk -u $WORKSTATION_USERNAME -p $WORKSTATION_PASSWORD revertToSnapshot "[standard] $i/$i.vmx" $WORKSTATION_SNAPSHOT || { echo "Error: revert of $i failed"; return 1; }
done
for i in $1
do
echo vmrun: starting $i
vmrun -T ws-shared -h https://localhost:443/sdk -u $WORKSTATION_USERNAME -p $WORKSTATION_PASSWORD start "[standard] $i/$i.vmx" || { echo "Error: $i failed to start"; return 1; }
done
}
setup_net() {
env=$1
add_interface_to_bridge $env public vmnet1 172.16.0.1/24
}
setup_stt() {
set -e
env=$1
net_name='private'
nic='vmnet2'
for net in $(virsh net-list |grep ${env}_${net_name} | awk '{print $1}');do
bridge=$(virsh net-info $net | grep -i bridge | awk '{print $2}')
done
sudo /sbin/brctl stp $bridge off
sudo /sbin/brctl addif $bridge $nic
echo $nic added to $bridge
sudo /sbin/ip link set dev $bridge up
if sudo /sbin/iptables-save | grep $bridge | grep -i reject| grep -q FORWARD; then
sudo /sbin/iptables -D FORWARD -o $bridge -j REJECT --reject-with icmp-port-unreachable
sudo /sbin/iptables -D FORWARD -i $bridge -j REJECT --reject-with icmp-port-unreachable
fi
echo "Stt added to $net_name bridge $bridge"
}
setup_external_net() {
nic='vmnet5'
ip=${NSXT_ROUTING_NET_CIDR%\.*}.1
gw_ip=${NSXT_ROUTING_NET_CIDR%\.*}.2
mask=${NSXT_ROUTING_NET_CIDR##*\/}
#set if with existing ip down
for itf in $(sudo ip -o addr show to $ip | cut -d' ' -f2); do
echo deleting $ip from $itf
sudo ip addr del $ip/$mask dev $itf
done
for itf in $(sudo ip -o ro show to ${NSXT_FLOATING_NET_CIDR} | cut -d' ' -f5); do
echo deleting route to ${NSXT_FLOATING_NET_CIDR} dev $itf
sudo ip ro del ${NSXT_FLOATING_NET_CIDR} dev $itf
done
set -e
sudo /sbin/ip addr add ${ip}/${mask} dev $nic
sudo /sbin/ip ro add ${NSXT_FLOATING_NET_CIDR} via ${gw_ip}
echo "Routing net added to $nic"
}
# MAIN
# first we want to get variable from command line options
GetoptsVariables "${@}"
# then we define global variables and there defaults when needed
GlobalVariables
# check do we have all critical variables set
CheckVariables
# first we chdir into our working directory unless we dry run
CdWorkSpace
# finally we can choose what to do according to TASK_NAME
RouteTasks

View File

@ -1,29 +1,27 @@
# -*- coding: utf-8 -*-
#
# Fuel NSXv plugin documentation build configuration file, created by
# sphinx-quickstart on Fri Aug 14 12:14:29 2015.
#
# This file is execfile()d with the current directory set to its
# containing dir.
#
# Note that not all possible configuration values are present in this
# autogenerated file.
#
# All configuration values have a default; values that are commented out
# serve to show the default.
"""Copyright 2016 Mirantis, Inc.
import sys
import os
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
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.
"""
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#sys.path.insert(0, os.path.abspath('.'))
# sys.path.insert(0, os.path.abspath('.'))
# -- General configuration ------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
#needs_sphinx = '1.0'
# needs_sphinx = '1.0'
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
@ -37,7 +35,7 @@ templates_path = ['_templates']
source_suffix = '.rst'
# The encoding of source files.
#source_encoding = 'utf-8-sig'
# source_encoding = 'utf-8-sig'
# The master toctree document.
master_doc = 'index'
@ -57,13 +55,13 @@ release = '1.0.0'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#language = None
# language = None
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
#today = ''
# today = ''
# Else, today_fmt is used as the format for a strftime call.
#today_fmt = '%B %d, %Y'
# today_fmt = '%B %d, %Y'
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
@ -71,27 +69,27 @@ exclude_patterns = ['_build']
# The reST default role (used for this markup: `text`) to use for all
# documents.
#default_role = None
# default_role = None
# If true, '()' will be appended to :func: etc. cross-reference text.
#add_function_parentheses = True
# add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
#add_module_names = True
# add_module_names = True
# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
#show_authors = False
# show_authors = False
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
# A list of ignored prefixes for module index sorting.
#modindex_common_prefix = []
# modindex_common_prefix = []
# If true, keep warnings as "system message" paragraphs in the built documents.
#keep_warnings = False
# keep_warnings = False
# -- Options for HTML output ----------------------------------------------
@ -103,26 +101,26 @@ html_theme = 'default'
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
#html_theme_options = {}
# html_theme_options = {}
# Add any paths that contain custom themes here, relative to this directory.
#html_theme_path = []
# html_theme_path = []
# The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation".
#html_title = None
# html_title = None
# A shorter title for the navigation bar. Default is the same as html_title.
#html_short_title = None
# html_short_title = None
# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
#html_logo = None
# html_logo = None
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
#html_favicon = None
# html_favicon = None
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
@ -132,48 +130,48 @@ html_static_path = ['_static']
# Add any extra paths that contain custom files (such as robots.txt or
# .htaccess) here, relative to this directory. These files are copied
# directly to the root of the documentation.
#html_extra_path = []
# html_extra_path = []
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
#html_last_updated_fmt = '%b %d, %Y'
# html_last_updated_fmt = '%b %d, %Y'
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
#html_use_smartypants = True
# html_use_smartypants = True
# Custom sidebar templates, maps document names to template names.
#html_sidebars = {}
# html_sidebars = {}
# Additional templates that should be rendered to pages, maps page names to
# template names.
#html_additional_pages = {}
# html_additional_pages = {}
# If false, no module index is generated.
#html_domain_indices = True
# html_domain_indices = True
# If false, no index is generated.
#html_use_index = True
# html_use_index = True
# If true, the index is split into individual pages for each letter.
#html_split_index = False
# html_split_index = False
# If true, links to the reST sources are added to the pages.
#html_show_sourcelink = True
# html_show_sourcelink = True
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
#html_show_sphinx = True
# html_show_sphinx = True
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
#html_show_copyright = True
# html_show_copyright = True
# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it. The value of this option must be the
# base URL from which the finished HTML is served.
#html_use_opensearch = ''
# html_use_opensearch = ''
# This is the file name suffix for HTML files (e.g. ".xhtml").
#html_file_suffix = None
# html_file_suffix = None
# Output file base name for HTML help builder.
htmlhelp_basename = 'FuelNSXTplugindoc'
@ -183,13 +181,13 @@ htmlhelp_basename = 'FuelNSXTplugindoc'
latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
#'papersize': 'letterpaper',
# 'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
#'pointsize': '10pt',
# 'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
#'preamble': '',
# 'preamble': '',
}
# Grouping the document tree into LaTeX files. List of tuples
@ -202,23 +200,23 @@ latex_documents = [
# The name of an image file (relative to this directory) to place at the top of
# the title page.
#latex_logo = None
# latex_logo = None
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
#latex_use_parts = False
# latex_use_parts = False
# If true, show page references after internal links.
#latex_show_pagerefs = False
# latex_show_pagerefs = False
# If true, show URL addresses after external links.
#latex_show_urls = False
# latex_show_urls = False
# Documents to append as an appendix to all manuals.
#latex_appendices = []
# latex_appendices = []
# If false, no module index is generated.
#latex_domain_indices = True
# latex_domain_indices = True
# -- Options for manual page output ---------------------------------------
@ -231,7 +229,7 @@ man_pages = [
]
# If true, show URL addresses after external links.
#man_show_urls = False
# man_show_urls = False
# -- Options for Texinfo output -------------------------------------------
@ -246,13 +244,13 @@ texinfo_documents = [
]
# Documents to append as an appendix to all manuals.
#texinfo_appendices = []
# texinfo_appendices = []
# If false, no module index is generated.
#texinfo_domain_indices = True
# texinfo_domain_indices = True
# How to display URL addresses: 'footnote', 'no', or 'inline'.
#texinfo_show_urls = 'footnote'
# texinfo_show_urls = 'footnote'
# If true, do not generate a @detailmenu in the "Top" node's menu.
#texinfo_no_detailmenu = False
# texinfo_no_detailmenu = False