Merge "Add sanity tests for testing actions with Node"

This commit is contained in:
Jenkins 2015-12-01 14:12:28 +00:00 committed by Gerrit Code Review
commit ceddac0a20
5 changed files with 360 additions and 77 deletions

View File

@ -1,3 +1,5 @@
# 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
@ -12,16 +14,18 @@
import os
import six
import six.moves.configparser as config_parser
from tempest_lib.cli import base
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()
self.client = self._get_clients()
@ -84,7 +88,7 @@ class FunctionalTestBase(base.ClientTestBase):
return cli_flags
def _cmd_no_auth(self, cmd, action, flags='', params=''):
"""Executes given command with noauth attributes.
"""Execute given command with noauth attributes.
:param cmd: command to be executed
:type cmd: string
@ -103,8 +107,8 @@ class FunctionalTestBase(base.ClientTestBase):
return base.execute(cmd, action, flags, params,
cli_dir=self.client.cli_dir)
def ironic(self, action, flags='', params=''):
"""Executes ironic command for the given action.
def _ironic(self, action, flags='', params=''):
"""Execute ironic command for the given action.
:param action: the cli command to run using Ironic
:type action: string
@ -114,48 +118,124 @@ class FunctionalTestBase(base.ClientTestBase):
:type params: string
"""
flags += ' --os-endpoint-type publicURL'
if hasattr(self, 'os_auth_token'):
return self._cmd_no_auth('ironic', action, flags, params)
else:
return self.client.cmd_with_auth('ironic', action, flags, params)
try:
if hasattr(self, 'os_auth_token'):
return self._cmd_no_auth('ironic', action, flags, params)
else:
return self.client.cmd_with_auth('ironic',
action, flags, params)
except exceptions.CommandFailed as e:
self.fail(e)
def _try_delete_node(self, node_id):
if node_id in self.ironic('node-list'):
self.ironic('node-delete', params=node_id)
def ironic(self, action, flags='', params=''):
"""Return parsed list of dicts with basic item info.
def get_dict_from_output(self, output):
"""Create a dictionary from an output
:param output: the output of the cmd
: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
"""
obj = {}
items = self.parser.listing(output)
for item in items:
obj[item['Property']] = six.text_type(item['Value'])
return obj
output = self._ironic(action=action, flags=flags, params=params)
return self.parser.listing(output)
def create_node(self, params=''):
if not any(dr in params for dr in ('--driver', '-d')):
params += '--driver fake'
node = self.ironic('node-create', params=params)
node = self.get_dict_from_output(node)
self.addCleanup(self._try_delete_node, node['uuid'])
return node
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, output_lines):
"""Verify that output table has headers item listed in field_names.
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 output_lines: output table from cmd
:param table_heades: table headers output from cmd
"""
table = self.parser.table(output_lines)
headers = table['headers']
for field in field_names:
self.assertIn(field, headers)
self.assertEqual(sorted(field_names), sorted(table_headers))
def assertNodeDeleted(self, node_id):
"""Verify that there isn't node with given id.
def assertNodeStates(self, node_show, node_show_states):
"""Assert that node_show_states output corresponds to node_show output.
:param node_id: node id to verify
:param node_show: output from node-show cmd
:param node_show_states: output from node-show-states cmd
"""
self.assertNotIn(node_id, self.ironic('node-list'))
for key in node_show_states.keys():
self.assertEqual(node_show_states[key], node_show[key])
def assertNodeValidate(self, node_validate):
"""Assert that node_validate is able to validate all interfaces present.
: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
"""
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'] != 'available':
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', 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):
self.ironic('node-set-power-state',
params='{0} {1}'.format(node_id, power_state))
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)

View File

@ -1,27 +0,0 @@
# Copyright 2015 Hewlett-Packard Development Company, L.P.
# All Rights Reserved.
#
# 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 import base
class TestIronicClient(base.FunctionalTestBase):
def test_node_create_get_delete(self):
node = self.create_node()
got = self.ironic('node-show', params=node['uuid'])
expected_node = self.get_dict_from_output(got)
self.assertEqual(expected_node['uuid'], node['uuid'])
self.ironic('node-delete', params=node['uuid'])
self.assertNodeDeleted(node['uuid'])

View File

@ -0,0 +1,180 @@
# 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.
from ironicclient.tests.functional import base
import ironicclient.tests.functional.utils as utils
class NodeSanityTestIronicClient(base.FunctionalTestBase):
"""Sanity tests for testing actions with Node.
Smoke test for the Ironic CLI commands which checks basic actions with
node command like create, delete etc.
"""
def setUp(self):
super(NodeSanityTestIronicClient, self).setUp()
self.node = self.create_node()
def test_node_create(self):
"""Test steps:
1) create node
2) check that node has been successfully created
"""
self.assertIn(self.node['uuid'], self.get_nodes_uuids_from_node_list())
def test_node_show(self):
"""Test steps:
1) create node
2) check that created node UUID equals to the one present
in node-show output
"""
node_show = self.show_node(self.node['uuid'])
self.assertEqual(self.node['uuid'], node_show['uuid'])
def test_node_delete(self):
"""Test steps:
1) create node
2) check that it was created
3) delete node
4) check that node has been successfully deleted
"""
self.assertIn(self.node['uuid'], self.get_nodes_uuids_from_node_list())
self.delete_node(self.node['uuid'])
self.assertNotIn(self.node['uuid'],
self.get_nodes_uuids_from_node_list())
def test_node_update(self):
"""Test steps:
1) create node
2) update node name
3) check that node name has been successfully updated
"""
node_name = utils.generate_name('test')
updated_node = self.update_node(self.node['uuid'],
'add name={0}'.format(node_name))
self.assertEqual(node_name, updated_node['name'])
def test_node_set_console_mode(self):
"""Test steps:
1) create node
2) check that console_enabled is False
3) set node console mode to True
4) check that node console mode has been successfully updated
"""
node_show = self.show_node(self.node['uuid'])
self.assertEqual('False', node_show['console_enabled'])
self.ironic('node-set-console-mode',
params='{0} true'.format(self.node['uuid']))
node_show = self.show_node(self.node['uuid'])
self.assertEqual('True', node_show['console_enabled'])
def test_node_get_console(self):
"""Test steps:
1) create node
2) check console mode using node-show
3) get console mode using node-get-console
4) check that node-get-console value equals node-show value
"""
node_show = self.show_node(self.node['uuid'])
node_get = self.ironic('node-get-console', params=self.node['uuid'])
node_get = utils.get_dict_from_output(node_get)
self.assertEqual(node_show['console_enabled'],
node_get['console_enabled'])
def test_node_set_maintenance(self):
"""Test steps:
1) create node
2) check that maintenance is False
3) put node to maintenance
4) check that node is in maintenance
5) check that maintenance reason has been successfully updated
"""
node_show = self.show_node(self.node['uuid'])
self.assertEqual('False', node_show['maintenance'])
self.set_node_maintenance(
self.node['uuid'],
"true --reason 'Testing node-set power state command'")
node_show = self.show_node(self.node['uuid'])
self.assertEqual('True', node_show['maintenance'])
self.assertEqual('Testing node-set power state command',
node_show['maintenance_reason'])
def test_node_set_power_state(self):
"""Test steps:
1) create node
2) check that power state is None
3) set power state to On
4) check that power state has been changed successfully
"""
node_show = self.show_node(self.node['uuid'])
self.assertEqual('None', node_show['power_state'])
self.set_node_power_state(self.node['uuid'], "off")
node_show = self.show_node(self.node['uuid'])
self.assertEqual('power off', node_show['power_state'])
def test_node_set_provision_state(self):
"""Test steps:
1) create node
2) check that provision state is 'available'
3) set new provision state to the node
4) check that provision state has been updated successfully
"""
node_show = self.show_node(self.node['uuid'])
self.assertEqual('available', node_show['provision_state'])
self.set_node_provision_state(self.node['uuid'], 'active')
node_show = self.show_node(self.node['uuid'])
self.assertEqual('active', node_show['provision_state'])
def test_node_validate(self):
"""Test steps:
1) create node
2) validate node
"""
node_validate = self.validate_node(self.node['uuid'])
self.assertNodeValidate(node_validate)
def test_show_node_states(self):
"""Test steps:
1) create node
2) check that states returned by node-show and node-show-states
are the same
"""
node_show = self.show_node(self.node['uuid'])
show_node_states = self.show_node_states(self.node['uuid'])
self.assertNodeStates(node_show, show_node_states)

View File

@ -1,3 +1,5 @@
# 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
@ -21,40 +23,40 @@ class TableStructureIronicCLITests(base.FunctionalTestBase):
"""
def test_chassis_list_table_structure(self):
"""Test scenario:
"""Test steps:
1) get chassis-list
2) check table structure
"""
chassis_list = self.ironic('chassis-list')
self.assertTableHeaders(['Description', 'UUID'], chassis_list)
chassis_list_header = self.get_table_headers('chassis-list')
self.assertTableHeaders(['Description', 'UUID'], chassis_list_header)
def test_node_list_table_structure(self):
"""Test scenario:
"""Test steps:
1) get node-list
2) check table structure
"""
node_list = self.ironic('node-list')
node_list_header = self.get_table_headers('node-list')
self.assertTableHeaders(['UUID', 'Name', 'Instance UUID',
'Power State', 'Provisioning State',
'Maintenance'], node_list)
'Maintenance'], node_list_header)
def test_port_list_table_structure(self):
"""Test scenario:
"""Test steps:
1) get port-list
2) check table structure
"""
port_list = self.ironic('port-list')
self.assertTableHeaders(['UUID', 'Address'], port_list)
port_list_header = self.get_table_headers('port-list')
self.assertTableHeaders(['UUID', 'Address'], port_list_header)
def test_driver_list_table_structure(self):
"""Test scenario:
"""Test steps:
1) get driver-list
2) check table structure
"""
driver_list = self.ironic('driver-list')
driver_list_header = self.get_table_headers('driver-list')
self.assertTableHeaders(['Supported driver(s)', 'Active host(s)'],
driver_list)
driver_list_header)

View File

@ -0,0 +1,48 @@
# Copyright (c) 2015 Mirantis, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import uuid
import six
def get_dict_from_output(output):
"""Parce list of dictonaries, return dictonary.
:param output: list of dictonaries
"""
obj = {}
for item in output:
obj[item['Property']] = six.text_type(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
def generate_name(prefix='test'):
"""Generate name for objects.
:param prefix: prefix of the generated name
"""
suffix = uuid.uuid4().hex
return "{0}-{1}".format(prefix, suffix)