Remove Functional Tests

Functional Tests have not been known to not functional since Jan 2024 (https://review.opendev.org/c/openstack/python-ironicclient/+/430904)

The last time they were run in CI before that was in late Aug 2023. (https://review.opendev.org/c/openstack/python-ironicclient/+/891560)

This leaves a very large window for trying to figure out how they went wrong. They were made non-voting in Feb 2024 (https://review.opendev.org/c/openstack/python-ironicclient/+/908828), after which no real efforts were made to fix them.

This patch removes them entirely. For reference, the error as of Nov 1st 2024 when trying to run them is to do with auth.

"AttributeError: 'BaremetalXXXXTests' object has no attribute 'auth_ref'"

Change-Id: I50e8dbcef02ccad03c383a70618d8228db47b876
This commit is contained in:
Sharpz7 2024-11-05 20:40:11 +00:00
parent 2caa47fdf0
commit 051fd899f9
27 changed files with 2 additions and 2609 deletions

@ -1,3 +1,2 @@
[report]
include = ironicclient/*
omit = ironicclient/tests/functional/*

@ -12,7 +12,6 @@ extensions = ['sphinxcontrib.apidoc',
apidoc_module_dir = '../../ironicclient'
apidoc_output_dir = 'reference/api'
apidoc_excluded_paths = [
'tests/functional/*',
'tests']
apidoc_separate_modules = True
@ -54,7 +53,7 @@ pygments_style = 'native'
# A list of glob-style patterns that should be excluded when looking for
# source files. They are matched against the source file names relative to the
# source directory, using slashes as directory separators on all platforms.
exclude_patterns = ['api/ironicclient.tests.functional.*']
exclude_patterns = ['']
# -- Options for HTML output --------------------------------------------------

@ -34,34 +34,4 @@ chosen environments after a -e flag::
Functional Testing
..................
Functional testing assumes the existence of the script run_functional.sh in the
python-ironicclient/tools directory. The script run_functional.sh generates
test.conf file. To run functional tests just run ./run_functional.sh.
Also, the test.conf file could be created manually or generated from
environment variables. It assumes the existence of an openstack
cloud installation along with admin credentials. The test.conf file lives in
ironicclient/tests/functional/ directory. To run functional tests in that way
create test.conf manually and run::
$ tox -e functional
An example test.conf file::
[functional]
api_version = 1
os_auth_url=http://192.168.0.2:5000/v2.0/
os_username=admin
os_password=admin
os_project_name=admin
If you are testing ironic in standalone mode, only the parameters
'auth_strategy', 'os_auth_token' and 'ironic_url' are required;
all others will be ignored.
An example test.conf file for standalone host::
[functional]
auth_strategy = noauth
os_auth_token = fake
ironic_url = http://10.0.0.2:6385
Functional tests have been removed as of November 2024.

@ -1,440 +0,0 @@
# Copyright (c) 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
# 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 configparser
import os
from tempest.lib.cli import base
from tempest.lib.common.utils import data_utils
from tempest.lib import exceptions
import ironicclient.tests.functional.utils as utils
DEFAULT_CONFIG_FILE = os.path.join(os.path.dirname(__file__), 'test.conf')
class FunctionalTestBase(base.ClientTestBase):
"""Ironic base class, calls to ironicclient."""
def setUp(self):
super(FunctionalTestBase, self).setUp()
if not self.auth_ref.project_scoped:
raise Exception("Could not run functional tests, which are "
"run based on the scope provided for "
"authentication. Please provide a project "
"scope information.")
self.client = self._get_clients()
# NOTE(kromanenko) set ironic api version for portgroups
self.pg_api_ver = '--ironic-api-version 1.25'
def _get_clients(self):
# NOTE(aarefiev): {toxinidir} is a current working directory, so
# the tox env path is {toxinidir}/.tox
venv_name = os.environ.get('OS_TESTENV_NAME', 'functional')
cli_dir = os.path.join(os.path.abspath('.'), '.tox/%s/bin' % venv_name)
config = self._get_config()
if config.get('os_auth_url'):
client = base.CLIClient(cli_dir=cli_dir,
username=config['os_username'],
password=config['os_password'],
tenant_name=config.get('os_project_name'),
uri=config['os_auth_url'])
for keystone_object in 'user', 'project':
domain_attr = 'os_%s_domain_id' % keystone_object
if config.get(domain_attr):
setattr(self, domain_attr, config.get(domain_attr))
else:
self.ironic_url = config['ironic_url']
client = base.CLIClient(cli_dir=cli_dir,
ironic_url=self.ironic_url)
return client
def _get_config(self):
config_file = os.environ.get('IRONICCLIENT_TEST_CONFIG',
DEFAULT_CONFIG_FILE)
config = configparser.ConfigParser()
if not config.read(config_file):
self.skipTest('Skipping, no test config found @ %s' % config_file)
try:
auth_strategy = config.get('functional', 'auth_strategy')
except configparser.NoOptionError:
auth_strategy = 'keystone'
if auth_strategy not in ['keystone', 'noauth']:
raise self.fail(
'Invalid auth type specified: %s in functional must be '
'one of: [keystone, noauth]' % auth_strategy)
conf_settings = []
keystone_v3_conf_settings = []
if auth_strategy == 'keystone':
conf_settings += ['os_auth_url', 'os_username',
'os_password', 'os_project_name']
keystone_v3_conf_settings += ['os_user_domain_id',
'os_project_domain_id',
'os_identity_api_version',
'os_system_scope']
else:
conf_settings += ['ironic_url']
cli_flags = {}
for c in conf_settings + keystone_v3_conf_settings:
try:
setting_value = config.get('functional', c)
if setting_value is not None:
cli_flags[c] = setting_value
except configparser.NoOptionError:
# NOTE(TheJulia): Here we populate the options, and if we
# don't have an option, it is okay, The keystone client will
# do the actual validity check instead of us trying to have
# internal check logic, as there are several different forms
# and parameters which can be used.
pass
return cli_flags
def _cmd_no_auth(self, cmd, action, flags='', params=''):
"""Execute given command with noauth attributes.
:param cmd: command to be executed
:type cmd: string
:param action: command on cli to run
:type action: string
:param flags: optional cli flags to use
:type flags: string
:param params: optional positional args to use
:type params: string
"""
flags = ('--os-endpoint %(url)s %(flags)s'
%
{'url': self.ironic_url,
'flags': flags})
return base.execute(cmd, action, flags, params,
cli_dir=self.client.cli_dir)
def _ironic(self, action, cmd='ironic', flags='', params='',
merge_stderr=False):
"""Execute ironic command for the given action.
:param action: the cli command to run using Ironic
:type action: string
:param cmd: the base of cli command to run
:type action: string
:param flags: any optional cli flags to use
:type flags: string
:param params: any optional positional args to use
:type params: string
:param merge_stderr: whether to merge stderr into the result
:type merge_stderr: bool
"""
if cmd == 'openstack':
config = self._get_config()
id_api_version = config.get('os_identity_api_version')
if id_api_version:
flags += ' --os-identity-api-version {}'.format(id_api_version)
else:
flags += ' --os-endpoint-type publicURL'
if hasattr(self, 'ironic_url'):
if cmd == 'openstack':
flags += ' --os-auth-type none'
return self._cmd_no_auth(cmd, action, flags, params)
else:
for keystone_object in 'user', 'project':
domain_attr = 'os_%s_domain_id' % keystone_object
if (hasattr(self, domain_attr)
and getattr(self, domain_attr) is not None):
flags += ' --os-%(ks_obj)s-domain-id %(value)s' % {
'ks_obj': keystone_object,
'value': getattr(self, domain_attr)
}
return self.client.cmd_with_auth(
cmd, action, flags, params, merge_stderr=merge_stderr)
def ironic(self, action, flags='', params='', parse=True):
"""Return parsed list of dicts with basic item info.
:param action: the cli command to run using Ironic
:type action: string
:param flags: any optional cli flags to use
:type flags: string
:param params: any optional positional args to use
:type params: string
:param parse: return parsed list or raw output
:type parse: bool
"""
output = self._ironic(action=action, flags=flags, params=params)
return self.parser.listing(output) if parse else output
def get_table_headers(self, action, flags='', params=''):
output = self._ironic(action=action, flags=flags, params=params)
table = self.parser.table(output)
return table['headers']
def assertTableHeaders(self, field_names, table_headers):
"""Assert that field_names and table_headers are equal.
:param field_names: field names from the output table of the cmd
:param table_headers: table headers output from cmd
"""
self.assertEqual(sorted(field_names), sorted(table_headers))
def assertNodeStates(self, node_show, node_show_states):
"""Assert that node_show_states output corresponds to node_show output.
:param node_show: output from node-show cmd
:param node_show_states: output from node-show-states cmd
"""
for key in node_show_states.keys():
self.assertEqual(node_show_states[key], node_show[key])
def assertNodeValidate(self, node_validate):
"""Assert that all interfaces present are valid.
:param node_validate: output from node-validate cmd
"""
self.assertNotIn('False', [x['Result'] for x in node_validate])
def delete_node(self, node_id):
"""Delete node method works only with fake driver.
:param node_id: node uuid
:raises: CommandFailed exception when command fails to delete a node
"""
node_list = self.list_nodes()
if utils.get_object(node_list, node_id):
node_show = self.show_node(node_id)
if node_show['provision_state'] not in ('available',
'manageable',
'enroll'):
self.ironic('node-set-provision-state',
params='{0} deleted'.format(node_id))
if node_show['power_state'] not in ('None', 'off'):
self.ironic('node-set-power-state',
params='{0} off'.format(node_id))
self.ironic('node-delete', params=node_id)
node_list_uuid = self.get_nodes_uuids_from_node_list()
if node_id in node_list_uuid:
self.fail('Ironic node {0} has not been deleted!'
.format(node_id))
def create_node(self, driver='fake-hardware', params=''):
node = self.ironic('node-create',
params='--driver {0} {1}'.format(driver, params))
if not node:
self.fail('Ironic node has not been created!')
node = utils.get_dict_from_output(node)
self.addCleanup(self.delete_node, node['uuid'])
return node
def show_node(self, node_id, params=''):
node_show = self.ironic('node-show',
params='{0} {1}'.format(node_id, params))
return utils.get_dict_from_output(node_show)
def list_nodes(self, params=''):
return self.ironic('node-list', params=params)
def update_node(self, node_id, params):
updated_node = self.ironic('node-update',
params='{0} {1}'.format(node_id, params))
return utils.get_dict_from_output(updated_node)
def get_nodes_uuids_from_node_list(self):
node_list = self.list_nodes()
return [x['UUID'] for x in node_list]
def show_node_states(self, node_id):
show_node_states = self.ironic('node-show-states', params=node_id)
return utils.get_dict_from_output(show_node_states)
def set_node_maintenance(self, node_id, maintenance_mode, params=''):
self.ironic(
'node-set-maintenance',
params='{0} {1} {2}'.format(node_id, maintenance_mode, params))
def set_node_power_state(self, node_id, power_state, params=''):
self.ironic('node-set-power-state',
params='{0} {1} {2}'
.format(node_id, power_state, params))
def set_node_provision_state(self, node_id, provision_state, params=''):
self.ironic('node-set-provision-state',
params='{0} {1} {2}'
.format(node_id, provision_state, params))
def validate_node(self, node_id):
return self.ironic('node-validate', params=node_id)
def list_node_chassis(self, chassis_uuid, params=''):
return self.ironic('chassis-node-list',
params='{0} {1}'.format(chassis_uuid, params))
def get_nodes_uuids_from_chassis_node_list(self, chassis_uuid):
chassis_node_list = self.list_node_chassis(chassis_uuid)
return [x['UUID'] for x in chassis_node_list]
def list_driver(self, params=''):
return self.ironic('driver-list', params=params)
def show_driver(self, driver_name):
driver_show = self.ironic('driver-show', params=driver_name)
return utils.get_dict_from_output(driver_show)
def properties_driver(self, driver_name):
return self.ironic('driver-properties', params=driver_name)
def get_drivers_names(self):
driver_list = self.list_driver()
return [x['Supported driver(s)'] for x in driver_list]
def delete_chassis(self, chassis_id, ignore_exceptions=False):
try:
self.ironic('chassis-delete', params=chassis_id)
except exceptions.CommandFailed:
if not ignore_exceptions:
raise
def get_chassis_uuids_from_chassis_list(self):
chassis_list = self.list_chassis()
return [x['UUID'] for x in chassis_list]
def create_chassis(self, params=''):
chassis = self.ironic('chassis-create', params=params)
if not chassis:
self.fail('Ironic chassis has not been created!')
chassis = utils.get_dict_from_output(chassis)
self.addCleanup(self.delete_chassis,
chassis['uuid'],
ignore_exceptions=True)
return chassis
def list_chassis(self, params=''):
return self.ironic('chassis-list', params=params)
def show_chassis(self, chassis_id, params=''):
chassis_show = self.ironic('chassis-show',
params='{0} {1}'.format(chassis_id, params))
return utils.get_dict_from_output(chassis_show)
def update_chassis(self, chassis_id, operation, params=''):
updated_chassis = self.ironic(
'chassis-update',
params='{0} {1} {2}'.format(chassis_id, operation, params))
return utils.get_dict_from_output(updated_chassis)
def delete_port(self, port_id, ignore_exceptions=False):
try:
self.ironic('port-delete', params=port_id)
except exceptions.CommandFailed:
if not ignore_exceptions:
raise
def create_port(self,
node_id,
mac_address=None,
flags='',
params=''):
if mac_address is None:
mac_address = data_utils.rand_mac_address()
port = self.ironic('port-create',
flags=flags,
params='--address {0} --node {1} {2}'
.format(mac_address, node_id, params))
if not port:
self.fail('Ironic port has not been created!')
return utils.get_dict_from_output(port)
def list_ports(self, params=''):
return self.ironic('port-list', params=params)
def show_port(self, port_id, params=''):
port_show = self.ironic('port-show', params='{0} {1}'
.format(port_id, params))
return utils.get_dict_from_output(port_show)
def get_uuids_from_port_list(self):
port_list = self.list_ports()
return [x['UUID'] for x in port_list]
def update_port(self, port_id, operation, flags='', params=''):
updated_port = self.ironic('port-update',
flags=flags,
params='{0} {1} {2}'
.format(port_id, operation, params))
return utils.get_dict_from_output(updated_port)
def create_portgroup(self, node_id, params=''):
"""Create a new portgroup."""
portgroup = self.ironic('portgroup-create',
flags=self.pg_api_ver,
params='--node {0} {1}'
.format(node_id, params))
if not portgroup:
self.fail('Ironic portgroup failed to create!')
portgroup = utils.get_dict_from_output(portgroup)
self.addCleanup(self.delete_portgroup, portgroup['uuid'],
ignore_exceptions=True)
return portgroup
def delete_portgroup(self, portgroup_id, ignore_exceptions=False):
"""Delete a port group."""
try:
self.ironic('portgroup-delete',
flags=self.pg_api_ver,
params=portgroup_id)
except exceptions.CommandFailed:
if not ignore_exceptions:
raise
def list_portgroups(self, params=''):
"""List the port groups."""
return self.ironic('portgroup-list',
flags=self.pg_api_ver,
params=params)
def show_portgroup(self, portgroup_id, params=''):
"""Show detailed information about a port group."""
portgroup_show = self.ironic('portgroup-show',
flags=self.pg_api_ver,
params='{0} {1}'
.format(portgroup_id, params))
return utils.get_dict_from_output(portgroup_show)
def update_portgroup(self, portgroup_id, op, params=''):
"""Update information about a port group."""
updated_portgroup = self.ironic('portgroup-update',
flags=self.pg_api_ver,
params='{0} {1} {2}'
.format(portgroup_id, op, params))
return utils.get_dict_from_output(updated_portgroup)
def get_portgroup_uuids_from_portgroup_list(self):
"""Get UUIDs from list of port groups."""
portgroup_list = self.list_portgroups()
return [x['UUID'] for x in portgroup_list]
def portgroup_port_list(self, portgroup_id, params=''):
"""List the ports associated with a port group."""
return self.ironic('portgroup-port-list', flags=self.pg_api_ver,
params='{0} {1}'.format(portgroup_id, params))

@ -1,485 +0,0 @@
# 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 json
from tempest.lib.common.utils import data_utils
from tempest.lib import exceptions
from ironicclient.tests.functional import base
class TestCase(base.FunctionalTestBase):
driver_name = 'fake-hardware'
def openstack(self, *args, **kwargs):
return self._ironic(cmd='openstack', *args, **kwargs)
def get_opts(self, fields=None, output_format='json'):
"""Get options for OSC output fields format.
:param List fields: List of fields to get
:param String output_format: Select output format
:return: String of formatted options
"""
if not fields:
return ' -f {0}'.format(output_format)
return ' -f {0} {1}'.format(output_format,
' '.join(['-c ' + it for it in fields]))
@staticmethod
def construct_cmd(*parts):
return ' '.join(str(x) for x in parts)
@staticmethod
def generate_params(argument, params):
"""Generate parameters string.
:param argument: argument
:param params: values passed with argument
"""
parts = []
for key, value in params.items():
parts.append('{} {}={}'.format(argument, key, value))
return ' '.join(parts)
def assert_dict_is_subset(self, expected, actual):
"""Check if expected keys/values exist in actual response body.
Check if the expected keys and values are in the actual response body.
:param expected: dict of key-value pairs that are expected to be in
'actual' dict.
:param actual: dict of key-value pairs.
"""
for key, value in expected.items():
self.assertEqual(value, actual[key])
def node_create(self, driver=driver_name, name=None, params=''):
"""Create baremetal node and add cleanup.
:param String driver: Driver for a new node
:param String name: Name for a new node
:param String params: Additional args and kwargs
:return: JSON object of created node
"""
if not name:
name = data_utils.rand_name('baremetal')
opts = self.get_opts()
output = self.openstack('baremetal node create {0} '
'--driver {1} --name {2} {3}'
.format(opts, driver, name, params))
node = json.loads(output)
self.addCleanup(self.node_delete, node['uuid'], True)
if not output:
self.fail('Baremetal node has not been created!')
return node
def node_list(self, fields=None, params=''):
"""List baremetal nodes.
:param List fields: List of fields to show
:param String params: Additional kwargs
:return: list of JSON node objects
"""
opts = self.get_opts(fields=fields)
output = self.openstack('baremetal node list {0} {1}'
.format(opts, params))
return json.loads(output)
def node_show(self, identifier, fields=None, params=''):
"""Show specified baremetal node.
:param String identifier: Name or UUID of the node
:param List fields: List of fields to show
:param List params: Additional kwargs
:return: JSON object of node
"""
opts = self.get_opts(fields)
output = self.openstack('baremetal node show {0} {1} {2}'
.format(opts, identifier, params))
return json.loads(output)
def node_delete(self, identifier, ignore_exceptions=False):
"""Try to delete baremetal node by name or UUID.
:param String identifier: Name or UUID of the node
:param Bool ignore_exceptions: Ignore exception (needed for cleanUp)
:return: raw values output
:raise: CommandFailed exception when command fails to delete a node
"""
try:
return self.openstack('baremetal node delete {0}'
.format(identifier))
except exceptions.CommandFailed:
if not ignore_exceptions:
raise
def port_create(self, node_id, mac_address=None, params=''):
"""Create baremetal port and add cleanup.
:param String node_id: baremetal node UUID
:param String mac_address: MAC address for port
:param String params: Additional args and kwargs
:return: JSON object of created port
"""
if not mac_address:
mac_address = data_utils.rand_mac_address()
opts = self.get_opts()
port = self.openstack('baremetal port create {0} '
'--node {1} {2} {3}'
.format(opts, node_id, mac_address, params))
port = json.loads(port)
if not port:
self.fail('Baremetal port has not been created!')
self.addCleanup(self.port_delete, port['uuid'], True)
return port
def port_list(self, fields=None, params=''):
"""List baremetal ports.
:param List fields: List of fields to show
:param String params: Additional kwargs
:return: list of JSON port objects
"""
opts = self.get_opts(fields=fields)
output = self.openstack('baremetal port list {0} {1}'
.format(opts, params))
return json.loads(output)
def port_show(self, uuid, fields=None, params=''):
"""Show specified baremetal port.
:param String uuid: UUID of the port
:param List fields: List of fields to show
:param List params: Additional kwargs
:return: JSON object of port
"""
opts = self.get_opts(fields)
output = self.openstack('baremetal port show {0} {1} {2}'
.format(opts, uuid, params))
return json.loads(output)
def port_delete(self, uuid, ignore_exceptions=False):
"""Try to delete baremetal port by UUID.
:param String uuid: UUID of the port
:param Bool ignore_exceptions: Ignore exception (needed for cleanUp)
:return: raw values output
:raise: CommandFailed exception when command fails to delete a port
"""
try:
return self.openstack('baremetal port delete {0}'
.format(uuid))
except exceptions.CommandFailed:
if not ignore_exceptions:
raise
def port_group_list(self, fields=None, params=''):
"""List baremetal port groups.
:param List fields: List of fields to show
:param String params: Additional kwargs
:return: JSON object of port group list
"""
opts = self.get_opts(fields=fields)
output = self.openstack('baremetal port group list {0} {1}'
.format(opts, params))
return json.loads(output)
def port_group_create(self, node_id, name=None, params=''):
"""Create baremetal port group.
:param String node_id: baremetal node UUID
:param String name: port group name
:param String params: Additional args and kwargs
:return: JSON object of created port group
"""
if not name:
name = data_utils.rand_name('port_group')
opts = self.get_opts()
output = self.openstack(
'baremetal port group create {0} --node {1} --name {2} {3}'
.format(opts, node_id, name, params))
port_group = json.loads(output)
if not port_group:
self.fail('Baremetal port group has not been created!')
self.addCleanup(self.port_group_delete, port_group['uuid'],
params=params, ignore_exceptions=True)
return port_group
def port_group_delete(self, identifier, params='',
ignore_exceptions=False):
"""Try to delete baremetal port group by Name or UUID.
:param String identifier: Name or UUID of the port group
:param String params: temporary arg to pass api version.
:param Bool ignore_exceptions: Ignore exception (needed for cleanUp)
:return: raw values output
:raise: CommandFailed exception if not ignore_exceptions
"""
try:
return self.openstack('baremetal port group delete {0} {1}'
.format(identifier, params))
except exceptions.CommandFailed:
if not ignore_exceptions:
raise
def port_group_show(self, identifier, fields=None, params=''):
"""Show specified baremetal port group.
:param String identifier: Name or UUID of the port group
:param List fields: List of fields to show
:param List params: Additional kwargs
:return: JSON object of port group
"""
opts = self.get_opts(fields)
output = self.openstack('baremetal port group show {0} {1} {2}'
.format(identifier, opts, params))
return json.loads(output)
def chassis_create(self, params=''):
"""Create baremetal chassis and add cleanup.
:param String params: Additional args and kwargs
:return: JSON object of created chassis
"""
opts = self.get_opts()
chassis = self.openstack('baremetal chassis create {0} {1}'
.format(opts, params))
chassis = json.loads(chassis)
if not chassis:
self.fail('Baremetal chassis has not been created!')
self.addCleanup(self.chassis_delete, chassis['uuid'], True)
return chassis
def chassis_delete(self, uuid, ignore_exceptions=False):
"""Try to delete baremetal chassis by UUID.
:param String uuid: UUID of the chassis
:param Bool ignore_exceptions: Ignore exception (needed for cleanUp)
:return: raw values output
:raise: CommandFailed exception when command fails to delete a chassis
"""
try:
return self.openstack('baremetal chassis delete {0}'
.format(uuid))
except exceptions.CommandFailed:
if not ignore_exceptions:
raise
def chassis_list(self, fields=None, params=''):
"""List baremetal chassis.
:param List fields: List of fields to show
:param String params: Additional kwargs
:return: list of JSON chassis objects
"""
opts = self.get_opts(fields=fields)
output = self.openstack('baremetal chassis list {0} {1}'
.format(opts, params))
return json.loads(output)
def chassis_show(self, uuid, fields=None, params=''):
"""Show specified baremetal chassis.
:param String uuid: UUID of the chassis
:param List fields: List of fields to show
:param List params: Additional kwargs
:return: JSON object of chassis
"""
opts = self.get_opts(fields)
chassis = self.openstack('baremetal chassis show {0} {1} {2}'
.format(opts, uuid, params))
return json.loads(chassis)
def driver_show(self, driver_name, fields=None, params=''):
"""Show specified baremetal driver.
:param String driver_name: Name of the driver
:param List fields: List of fields to show
:param List params: Additional kwargs
:return: JSON object of driver
"""
opts = self.get_opts(fields=fields)
driver = self.openstack('baremetal driver show {0} {1} {2}'
.format(opts, driver_name, params))
return json.loads(driver)
def driver_list(self, fields=None, params=''):
"""List baremetal drivers.
:param List fields: List of fields to show
:param String params: Additional kwargs
:return: list of JSON driver objects
"""
opts = self.get_opts(fields=fields)
output = self.openstack('baremetal driver list {0} {1}'
.format(opts, params))
return json.loads(output)
def driver_raid_property_list(self, driver_name, fields=None, params=''):
"""List a driver's RAID logical disk properties.
:param String driver_name: Name of the driver
:param List fields: List of fields to show
:param List params: Additional kwargs
:return: list of JSON driver RAID properties objects
"""
opts = self.get_opts(fields=fields)
output = self.openstack('baremetal driver raid property list {} {} {}'
.format(opts, driver_name, params))
return json.loads(output)
def conductor_show(self, hostname, fields=None, params=''):
"""Show specified baremetal conductors.
:param String hostname: hostname of the conductor
:param List fields: List of fields to show
:param List params: Additional kwargs
:return: JSON object of driver
"""
opts = self.get_opts(fields=fields)
output = self.openstack('baremetal conductor show {0} {1} {2}'
.format(opts, hostname, params))
return json.loads(output)
def conductor_list(self, fields=None, params=''):
"""List baremetal conductors.
:param List fields: List of fields to show
:param String params: Additional kwargs
:return: list of JSON driver objects
"""
opts = self.get_opts(fields=fields)
output = self.openstack('baremetal conductor list {0} {1}'
.format(opts, params))
return json.loads(output)
def allocation_create(self, resource_class='allocation-test', params=''):
opts = self.get_opts()
output = self.openstack('baremetal allocation create {0} '
'--resource-class {1} {2}'
.format(opts, resource_class, params))
allocation = json.loads(output)
self.addCleanup(self.allocation_delete, allocation['uuid'], True)
if not output:
self.fail('Baremetal allocation has not been created!')
return allocation
def allocation_list(self, fields=None, params=''):
"""List baremetal allocations.
:param List fields: List of fields to show
:param String params: Additional kwargs
:return: list of JSON allocation objects
"""
opts = self.get_opts(fields=fields)
output = self.openstack('baremetal allocation list {0} {1}'
.format(opts, params))
return json.loads(output)
def allocation_show(self, identifier, fields=None, params=''):
"""Show specified baremetal allocation.
:param String identifier: Name or UUID of the allocation
:param List fields: List of fields to show
:param List params: Additional kwargs
:return: JSON object of allocation
"""
opts = self.get_opts(fields)
output = self.openstack('baremetal allocation show {0} {1} {2}'
.format(opts, identifier, params))
return json.loads(output)
def allocation_delete(self, identifier, ignore_exceptions=False):
"""Try to delete baremetal allocation by name or UUID.
:param String identifier: Name or UUID of the allocation
:param Bool ignore_exceptions: Ignore exception (needed for cleanUp)
:return: raw values output
:raise: CommandFailed exception when command fails to delete
an allocation
"""
try:
return self.openstack('baremetal allocation delete {0}'
.format(identifier))
except exceptions.CommandFailed:
if not ignore_exceptions:
raise
def deploy_template_create(self, name, params=''):
"""Create baremetal deploy template and add cleanup.
:param String name: deploy template name
:param String params: additional parameters
:return: JSON object of created deploy template
"""
opts = self.get_opts()
template = self.openstack('baremetal deploy template create {0} {1} '
'{2}'.format(opts, name, params))
template = json.loads(template)
if not template:
self.fail('Baremetal deploy template has not been created!')
self.addCleanup(self.deploy_template_delete, template['uuid'], True)
return template
def deploy_template_list(self, fields=None, params=''):
"""List baremetal deploy templates.
:param List fields: List of fields to show
:param String params: Additional kwargs
:return: list of JSON deploy template objects
"""
opts = self.get_opts(fields=fields)
output = self.openstack('baremetal deploy template list {0} {1}'
.format(opts, params))
return json.loads(output)
def deploy_template_show(self, identifier, fields=None, params=''):
"""Show specified baremetal deploy template.
:param String identifier: Name or UUID of the deploy template
:param List fields: List of fields to show
:param List params: Additional kwargs
:return: JSON object of deploy template
"""
opts = self.get_opts(fields)
output = self.openstack('baremetal deploy template show {0} {1} {2}'
.format(opts, identifier, params))
return json.loads(output)
def deploy_template_delete(self, identifier, ignore_exceptions=False):
"""Try to delete baremetal deploy template by UUID.
:param String identifier: Name or UUID of the deploy template
:param Bool ignore_exceptions: Ignore exception (needed for cleanUp)
:return: raw values output
:raise: CommandFailed exception when command fails to delete a deploy
template
"""
try:
return self.openstack('baremetal deploy template delete {0}'
.format(identifier))
except exceptions.CommandFailed:
if not ignore_exceptions:
raise

@ -1,187 +0,0 @@
# 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 ddt
from tempest.lib.common.utils import data_utils
from tempest.lib import exceptions
from ironicclient.tests.functional.osc.v1 import base
@ddt.ddt
class BaremetalAllocationTests(base.TestCase):
"""Functional tests for baremetal allocation commands."""
def test_create(self):
"""Check baremetal allocation create command.
Test steps:
1) Create baremetal allocation in setUp.
2) Check that allocation successfully created.
"""
allocation_info = self.allocation_create()
self.assertTrue(allocation_info['resource_class'])
self.assertEqual(allocation_info['state'], 'allocating')
allocation_list = self.allocation_list()
self.assertIn(allocation_info['uuid'],
[x['UUID'] for x in allocation_list])
def test_create_name_uuid(self):
"""Check baremetal allocation create command with name and UUID.
Test steps:
1) Create baremetal allocation with specified name and UUID.
2) Check that allocation successfully created.
"""
uuid = data_utils.rand_uuid()
name = data_utils.rand_name('baremetal-allocation')
allocation_info = self.allocation_create(
params='--uuid {0} --name {1}'.format(uuid, name))
self.assertEqual(allocation_info['uuid'], uuid)
self.assertEqual(allocation_info['name'], name)
self.assertTrue(allocation_info['resource_class'])
self.assertEqual(allocation_info['state'], 'allocating')
allocation_list = self.allocation_list()
self.assertIn(uuid, [x['UUID'] for x in allocation_list])
self.assertIn(name, [x['Name'] for x in allocation_list])
def test_create_traits(self):
"""Check baremetal allocation create command with traits.
Test steps:
1) Create baremetal allocation with specified traits.
2) Check that allocation successfully created.
"""
allocation_info = self.allocation_create(
params='--trait CUSTOM_1 --trait CUSTOM_2')
self.assertTrue(allocation_info['resource_class'])
self.assertEqual(allocation_info['state'], 'allocating')
self.assertIn('CUSTOM_1', allocation_info['traits'])
self.assertIn('CUSTOM_2', allocation_info['traits'])
def test_create_candidate_nodes(self):
"""Check baremetal allocation create command with candidate nodes.
Test steps:
1) Create two nodes.
2) Create baremetal allocation with specified traits.
3) Check that allocation successfully created.
"""
name = data_utils.rand_name('baremetal-allocation')
node1 = self.node_create(name=name)
node2 = self.node_create()
allocation_info = self.allocation_create(
params='--candidate-node {0} --candidate-node {1}'
.format(node1['name'], node2['uuid']))
self.assertEqual(allocation_info['state'], 'allocating')
# NOTE(dtantsur): names are converted to uuids in the API
self.assertIn(node1['uuid'], allocation_info['candidate_nodes'])
self.assertIn(node2['uuid'], allocation_info['candidate_nodes'])
@ddt.data('name', 'uuid')
def test_delete(self, key):
"""Check baremetal allocation delete command with name/UUID argument.
Test steps:
1) Create baremetal allocation.
2) Delete baremetal allocation by name/UUID.
3) Check that allocation deleted successfully.
"""
name = data_utils.rand_name('baremetal-allocation')
allocation = self.allocation_create(params='--name {}'.format(name))
output = self.allocation_delete(allocation[key])
self.assertIn('Deleted allocation {0}'.format(allocation[key]), output)
allocation_list = self.allocation_list()
self.assertNotIn(allocation['name'],
[x['Name'] for x in allocation_list])
self.assertNotIn(allocation['uuid'],
[x['UUID'] for x in allocation_list])
@ddt.data('name', 'uuid')
def test_show(self, key):
"""Check baremetal allocation show command with name and UUID.
Test steps:
1) Create baremetal allocation.
2) Show baremetal allocation calling it with name and UUID arguments.
3) Check name, uuid and resource_class in allocation show output.
"""
name = data_utils.rand_name('baremetal-allocation')
allocation = self.allocation_create(params='--name {}'.format(name))
result = self.allocation_show(allocation[key],
['name', 'uuid', 'resource_class'])
self.assertEqual(allocation['name'], result['name'])
self.assertEqual(allocation['uuid'], result['uuid'])
self.assertTrue(result['resource_class'])
self.assertNotIn('state', result)
@ddt.data(
('--uuid', '', 'expected one argument'),
('--uuid', '!@#$^*&%^', 'Expected UUID for uuid'),
('--extra', '', 'expected one argument'),
('--name', '', 'expected one argument'),
('--name', 'not/a/name', 'invalid name'),
('--resource-class', '', 'expected one argument'),
('--resource-class', 'x' * 81, 'is too long'),
('--trait', '', 'expected one argument'),
('--trait', 'foo', 'does not match'),
('--candidate-node', '', 'expected one argument'),
('--candidate-node', 'banana?', 'Nodes cannot be found'),
('--wait', 'meow', 'invalid int value'))
@ddt.unpack
def test_create_negative(self, argument, value, ex_text):
"""Check errors on invalid input parameters."""
base_cmd = 'baremetal allocation create'
if argument != '--resource-class':
base_cmd += ' --resource-class allocation-test'
command = self.construct_cmd(base_cmd, argument, value)
self.assertRaisesRegex(exceptions.CommandFailed, ex_text,
self.openstack, command)
def test_create_no_resource_class(self):
"""Check errors on missing resource class."""
base_cmd = 'baremetal allocation create'
self.assertRaisesRegex(exceptions.CommandFailed,
'--resource-class',
self.openstack, base_cmd)
def test_set_unset(self):
"""Check baremetal allocation set and unset commands.
Test steps:
1) Create baremetal allocation in setUp.
2) Set extra data for allocation.
3) Check that baremetal allocation extra data was set.
4) Unset extra data for allocation.
5) Check that baremetal allocation extra data was unset.
"""
name = data_utils.rand_name('baremetal-allocation')
allocation = self.allocation_create(params='--name {}'.format(name))
extra_key = 'ext'
extra_value = 'testdata'
self.openstack(
'baremetal allocation set --extra {0}={1} {2}'
.format(extra_key, extra_value, allocation['uuid']))
show_prop = self.allocation_show(allocation['uuid'],
fields=['extra'])
self.assertEqual(extra_value, show_prop['extra'][extra_key])
self.openstack('baremetal allocation unset --extra {0} {1}'
.format(extra_key, allocation['uuid']))
show_prop = self.allocation_show(allocation['uuid'],
fields=['extra'])
self.assertNotIn(extra_key, show_prop['extra'])

@ -1,86 +0,0 @@
# Copyright (c) 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
# 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.
from ironicclient.tests.functional.osc.v1 import base
class BaremetalChassisTests(base.TestCase):
"""Functional tests for baremetal chassis commands."""
def setUp(self):
super(BaremetalChassisTests, self).setUp()
self.chassis = self.chassis_create()
def test_list(self):
"""Check baremetal chassis list command.
Test steps:
1) Create baremetal chassis in setUp.
2) List baremetal chassis.
3) Check chassis description and UUID in chassis list.
"""
chassis_list = self.chassis_list()
self.assertIn(self.chassis['uuid'],
[x['UUID'] for x in chassis_list])
self.assertIn(self.chassis['description'],
[x['Description'] for x in chassis_list])
def test_show(self):
"""Check baremetal chassis show command.
Test steps:
1) Create baremetal chassis in setUp.
2) Show baremetal chassis.
3) Check chassis in chassis show.
"""
chassis = self.chassis_show(self.chassis['uuid'])
self.assertEqual(self.chassis['uuid'], chassis['uuid'])
self.assertEqual(self.chassis['description'], chassis['description'])
def test_delete(self):
"""Check baremetal chassis delete command.
Test steps:
1) Create baremetal chassis in setUp.
2) Delete baremetal chassis by UUID.
3) Check that chassis deleted successfully.
"""
output = self.chassis_delete(self.chassis['uuid'])
self.assertIn('Deleted chassis {0}'.format(self.chassis['uuid']),
output)
self.assertNotIn(self.chassis['uuid'], self.chassis_list(['UUID']))
def test_set_unset_extra(self):
"""Check baremetal chassis set and unset commands.
Test steps:
1) Create baremetal chassis in setUp.
2) Set extra data for chassis.
3) Check that baremetal chassis extra data was set.
4) Unset extra data for chassis.
5) Check that baremetal chassis extra data was unset.
"""
extra_key = 'ext'
extra_value = 'testdata'
self.openstack('baremetal chassis set --extra {0}={1} {2}'
.format(extra_key, extra_value, self.chassis['uuid']))
show_prop = self.chassis_show(self.chassis['uuid'], ['extra'])
self.assertEqual(extra_value, show_prop['extra'][extra_key])
self.openstack('baremetal chassis unset --extra {0} {1}'
.format(extra_key, self.chassis['uuid']))
show_prop = self.chassis_show(self.chassis['uuid'], ['extra'])
self.assertNotIn(extra_key, show_prop['extra'])

@ -1,38 +0,0 @@
# 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.
from ironicclient.tests.functional.osc.v1 import base
class BaremetalConductorTests(base.TestCase):
"""Functional tests for baremetal conductor commands."""
def test_list(self):
"""List available conductors.
There is at lease one conductor in the functional tests, if not, other
tests will fail too.
"""
hostnames = [c['Hostname'] for c in self.conductor_list()]
self.assertIsNotNone(hostnames)
def test_show(self):
"""Show specified conductor.
Conductor name varies in different environment, list first, then show
one of them.
"""
conductors = self.conductor_list()
conductor = self.conductor_show(conductors[0]['Hostname'])
self.assertIn('conductor_group', conductor)
self.assertIn('alive', conductor)
self.assertIn('drivers', conductor)

@ -1,177 +0,0 @@
# 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 json
import ddt
from tempest.lib.common.utils import data_utils
from tempest.lib import exceptions
from ironicclient.tests.functional.osc.v1 import base
@ddt.ddt
class BaremetalDeployTemplateTests(base.TestCase):
"""Functional tests for baremetal deploy template commands."""
@staticmethod
def _get_random_trait():
return data_utils.rand_name('CUSTOM', '').replace('-', '_')
def setUp(self):
super(BaremetalDeployTemplateTests, self).setUp()
self.steps = json.dumps([{
'interface': 'bios',
'step': 'apply_configuration',
'args': {},
'priority': 10,
}])
name = self._get_random_trait()
self.template = self.deploy_template_create(
name, params="--steps '%s'" % self.steps)
def tearDown(self):
if self.template is not None:
self.deploy_template_delete(self.template['uuid'])
super(BaremetalDeployTemplateTests, self).tearDown()
def test_list(self):
"""Check baremetal deploy template list command.
Test steps:
1) Create baremetal deploy template in setUp.
2) List baremetal deploy templates.
3) Check deploy template name and UUID in deploy templates list.
"""
template_list = self.deploy_template_list()
self.assertIn(self.template['name'],
[template['Name']
for template in template_list])
self.assertIn(self.template['uuid'],
[template['UUID']
for template in template_list])
def test_list_long(self):
"""Check baremetal deploy template list --long command
Test steps:
1) Create baremetal deploy template in setUp.
2) List baremetal deploy templates with detail=True.
3) Check deploy template fields in output.
"""
template_list = self.deploy_template_list(params='--long')
template = [template for template in template_list
if template['Name'] == self.template['name']][0]
self.assertEqual(self.template['extra'], template['Extra'])
self.assertEqual(self.template['name'], template['Name'])
self.assertEqual(self.template['steps'], template['Steps'])
self.assertEqual(self.template['uuid'], template['UUID'])
def test_show(self):
"""Check baremetal deploy template show command with UUID.
Test steps:
1) Create baremetal deploy template in setUp.
2) Show baremetal deploy template calling it by UUID.
3) Check deploy template fields in output.
"""
template = self.deploy_template_show(self.template['uuid'])
self.assertEqual(self.template['extra'], template['extra'])
self.assertEqual(self.template['name'], template['name'])
self.assertEqual(self.template['steps'], template['steps'])
self.assertEqual(self.template['uuid'], template['uuid'])
def test_delete(self):
"""Check baremetal deploy template delete command.
Test steps:
1) Create baremetal deploy template in setUp.
2) Delete baremetal deploy template by UUID.
3) Check that deploy template deleted successfully and not in list.
"""
output = self.deploy_template_delete(self.template['uuid'])
self.assertIn('Deleted deploy template {0}'.format(
self.template['uuid']), output)
template_list = self.deploy_template_list()
self.assertNotIn(self.template['name'],
[template['Name'] for template in template_list])
self.assertNotIn(self.template['uuid'],
[template['UUID'] for template in template_list])
self.template = None
def test_set_steps(self):
"""Check baremetal deploy template set command for steps.
Test steps:
1) Create baremetal deploy template in setUp.
2) Set steps for deploy template.
3) Check that baremetal deploy template steps were set.
"""
steps = [{
'interface': 'bios',
'step': 'apply_configuration',
'args': {},
'priority': 20,
}]
self.openstack("baremetal deploy template set --steps '{0}' {1}"
.format(json.dumps(steps), self.template['uuid']))
show_prop = self.deploy_template_show(self.template['uuid'],
fields=['steps'])
self.assertEqual(steps, show_prop['steps'])
def test_set_unset(self):
"""Check baremetal deploy template set and unset commands.
Test steps:
1) Create baremetal deploy template in setUp.
2) Set extra data for deploy template.
3) Check that baremetal deploy template extra data was set.
4) Unset extra data for deploy template.
5) Check that baremetal deploy template extra data was unset.
"""
extra_key = 'ext'
extra_value = 'testdata'
self.openstack(
'baremetal deploy template set --extra {0}={1} {2}'
.format(extra_key, extra_value, self.template['uuid']))
show_prop = self.deploy_template_show(self.template['uuid'],
fields=['extra'])
self.assertEqual(extra_value, show_prop['extra'][extra_key])
self.openstack('baremetal deploy template unset --extra {0} {1}'
.format(extra_key, self.template['uuid']))
show_prop = self.deploy_template_show(self.template['uuid'],
fields=['extra'])
self.assertNotIn(extra_key, show_prop['extra'])
@ddt.data(
('--uuid', '', 'expected one argument'),
('--uuid', '!@#$^*&%^', 'Expected UUID for uuid'),
('', '', 'the following arguments are required'),
('', 'not/a/name', 'does not match'),
('', 'foo', 'does not match'),
('--steps', '', 'expected one argument'),
('--steps', '[]', 'is too short'))
@ddt.unpack
def test_create_negative(self, argument, value, ex_text):
"""Check errors on invalid input parameters."""
base_cmd = 'baremetal deploy template create'
if argument != '':
base_cmd += ' %s' % self._get_random_trait()
if argument != '--steps':
base_cmd += " --steps '%s'" % self.steps
command = self.construct_cmd(base_cmd, argument, value)
self.assertRaisesRegex(exceptions.CommandFailed, ex_text,
self.openstack, command)

@ -1,57 +0,0 @@
# Copyright (c) 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
# 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.
from ironicclient.tests.functional.osc.v1 import base
class BaremetalDriverTests(base.TestCase):
"""Functional tests for baremetal driver commands."""
def test_show(self):
"""Show specified driver.
Test step:
1) Check output of baremetal driver show command.
"""
driver = self.driver_show(self.driver_name)
self.assertEqual(self.driver_name, driver['name'])
def test_list(self):
"""List available drivers.
Test steps:
1) Get list of drivers.
2) Check that list of drivers is not empty.
"""
drivers = [
driver['Supported driver(s)'] for driver in self.driver_list()
]
self.assertIn(self.driver_name, drivers)
def test_driver_raid_property_list(self):
"""Test baremetal driver raid property list command.
Test steps:
1) Get list of fake driver raid properties.
2) Check contents of driver raid properties list.
"""
props = ['controller', 'disk_type', 'interface_type',
'is_root_volume', 'number_of_physical_disks',
'physical_disks', 'raid_level', 'share_physical_disks',
'size_gb', 'volume_name']
raid_props = self.driver_raid_property_list(
self.driver_name,
params='--os-baremetal-api-version 1.12')
for prop in props:
self.assertIn(prop, [i['Property'] for i in raid_props])

@ -1,231 +0,0 @@
# Copyright (c) 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
# 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 json
import ddt
from tempest.lib.common.utils import data_utils
from ironicclient.tests.functional.osc.v1 import base
@ddt.ddt
class BaremetalNodeTests(base.TestCase):
"""Functional tests for baremetal node commands."""
def setUp(self):
super(BaremetalNodeTests, self).setUp()
self.node = self.node_create()
def test_create_name_uuid(self):
"""Check baremetal node create command with name and UUID.
Test steps:
1) Create baremetal node in setUp.
2) Create one more baremetal node explicitly
with specified name and UUID.
3) Check that node successfully created.
"""
uuid = data_utils.rand_uuid()
name = data_utils.rand_name('baremetal-node')
node_info = self.node_create(name=name,
params='--uuid {0}'.format(uuid))
self.assertEqual(node_info['uuid'], uuid)
self.assertEqual(node_info['name'], name)
self.assertEqual(node_info['driver'], self.driver_name)
self.assertEqual(node_info['maintenance'], False)
self.assertEqual(node_info['provision_state'], 'enroll')
node_list = self.node_list()
self.assertIn(uuid, [x['UUID'] for x in node_list])
self.assertIn(name, [x['Name'] for x in node_list])
def test_create_old_api_version(self):
"""Check baremetal node create command with name and UUID.
Test steps:
1) Create baremetal node in setUp.
2) Create one more baremetal node explicitly with old API version
3) Check that node successfully created.
"""
node_info = self.node_create(
params='--os-baremetal-api-version 1.5')
self.assertEqual(node_info['driver'], self.driver_name)
self.assertEqual(node_info['maintenance'], False)
self.assertEqual(node_info['provision_state'], 'available')
@ddt.data('name', 'uuid')
def test_delete(self, key):
"""Check baremetal node delete command with name/UUID argument.
Test steps:
1) Create baremetal node in setUp.
2) Delete baremetal node by name/UUID.
3) Check that node deleted successfully.
"""
output = self.node_delete(self.node[key])
self.assertIn('Deleted node {0}'.format(self.node[key]), output)
node_list = self.node_list()
self.assertNotIn(self.node['name'], [x['Name'] for x in node_list])
self.assertNotIn(self.node['uuid'], [x['UUID'] for x in node_list])
def test_list(self):
"""Check baremetal node list command.
Test steps:
1) Create baremetal node in setUp.
2) List baremetal nodes.
3) Check node name in nodes list.
"""
node_list = self.node_list()
self.assertIn(self.node['name'], [x['Name'] for x in node_list])
self.assertIn(self.node['uuid'], [x['UUID'] for x in node_list])
@ddt.data('name', 'uuid')
def test_set(self, key):
"""Check baremetal node set command calling it by name/UUID.
Test steps:
1) Create baremetal node in setUp.
2) Set another name for node calling it by name/UUID.
3) Check that baremetal node name was changed.
"""
new_name = data_utils.rand_name('newnodename')
self.openstack('baremetal node set --name {0} {1}'
.format(new_name, self.node[key]))
show_prop = self.node_show(self.node['uuid'], ['name'])
self.assertEqual(new_name, show_prop['name'])
@ddt.data('name', 'uuid')
def test_unset(self, key):
"""Check baremetal node unset command calling it by node name/UUID.
Test steps:
1) Create baremetal node in setUp.
2) Unset name of baremetal node calling it by node name/UUID.
3) Check that node has no more name.
"""
self.openstack('baremetal node unset --name {0}'
.format(self.node[key]))
show_prop = self.node_show(self.node['uuid'], ['name'])
self.assertIsNone(show_prop['name'])
@ddt.data('name', 'uuid')
def test_show(self, key):
"""Check baremetal node show command with name and UUID arguments.
Test steps:
1) Create baremetal node in setUp.
2) Show baremetal node calling it with name and UUID arguments.
3) Check name, uuid and driver in node show output.
"""
node = self.node_show(self.node[key],
['name', 'uuid', 'driver'])
self.assertEqual(self.node['name'], node['name'])
self.assertEqual(self.node['uuid'], node['uuid'])
self.assertEqual(self.node['driver'], node['driver'])
def test_baremetal_node_maintenance_set_unset(self):
"""Check baremetal node maintenance set command.
Test steps:
1) Create baremetal node in setUp.
2) Check maintenance status of fresh node is False.
3) Set maintenance status for node.
4) Check maintenance status of node is True.
5) Unset maintenance status for node.
6) Check maintenance status of node is False back.
"""
show_prop = self.node_show(self.node['name'], ['maintenance'])
self.assertFalse(show_prop['maintenance'])
self.openstack('baremetal node maintenance set {0}'.
format(self.node['name']))
show_prop = self.node_show(self.node['name'], ['maintenance'])
self.assertTrue(show_prop['maintenance'])
self.openstack('baremetal node maintenance unset {0}'.
format(self.node['name']))
show_prop = self.node_show(self.node['name'], ['maintenance'])
self.assertFalse(show_prop['maintenance'])
def test_baremetal_node_maintenance_set_unset_reason(self):
"""Check baremetal node maintenance set command.
Test steps:
1) Create baremetal node in setUp.
2) Check initial maintenance reason is None.
3) Set maintenance status for node with reason.
4) Check maintenance reason of node equals to expected value.
Also check maintenance status.
5) Unset maintenance status for node. Recheck maintenance status.
6) Check maintenance reason is None. Recheck maintenance status.
"""
reason = "Hardware maintenance."
show_prop = self.node_show(self.node['name'],
['maintenance_reason', 'maintenance'])
self.assertIsNone(show_prop['maintenance_reason'])
self.assertFalse(show_prop['maintenance'])
self.openstack("baremetal node maintenance set --reason '{0}' {1}".
format(reason, self.node['name']))
show_prop = self.node_show(self.node['name'],
['maintenance_reason', 'maintenance'])
self.assertEqual(reason, show_prop['maintenance_reason'])
self.assertTrue(show_prop['maintenance'])
self.openstack('baremetal node maintenance unset {0}'.
format(self.node['name']))
show_prop = self.node_show(self.node['name'],
['maintenance_reason', 'maintenance'])
self.assertIsNone(show_prop['maintenance_reason'])
self.assertFalse(show_prop['maintenance'])
@ddt.data(
(50, '1'),
('MAX', 'JBOD'),
(300, '6+0')
)
@ddt.unpack
def test_set_unset_target_raid_config(self, size, raid_level):
"""Set and unset node target RAID config data.
Test steps:
1) Create baremetal node in setUp.
2) Set target RAID config data for the node
3) Check target_raid_config of node equals to expected value.
4) Unset target_raid_config data.
5) Check that target_raid_config data is empty.
"""
min_version = '--os-baremetal-api-version 1.12'
argument_json = {"logical_disks":
[{"size_gb": size, "raid_level": raid_level}]}
argument_string = json.dumps(argument_json)
self.openstack("baremetal node set --target-raid-config '{}' {} {}"
.format(argument_string, self.node['uuid'],
min_version))
show_prop = self.node_show(self.node['uuid'], ['target_raid_config'],
min_version)
self.assert_dict_is_subset(argument_json,
show_prop['target_raid_config'])
self.openstack("baremetal node unset --target-raid-config {} {}"
.format(self.node['uuid'], min_version))
show_prop = self.node_show(self.node['uuid'], ['target_raid_config'],
min_version)
self.assertEqual({}, show_prop['target_raid_config'])

@ -1,47 +0,0 @@
# Copyright (c) 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
# 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 ddt
from tempest.lib import exceptions
from ironicclient.tests.functional.osc.v1 import base
@ddt.ddt
class BaremetalNodeCreateNegativeTests(base.TestCase):
"""Negative tests for node create command."""
def setUp(self):
super(BaremetalNodeCreateNegativeTests, self).setUp()
@ddt.data(
('--uuid', '', 'expected one argument'),
('--uuid', '!@#$^*&%^', 'Expected UUID for uuid'),
('--uuid', '0000 0000', 'unrecognized arguments'),
('--driver-info', '', 'expected one argument'),
('--driver-info', 'some info', 'unrecognized arguments'),
('--property', '', 'expected one argument'),
('--property', 'some property', 'unrecognized arguments'),
('--extra', '', 'expected one argument'),
('--extra', 'some extra', 'unrecognized arguments'),
('--name', '', 'expected one argument'),
('--name', 'some name', 'unrecognized arguments'),
('--network-interface', '', 'expected one argument'),
('--resource-class', '', 'expected one argument'))
@ddt.unpack
def test_baremetal_node_create(self, argument, value, ex_text):
base_cmd = 'baremetal node create --driver %s' % self.driver_name
command = self.construct_cmd(base_cmd, argument, value)
self.assertRaisesRegex(exceptions.CommandFailed, ex_text,
self.openstack, command)

@ -1,136 +0,0 @@
# Copyright (c) 2017 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.
from tempest.lib import exceptions
from ironicclient.tests.functional.osc.v1 import base
class TestNodeListFields(base.TestCase):
"""Functional tests for "baremetal node list" with --fields."""
def setUp(self):
super(TestNodeListFields, self).setUp()
self.node = self.node_create()
def _get_table_headers(self, raw_output):
table = self.parser.table(raw_output)
return table['headers']
def test_list_default_fields(self):
"""Test presence of default list table headers."""
headers = ['UUID', 'Name', 'Instance UUID',
'Power State', 'Provisioning State', 'Maintenance']
nodes_list = self.openstack('baremetal node list')
nodes_list_headers = self._get_table_headers(nodes_list)
self.assertEqual(set(headers), set(nodes_list_headers))
def test_list_minimal_fields(self):
headers = ['Instance UUID', 'Name', 'UUID']
fields = ['instance_uuid', 'name', 'uuid']
node_list = self.openstack(
'baremetal node list --fields {}'.format(' '.join(fields)))
nodes_list_headers = self._get_table_headers(node_list)
self.assertEqual(headers, nodes_list_headers)
def test_list_no_fields(self):
command = 'baremetal node list --fields'
ex_text = 'expected at least one argument'
self.assertRaisesRegex(exceptions.CommandFailed, ex_text,
self.openstack, command)
def test_list_wrong_field(self):
command = 'baremetal node list --fields ABC'
ex_text = 'invalid choice'
self.assertRaisesRegex(exceptions.CommandFailed, ex_text,
self.openstack, command)
class TestNodeShowFields(base.TestCase):
"""Functional tests for "baremetal node show" with --fields."""
def setUp(self):
super(TestNodeShowFields, self).setUp()
self.node = self.node_create()
self.api_version = '--os-baremetal-api-version 1.20'
def _get_table_rows(self, raw_output):
table = self.parser.table(raw_output)
rows = []
for row in table['values']:
rows.append(row[0])
return rows
def test_show_default_fields(self):
rows = ['console_enabled',
'clean_step',
'created_at',
'deploy_step',
'driver',
'driver_info',
'driver_internal_info',
'extra',
'inspection_finished_at',
'inspection_started_at',
'instance_info',
'instance_uuid',
'last_error',
'maintenance',
'maintenance_reason',
'name',
'power_state',
'properties',
'provision_state',
'provision_updated_at',
'reservation',
'target_power_state',
'target_provision_state',
'updated_at',
'uuid']
node_show = self.openstack('baremetal node show {}'
.format(self.node['uuid']))
nodes_show_rows = self._get_table_rows(node_show)
self.assertTrue(set(rows).issubset(set(nodes_show_rows)))
def test_show_minimal_fields(self):
rows = [
'instance_uuid',
'name',
'uuid']
node_show = self.openstack(
'baremetal node show {} --fields {} {}'.format(
self.node['uuid'], ' '.join(rows), self.api_version))
nodes_show_rows = self._get_table_rows(node_show)
self.assertEqual(set(rows), set(nodes_show_rows))
def test_show_no_fields(self):
command = 'baremetal node show {} --fields {}'.format(
self.node['uuid'], self.api_version)
ex_text = 'expected at least one argument'
self.assertRaisesRegex(exceptions.CommandFailed, ex_text,
self.openstack, command)
def test_show_wrong_field(self):
command = 'baremetal node show {} --fields ABC {}'.format(
self.node['uuid'], self.api_version)
ex_text = 'invalid choice'
self.assertRaisesRegex(exceptions.CommandFailed, ex_text,
self.openstack, command)

@ -1,83 +0,0 @@
# Copyright (c) 2017 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 ddt
from tempest.lib import exceptions
from ironicclient.tests.functional.osc.v1 import base
@ddt.ddt
class BaremetalNodeNegativeTests(base.TestCase):
"""Negative tests for baremetal node commands."""
def setUp(self):
super(BaremetalNodeNegativeTests, self).setUp()
self.node = self.node_create()
@ddt.data(
('', '', 'error: the following arguments are required: --driver'),
('--driver', 'wrongdriver',
'No valid host was found. Reason: No conductor service '
'registered which supports driver wrongdriver.')
)
@ddt.unpack
def test_create_driver(self, argument, value, ex_text):
"""Negative test for baremetal node driver options."""
base_cmd = 'baremetal node create'
command = self.construct_cmd(base_cmd, argument, value)
self.assertRaisesRegex(exceptions.CommandFailed, ex_text,
self.openstack, command)
def test_delete_no_node(self):
"""Test for baremetal node delete without node specified."""
command = 'baremetal node delete'
ex_text = ''
self.assertRaisesRegex(exceptions.CommandFailed, ex_text,
self.openstack, command)
def test_list_wrong_argument(self):
"""Test for baremetal node list with wrong argument."""
command = 'baremetal node list --wrong_arg'
ex_text = 'error: unrecognized arguments: --wrong_arg'
self.assertRaisesRegex(exceptions.CommandFailed, ex_text,
self.openstack, command)
@ddt.data(
('--property', '',
'error: the following arguments are required: <node>'),
('--property', 'prop', 'Attributes must be a list of PATH=VALUE')
)
@ddt.unpack
def test_set_property(self, argument, value, ex_text):
"""Negative test for baremetal node set command options."""
base_cmd = 'baremetal node set'
command = self.construct_cmd(base_cmd, argument, value,
self.node['uuid'])
self.assertRaisesRegex(exceptions.CommandFailed, ex_text,
self.openstack, command)
@ddt.data(
('--property', '',
'error: the following arguments are required: <node>'),
('--property', 'prop', "Reason: can't remove a non-existent object")
)
@ddt.unpack
def test_unset_property(self, argument, value, ex_text):
"""Negative test for baremetal node unset command options."""
base_cmd = 'baremetal node unset'
command = self.construct_cmd(base_cmd, argument, value,
self.node['uuid'])
self.assertRaisesRegex(exceptions.CommandFailed, ex_text,
self.openstack, command)

@ -1,58 +0,0 @@
# Copyright (c) 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
# 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.
from ironicclient.tests.functional.osc.v1 import base
class PowerStateTests(base.TestCase):
"""Functional tests for baremetal node power state commands."""
def setUp(self):
super(PowerStateTests, self).setUp()
self.node = self.node_create()
def test_off_reboot_on(self):
"""Reboot node from Power OFF state.
Test steps:
1) Create baremetal node in setUp.
2) Set node Power State OFF as precondition.
3) Call reboot command for baremetal node.
4) Check node Power State ON in node properties.
"""
self.openstack('baremetal node power off {0}'
.format(self.node['uuid']))
show_prop = self.node_show(self.node['uuid'], ['power_state'])
self.assertEqual('power off', show_prop['power_state'])
self.openstack('baremetal node reboot {0}'.format(self.node['uuid']))
show_prop = self.node_show(self.node['uuid'], ['power_state'])
self.assertEqual('power on', show_prop['power_state'])
def test_on_reboot_on(self):
"""Reboot node from Power ON state.
Test steps:
1) Create baremetal node in setUp.
2) Set node Power State ON as precondition.
3) Call reboot command for baremetal node.
4) Check node Power State ON in node properties.
"""
self.openstack('baremetal node power on {0}'.format(self.node['uuid']))
show_prop = self.node_show(self.node['uuid'], ['power_state'])
self.assertEqual('power on', show_prop['power_state'])
self.openstack('baremetal node reboot {0}'.format(self.node['uuid']))
show_prop = self.node_show(self.node['uuid'], ['power_state'])
self.assertEqual('power on', show_prop['power_state'])

@ -1,84 +0,0 @@
# Copyright (c) 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
# 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.
from ironicclient.tests.functional.osc.v1 import base
class ProvisionStateTests(base.TestCase):
"""Functional tests for baremetal node provision state commands."""
def setUp(self):
super(ProvisionStateTests, self).setUp()
self.node = self.node_create()
def test_deploy_rebuild_undeploy_manage(self):
"""Deploy, rebuild and undeploy node.
Test steps:
1) Create baremetal node in setUp.
2) Check initial "enroll" provision state.
3) Set baremetal node "manage" provision state.
4) Check baremetal node provision_state field value is "manageable".
5) Set baremetal node "provide" provision state.
6) Check baremetal node provision_state field value is "available".
7) Set baremetal node "deploy" provision state.
8) Check baremetal node provision_state field value is "active".
9) Set baremetal node "rebuild" provision state.
10) Check baremetal node provision_state field value is "active".
11) Set baremetal node "undeploy" provision state.
12) Check baremetal node provision_state field value is "available".
13) Set baremetal node "manage" provision state.
14) Check baremetal node provision_state field value is "manageable".
15) Set baremetal node "provide" provision state.
16) Check baremetal node provision_state field value is "available".
"""
show_prop = self.node_show(self.node['uuid'], ["provision_state"])
self.assertEqual("enroll", show_prop["provision_state"])
# manage
self.openstack('baremetal node manage {0}'.format(self.node['uuid']))
show_prop = self.node_show(self.node['uuid'], ["provision_state"])
self.assertEqual("manageable", show_prop["provision_state"])
# provide
self.openstack('baremetal node provide {0}'.format(self.node['uuid']))
show_prop = self.node_show(self.node['uuid'], ["provision_state"])
self.assertEqual("available", show_prop["provision_state"])
# deploy
self.openstack('baremetal node deploy {0}'.format(self.node['uuid']))
show_prop = self.node_show(self.node['uuid'], ["provision_state"])
self.assertEqual("active", show_prop["provision_state"])
# rebuild
self.openstack('baremetal node rebuild {0}'.format(self.node['uuid']))
show_prop = self.node_show(self.node['uuid'], ["provision_state"])
self.assertEqual("active", show_prop["provision_state"])
# undeploy
self.openstack('baremetal node undeploy {0}'.format(self.node['uuid']))
show_prop = self.node_show(self.node['uuid'], ["provision_state"])
self.assertEqual("available", show_prop["provision_state"])
# manage
self.openstack('baremetal node manage {0}'.format(self.node['uuid']))
show_prop = self.node_show(self.node['uuid'], ["provision_state"])
self.assertEqual("manageable", show_prop["provision_state"])
# provide back
self.openstack('baremetal node provide {0}'.format(self.node['uuid']))
show_prop = self.node_show(self.node['uuid'], ["provision_state"])
self.assertEqual("available", show_prop["provision_state"])

@ -1,124 +0,0 @@
# Copyright (c) 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
# 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.
from ironicclient.tests.functional.osc.v1 import base
class BaremetalPortTests(base.TestCase):
"""Functional tests for baremetal port commands."""
def setUp(self):
super(BaremetalPortTests, self).setUp()
self.node = self.node_create()
self.port = self.port_create(self.node['uuid'])
def test_list(self):
"""Check baremetal port list command.
Test steps:
1) Create baremetal port in setUp.
2) List baremetal ports.
3) Check port address and UUID in ports list.
"""
port_list = self.port_list()
self.assertIn(self.port['address'],
[port['Address'] for port in port_list])
self.assertIn(self.port['uuid'],
[port['UUID'] for port in port_list])
def test_show_uuid(self):
"""Check baremetal port show command with UUID.
Test steps:
1) Create baremetal port in setUp.
2) Show baremetal port calling it by UUID.
3) Check port fields in output.
"""
port = self.port_show(self.port['uuid'])
self.assertEqual(self.port['address'], port['address'])
self.assertEqual(self.port['uuid'], port['uuid'])
self.assertEqual(self.port['node_uuid'], self.node['uuid'])
def test_show_addr(self):
"""Check baremetal port show command with address.
Test steps:
1) Create baremetal port in setUp.
2) Show baremetal port calling it by address.
3) Check port fields in output.
"""
port = self.port_show(
uuid='', params='--address {}'.format(self.port['address']))
self.assertEqual(self.port['address'], port['address'])
self.assertEqual(self.port['uuid'], port['uuid'])
self.assertEqual(self.port['node_uuid'], self.node['uuid'])
def test_delete(self):
"""Check baremetal port delete command.
Test steps:
1) Create baremetal port in setUp.
2) Delete baremetal port by UUID.
3) Check that port deleted successfully and not in list.
"""
output = self.port_delete(self.port['uuid'])
self.assertIn('Deleted port {0}'.format(self.port['uuid']), output)
port_list = self.port_list()
self.assertNotIn(self.port['address'],
[port['Address'] for port in port_list])
self.assertNotIn(self.port['uuid'],
[port['UUID'] for port in port_list])
def test_set_unset_extra(self):
"""Check baremetal port set and unset commands.
Test steps:
1) Create baremetal port in setUp.
2) Set extra data for port.
3) Check that baremetal port extra data was set.
4) Unset extra data for port.
5) Check that baremetal port extra data was unset.
"""
extra_key = 'ext'
extra_value = 'testdata'
self.openstack('baremetal port set --extra {0}={1} {2}'
.format(extra_key, extra_value, self.port['uuid']))
show_prop = self.port_show(self.port['uuid'], ['extra'])
self.assertEqual(extra_value, show_prop['extra'][extra_key])
self.openstack('baremetal port unset --extra {0} {1}'
.format(extra_key, self.port['uuid']))
show_prop = self.port_show(self.port['uuid'], ['extra'])
self.assertNotIn(extra_key, show_prop['extra'])
def test_port_create_with_portgroup(self):
"""Create port with specific port group UUID.
Test steps:
1) Create node in setUp().
2) Create a port group.
3) Create a port with specified port group.
4) Check port properties for portgroup_uuid.
"""
api_version = ' --os-baremetal-api-version 1.24'
port_group = self.port_group_create(self.node['uuid'],
params=api_version)
port = self.port_create(
self.node['uuid'],
params='--port-group {0} {1}'.format(port_group['uuid'],
api_version))
self.assertEqual(port_group['uuid'], port['portgroup_uuid'])

@ -1,75 +0,0 @@
# Copyright (c) 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
# 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.
from tempest.lib.common.utils import data_utils
from ironicclient.tests.functional.osc.v1 import base
class BaremetalPortCreate(base.TestCase):
"""Detailed functional tests for baremetal port create command."""
def setUp(self):
super(BaremetalPortCreate, self).setUp()
self.node = self.node_create()
def test_extras(self):
"""Check baremetal port create command with extra data.
Test steps:
1) Create port using solitary and multiple --extra arguments.
2) Check that port successfully created with right extras.
"""
extras = [{'single_extra': 'yes'},
{'k1': 'v1', 'k2': 'v2', 'k3': 'v3'}]
for extra in extras:
params = self.generate_params('--extra', extra)
port = self.port_create(self.node['uuid'], params=params)
self.assert_dict_is_subset(extra, port['extra'])
def test_pxe_1_19(self):
"""Check baremetal port create command with PXE option.
Test steps:
1) Create port using --pxe-enabled argument.
2) Check that port successfully created with right PXE option.
"""
pxe_values = [True, False]
api_version = ' --os-baremetal-api-version 1.19'
for value in pxe_values:
port = self.port_create(
self.node['uuid'],
params='--pxe-enabled {0} {1}'.format(value, api_version))
self.assertEqual(value, port['pxe_enabled'])
def test_llc_1_19(self):
"""Check baremetal port create command with LLC option.
Test steps:
1) Create port using --local-link-connection argument.
2) Check that port successfully created with right LLC data.
"""
fake_port_id = data_utils.rand_name(prefix='ovs-node-')
fake_switch_id = data_utils.rand_mac_address()
llc_value = {"switch_info": "brbm",
"port_id": fake_port_id,
"switch_id": fake_switch_id}
api_version = ' --os-baremetal-api-version 1.19'
params = self.generate_params('--local-link-connection', llc_value)
port = self.port_create(self.node['uuid'],
params='{0} {1}'.format(params, api_version))
self.assert_dict_is_subset(llc_value, port['local_link_connection'])

@ -1,128 +0,0 @@
# Copyright (c) 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
# 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 ddt
from tempest.lib.common.utils import data_utils
from ironicclient.tests.functional.osc.v1 import base
@ddt.ddt
class BaremetalPortGroupTests(base.TestCase):
"""Functional tests for baremetal port group commands."""
def setUp(self):
super(BaremetalPortGroupTests, self).setUp()
self.node = self.node_create()
self.api_version = ' --os-baremetal-api-version 1.25'
self.port_group = self.port_group_create(self.node['uuid'],
params=self.api_version)
def test_create_with_address(self):
"""Check baremetal port group create command with address argument.
Test steps:
1) Create baremetal port group in setUp.
2) Create baremetal port group with specific address argument.
3) Check address of created port group.
"""
mac_address = data_utils.rand_mac_address()
port_group = self.port_group_create(
self.node['uuid'],
params='{0} --address {1}'.format(self.api_version, mac_address))
self.assertEqual(mac_address, port_group['address'])
def test_list(self):
"""Check baremetal port group list command.
Test steps:
1) Create baremetal port group in setUp.
2) List baremetal port groups.
3) Check port group address, UUID and name in port groups list.
"""
port_group_list = self.port_group_list(params=self.api_version)
self.assertIn(self.port_group['uuid'],
[x['UUID'] for x in port_group_list])
self.assertIn(self.port_group['name'],
[x['Name'] for x in port_group_list])
@ddt.data('name', 'uuid')
def test_delete(self, key):
"""Check baremetal port group delete command.
Test steps:
1) Create baremetal port group in setUp.
2) Delete baremetal port group by UUID.
3) Check that port group deleted successfully and not in list.
"""
output = self.port_group_delete(self.port_group[key],
params=self.api_version)
self.assertEqual('Deleted port group {0}'
.format(self.port_group[key]), output.strip())
port_group_list = self.port_group_list(params=self.api_version)
self.assertNotIn(self.port_group['uuid'],
[x['UUID'] for x in port_group_list])
self.assertNotIn(self.port_group['name'],
[x['Name'] for x in port_group_list])
@ddt.data('name', 'uuid')
def test_show(self, key):
"""Check baremetal port group show command.
Test steps:
1) Create baremetal port group in setUp.
2) Show baremetal port group.
3) Check name, uuid and address in port group show output.
"""
port_group = self.port_group_show(
self.port_group[key],
['name', 'uuid', 'address'],
params=self.api_version)
self.assertEqual(self.port_group['name'], port_group['name'])
self.assertEqual(self.port_group['uuid'], port_group['uuid'])
self.assertEqual(self.port_group['address'], port_group['address'])
@ddt.data('name', 'uuid')
def test_set_unset(self, key):
"""Check baremetal port group set and unset commands.
Test steps:
1) Create baremetal port group in setUp.
2) Set extra data for port group.
3) Check that baremetal port group extra data was set.
4) Unset extra data for port group.
5) Check that baremetal port group extra data was unset.
"""
extra_key = 'ext'
extra_value = 'testdata'
self.openstack(
'baremetal port group set --extra {0}={1} {2} {3}'
.format(extra_key, extra_value, self.port_group[key],
self.api_version))
show_prop = self.port_group_show(self.port_group[key], ['extra'],
params=self.api_version)
self.assertEqual(extra_value, show_prop['extra'][extra_key])
self.openstack('baremetal port group unset --extra {0} {1} {2}'
.format(extra_key, self.port_group[key],
self.api_version))
show_prop = self.port_group_show(self.port_group[key], ['extra'],
params=self.api_version)
self.assertNotIn(extra_key, show_prop['extra'])

@ -1,35 +0,0 @@
# 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.
def get_dict_from_output(output):
"""Parse list of dictionaries, return a dictionary.
:param output: list of dictionaries
"""
obj = {}
for item in output:
obj[item['Property']] = str(item['Value'])
return obj
def get_object(object_list, object_value):
"""Get Ironic object by value from list of Ironic objects.
:param object_list: the output of the cmd
:param object_value: value to get
"""
for obj in object_list:
if object_value in obj.values():
return obj

@ -1,54 +0,0 @@
- hosts: all
roles:
- ensure-tox
tasks:
- shell:
cmd: |
set -e
set -x
export BASE='/opt/stack'
export IRONICCLIENT_DIR="$BASE/python-ironicclient"
sudo chmod -R a+rw /opt/stack/
cd $IRONICCLIENT_DIR
set +e
echo "Running ironicclient functional test suite"
# Only admin credentials needed for ironic api
source $BASE/devstack/openrc admin admin
FUNC_TEST_DIR=$IRONICCLIENT_DIR/ironicclient/tests/functional
CONFIG_FILE=$IRONICCLIENT_DIR/test.conf
echo 'Generating configuration file for functional tests'
if [[ -n "$IRONIC_URL" ]]; then
cat <<END >$CONFIG_FILE
[functional]
api_version = 1
auth_strategy=noauth
ironic_url=$IRONIC_URL
END
else
cat <<END >$CONFIG_FILE
[functional]
api_version = 1
os_auth_url=$OS_AUTH_URL
os_identity_api_version=$OS_IDENTITY_API_VERSION
os_username=$OS_USERNAME
os_password=$OS_PASSWORD
os_user_domain_id=$OS_USER_DOMAIN_ID
# os_project_name=$OS_PROJECT_NAME
# os_project_domain_id=$OS_PROJECT_DOMAIN_ID
os_service_type=baremetal
os_endpoint_type=public
os_system_scope=all
END
fi
echo 'Configuration file is in '$CONFIG_FILE''
export IRONICCLIENT_TEST_CONFIG=$CONFIG_FILE
cd $IRONICCLIENT_DIR
echo 'Running Functional Tests under Python3'
{{ tox_executable }} -e functionalpy3
executable: /bin/bash
chdir: '/opt/stack/python-ironicclient'

@ -53,12 +53,6 @@ deps =
-r{toxinidir}/doc/requirements.txt
commands = {posargs}
[testenv:functionalpy3]
passenv = *
setenv = TESTS_DIR=./ironicclient/tests/functional
LANGUAGE=en_US
OS_TESTENV_NAME = {envname}
[testenv:docs]
deps =
-c{env:TOX_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master}

@ -1,39 +1,3 @@
- job:
name: ironicclient-functional
parent: devstack-minimal
irrelevant-files:
- ^.*\.rst$
- ^doc/.*$
- ^ironicclient/locale/.*$
- ^releasenotes/.*$
- ^setup.cfg$
- ^tools/.*$
- ^tox.ini$
required-projects:
- openstack/ironic
- openstack/python-ironicclient
- openstack/keystone
- openstack/tempest
timeout: 4800
post-run: playbooks/functional/run.yaml
vars:
tox_environment:
PYTHONUNBUFFERED: 'true'
tox_envlist: functionalpy3
devstack_plugins:
ironic: https://opendev.org/openstack/ironic
devstack_localrc:
USE_PYTHON3: True
EBTABLES_RACE_FIX: True
IRONIC_ENABLED_NETWORK_INTERFACES: noop
IRONIC_DHCP_PROVIDER: none
IRONIC_DEPLOY_DRIVER: fake
INSTALL_TEMPEST: False
devstack_services:
key: True
mysql: True
rabbit: True
- job:
name: ironicclient-tempest
parent: ironic-base

@ -8,14 +8,6 @@
- release-notes-jobs-python3
check:
jobs:
# NOTE(rpittau): temp non-voting until we fix it
- ironicclient-functional:
voting: false
- ironicclient-tempest
- ironicclient-tox-codespell:
voting: false
gate:
jobs:
# NOTE(rpittau): temp non-voting until we fix it
#- ironicclient-functional
- ironicclient-tempest