From e759386c53b91fdc68f2227cb7f315bf68b1aaf5 Mon Sep 17 00:00:00 2001 From: Alex Katz Date: Thu, 22 Oct 2020 18:11:03 +0300 Subject: [PATCH] Add openstack client tests We need to test openstack client as it may differ from the openstack API. Added some new openstack client tests together with the module to execute openstack commands on the undercloud node. Change-Id: Ia4960385c7f2b7565a5e9a5888a9cb5613f45520 --- extra-requirements.txt | 5 +- tobiko/openstack/openstackclient/__init__.py | 63 ++++++ tobiko/openstack/openstackclient/_client.py | 77 +++++++ .../openstack/openstackclient/_exception.py | 34 +++ tobiko/openstack/openstackclient/_network.py | 51 +++++ tobiko/openstack/openstackclient/_port.py | 52 +++++ .../openstackclient/_security_group.py | 51 +++++ .../openstackclient/_security_group_rule.py | 42 ++++ tobiko/openstack/openstackclient/_subnet.py | 52 +++++ tobiko/shell/sh/__init__.py | 1 + tobiko/tests/scenario/neutron/test_cli.py | 199 ++++++++++++++++++ tobiko/tripleo/__init__.py | 1 + 12 files changed, 626 insertions(+), 2 deletions(-) create mode 100644 tobiko/openstack/openstackclient/__init__.py create mode 100644 tobiko/openstack/openstackclient/_client.py create mode 100644 tobiko/openstack/openstackclient/_exception.py create mode 100644 tobiko/openstack/openstackclient/_network.py create mode 100644 tobiko/openstack/openstackclient/_port.py create mode 100644 tobiko/openstack/openstackclient/_security_group.py create mode 100644 tobiko/openstack/openstackclient/_security_group_rule.py create mode 100644 tobiko/openstack/openstackclient/_subnet.py create mode 100644 tobiko/tests/scenario/neutron/test_cli.py diff --git a/extra-requirements.txt b/extra-requirements.txt index 4034fd07a..59339e08f 100644 --- a/extra-requirements.txt +++ b/extra-requirements.txt @@ -1,2 +1,3 @@ -pandas # BSD -validations-libs # APACHE-2.0 +pandas # BSD +python-openstackclient # APACHE-2.0 +validations-libs # APACHE-2.0 diff --git a/tobiko/openstack/openstackclient/__init__.py b/tobiko/openstack/openstackclient/__init__.py new file mode 100644 index 000000000..868cf7b81 --- /dev/null +++ b/tobiko/openstack/openstackclient/__init__.py @@ -0,0 +1,63 @@ +# Copyright (c) 2020 Red Hat, Inc. +# +# 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 __future__ import absolute_import + +from tobiko.openstack.openstackclient import _exception +from tobiko.openstack.openstackclient import _client +from tobiko.openstack.openstackclient import _network +from tobiko.openstack.openstackclient import _port +from tobiko.openstack.openstackclient import _security_group +from tobiko.openstack.openstackclient import _security_group_rule +from tobiko.openstack.openstackclient import _subnet + + +OSPCliError = _exception.OSPCliAuthError +OSPCliAuthError = _exception.OSPCliAuthError + +execute = _client.execute + +network_list = _network.network_list +network_show = _network.network_show +network_create = _network.network_create +network_delete = _network.network_delete +network_set = _network.network_set +network_unset = _network.network_unset + +port_list = _port.port_list +port_show = _port.port_show +port_create = _port.port_create +port_delete = _port.port_delete +port_set = _port.port_set +port_unset = _port.port_unset + +security_group_list = _security_group.security_group_list +security_group_show = _security_group.security_group_show +security_group_create = _security_group.security_group_create +security_group_delete = _security_group.security_group_delete +security_group_set = _security_group.security_group_set +security_group_unset = _security_group.security_group_unset + +security_group_rule_list = _security_group_rule.security_group_rule_list +security_group_rule_show = _security_group_rule.security_group_rule_show +security_group_rule_create = _security_group_rule.security_group_rule_create +security_group_rule_delete = _security_group_rule.security_group_rule_delete + +subnet_list = _subnet.subnet_list +subnet_show = _subnet.subnet_show +subnet_create = _subnet.subnet_create +subnet_delete = _subnet.subnet_delete +subnet_set = _subnet.subnet_set +subnet_unset = _subnet.subnet_unset diff --git a/tobiko/openstack/openstackclient/_client.py b/tobiko/openstack/openstackclient/_client.py new file mode 100644 index 000000000..5ae1c0d2e --- /dev/null +++ b/tobiko/openstack/openstackclient/_client.py @@ -0,0 +1,77 @@ +# Copyright (c) 2020 Red Hat, Inc. +# +# 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 __future__ import absolute_import + +import json + +from oslo_log import log + +from tobiko.openstack import keystone +from tobiko.openstack.openstackclient import _exception +from tobiko.shell import sh +import tobiko.tripleo + + +LOG = log.getLogger(__name__) + + +def execute(cmd, *args, **kwargs): + arg_list = _param_list(*args, **kwargs) + cmd_to_exec = cmd.format(params=' '.join(arg_list)) + if tobiko.tripleo.has_undercloud(): + ssh_client = tobiko.tripleo.undercloud_ssh_client() + else: + ssh_client = None + try: + LOG.debug(f'Command to be executed:\n{cmd_to_exec}') + result = sh.execute(cmd_to_exec, ssh_client=ssh_client) + except sh.ShellCommandFailed as ex: + if ex.exit_status == 1: + raise _exception.OSPCliApiError(message=f'{ex.stderr}') + elif ex.exit_status == 2: + raise _exception.OSPCliClientError(message=f'{ex.stderr}') + else: + raise + output_format = kwargs.pop('format', '') + if output_format == 'json': + return json.loads(result.stdout) + else: + return dict() + + +def _param_list(*args, **kwargs): + if not any(param in kwargs for param in ['os-token', 'os-username']): + credentials = keystone.get_keystone_credentials() + kwargs['os-auth-url'] = credentials.auth_url + kwargs['os-password'] = credentials.password + kwargs['os-username'] = credentials.username + kwargs['os-project-name'] = credentials.project_name + if credentials.api_version == 3: + kwargs['os-user-domain-name'] = credentials.user_domain_name + kwargs['os-project-domain-name'] = credentials.project_domain_name + kwargs['os-identity-api-version'] = credentials.api_version + arg_list = [] + for arg in args: + if len(arg) == 1: + arg_list.append(f'-{arg}') + else: + arg_list.append(f'--{arg}') + for arg, value in kwargs.items(): + if len(arg) == 1: + arg_list.append(f'-{arg} {value}') + else: + arg_list.append(f'--{arg} {value}') + return arg_list diff --git a/tobiko/openstack/openstackclient/_exception.py b/tobiko/openstack/openstackclient/_exception.py new file mode 100644 index 000000000..a82c20ea3 --- /dev/null +++ b/tobiko/openstack/openstackclient/_exception.py @@ -0,0 +1,34 @@ +# Copyright (c) 2020 Red Hat, Inc. +# +# 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 __future__ import absolute_import + +import tobiko + + +class OSPCliError(tobiko.TobikoException): + pass + + +class OSPCliAuthError(OSPCliError): + pass + + +class OSPCliClientError(OSPCliError): + pass + + +class OSPCliApiError(OSPCliError): + pass diff --git a/tobiko/openstack/openstackclient/_network.py b/tobiko/openstack/openstackclient/_network.py new file mode 100644 index 000000000..1af0e03d8 --- /dev/null +++ b/tobiko/openstack/openstackclient/_network.py @@ -0,0 +1,51 @@ +# Copyright (c) 2020 Red Hat, Inc. +# +# 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 __future__ import absolute_import + +from tobiko.openstack.openstackclient import _client + + +def network_list(*args, **kwargs): + cmd = 'openstack network list {params}' + kwargs['format'] = 'json' + return _client.execute(cmd, *args, **kwargs) + + +def network_show(network, *args, **kwargs): + cmd = f'openstack network show {{params}} {network}' + kwargs['format'] = 'json' + return _client.execute(cmd, *args, **kwargs) + + +def network_create(net_name, *args, **kwargs): + cmd = f'openstack network create {{params}} {net_name}' + kwargs['format'] = 'json' + return _client.execute(cmd, *args, **kwargs) + + +def network_delete(networks, *args, **kwargs): + cmd = f'openstack network delete {{params}} {" ".join(networks)}' + return _client.execute(cmd, *args, **kwargs) + + +def network_set(network, *args, **kwargs): + cmd = f'openstack network set {{params}} {network}' + return _client.execute(cmd, *args, **kwargs) + + +def network_unset(network, *args, **kwargs): + cmd = f'openstack network unset {{params}} {network}' + return _client.execute(cmd, *args, **kwargs) diff --git a/tobiko/openstack/openstackclient/_port.py b/tobiko/openstack/openstackclient/_port.py new file mode 100644 index 000000000..b08f02ffe --- /dev/null +++ b/tobiko/openstack/openstackclient/_port.py @@ -0,0 +1,52 @@ +# Copyright (c) 2020 Red Hat, Inc. +# +# 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 __future__ import absolute_import + +from tobiko.openstack.openstackclient import _client + + +def port_list(*args, **kwargs): + cmd = 'openstack port list {params}' + kwargs['format'] = 'json' + return _client.execute(cmd, *args, **kwargs) + + +def port_show(port, *args, **kwargs): + cmd = f'openstack port show {{params}} {port}' + kwargs['format'] = 'json' + return _client.execute(cmd, *args, **kwargs) + + +def port_create(port_name, network_name, *args, **kwargs): + cmd = f'openstack port create {{params}} --network {network_name} '\ + f'{port_name}' + kwargs['format'] = 'json' + return _client.execute(cmd, *args, **kwargs) + + +def port_delete(ports, *args, **kwargs): + cmd = f'openstack port delete {{params}} {" ".join(ports)}' + return _client.execute(cmd, *args, **kwargs) + + +def port_set(port, *args, **kwargs): + cmd = f'openstack port set {{params}} {port}' + return _client.execute(cmd, *args, **kwargs) + + +def port_unset(port, *args, **kwargs): + cmd = f'openstack port unset {{params}} {port}' + return _client.execute(cmd, *args, **kwargs) diff --git a/tobiko/openstack/openstackclient/_security_group.py b/tobiko/openstack/openstackclient/_security_group.py new file mode 100644 index 000000000..482355dc2 --- /dev/null +++ b/tobiko/openstack/openstackclient/_security_group.py @@ -0,0 +1,51 @@ +# Copyright (c) 2020 Red Hat, Inc. +# +# 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 __future__ import absolute_import + +from tobiko.openstack.openstackclient import _client + + +def security_group_list(*args, **kwargs): + cmd = 'openstack security group list {params}' + kwargs['format'] = 'json' + return _client.execute(cmd, *args, **kwargs) + + +def security_group_show(group, *args, **kwargs): + cmd = f'openstack security group show {{params}} {group}' + kwargs['format'] = 'json' + return _client.execute(cmd, *args, **kwargs) + + +def security_group_create(group_name, *args, **kwargs): + cmd = f'openstack security group create {{params}} {group_name}' + kwargs['format'] = 'json' + return _client.execute(cmd, *args, **kwargs) + + +def security_group_delete(groups, *args, **kwargs): + cmd = f'openstack security group delete {{params}} {" ".join(groups)}' + return _client.execute(cmd, *args, **kwargs) + + +def security_group_set(group, *args, **kwargs): + cmd = f'openstack security group set {{params}} {group}' + return _client.execute(cmd, *args, **kwargs) + + +def security_group_unset(group, *args, **kwargs): + cmd = f'openstack security group unset {{params}} {group}' + return _client.execute(cmd, *args, **kwargs) diff --git a/tobiko/openstack/openstackclient/_security_group_rule.py b/tobiko/openstack/openstackclient/_security_group_rule.py new file mode 100644 index 000000000..dfdd40efd --- /dev/null +++ b/tobiko/openstack/openstackclient/_security_group_rule.py @@ -0,0 +1,42 @@ +# Copyright (c) 2020 Red Hat, Inc. +# +# 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 __future__ import absolute_import + +from tobiko.openstack.openstackclient import _client + + +def security_group_rule_list(*args, **kwargs): + group = kwargs.pop('group', '') + cmd = f'openstack security group rule list {{params}} {group}' + kwargs['format'] = 'json' + return _client.execute(cmd, *args, **kwargs) + + +def security_group_rule_show(rule, *args, **kwargs): + cmd = f'openstack security group rule show {{params}} {rule}' + kwargs['format'] = 'json' + return _client.execute(cmd, *args, **kwargs) + + +def security_group_rule_create(group, *args, **kwargs): + cmd = f'openstack security group rule create {{params}} {group}' + kwargs['format'] = 'json' + return _client.execute(cmd, *args, **kwargs) + + +def security_group_rule_delete(rules, *args, **kwargs): + cmd = f'openstack security group rule delete {{params}} {" ".join(rules)}' + return _client.execute(cmd, *args, **kwargs) diff --git a/tobiko/openstack/openstackclient/_subnet.py b/tobiko/openstack/openstackclient/_subnet.py new file mode 100644 index 000000000..4c9e5e713 --- /dev/null +++ b/tobiko/openstack/openstackclient/_subnet.py @@ -0,0 +1,52 @@ +# Copyright (c) 2020 Red Hat, Inc. +# +# 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 __future__ import absolute_import + +from tobiko.openstack.openstackclient import _client + + +def subnet_list(*args, **kwargs): + cmd = 'openstack subnet list {params}' + kwargs['format'] = 'json' + return _client.execute(cmd, *args, **kwargs) + + +def subnet_show(subnet, *args, **kwargs): + cmd = f'openstack subnet show {{params}} {subnet}' + kwargs['format'] = 'json' + return _client.execute(cmd, *args, **kwargs) + + +def subnet_create(subnet_name, network_name, *args, **kwargs): + cmd = f'openstack subnet create {{params}} --network '\ + f'{network_name} {subnet_name}' + kwargs['format'] = 'json' + return _client.execute(cmd, *args, **kwargs) + + +def subnet_delete(subnets, *args, **kwargs): + cmd = f'openstack subnet delete {{params}} {" ".join(subnets)}' + return _client.execute(cmd, *args, **kwargs) + + +def subnet_set(subnet, *args, **kwargs): + cmd = f'openstack subnet set {{params}} {subnet}' + return _client.execute(cmd, *args, **kwargs) + + +def subnet_unset(subnet, *args, **kwargs): + cmd = f'openstack subnet unset {{params}} {subnet}' + return _client.execute(cmd, *args, **kwargs) diff --git a/tobiko/shell/sh/__init__.py b/tobiko/shell/sh/__init__.py index 3d41673bb..8c2bc74b7 100644 --- a/tobiko/shell/sh/__init__.py +++ b/tobiko/shell/sh/__init__.py @@ -54,6 +54,7 @@ LocalShellProcessFixture = _local.LocalShellProcessFixture LocalExecutePathFixture = _local.LocalExecutePathFixture process = _process.process +str_from_stream = _process.str_from_stream ShellProcessFixture = _process.ShellProcessFixture PsError = _ps.PsError diff --git a/tobiko/tests/scenario/neutron/test_cli.py b/tobiko/tests/scenario/neutron/test_cli.py new file mode 100644 index 000000000..383e4b692 --- /dev/null +++ b/tobiko/tests/scenario/neutron/test_cli.py @@ -0,0 +1,199 @@ +# Copyright (c) 2019 Red Hat +# 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 __future__ import absolute_import + +import random + +import testtools +from oslo_log import log + +from tobiko.openstack import neutron +from tobiko.openstack import openstackclient + + +LOG = log.getLogger(__name__) + + +class BaseCliTest(testtools.TestCase): + + def setUp(self): + super(BaseCliTest, self).setUp() + self.api = neutron.get_neutron_client() + + def api_network_delete(self, network): + nets = self.api.list_networks()['networks'] + for net in nets: + if net['name'] == network: + self.api.delete_network(net['id']) + break + if net['id'] == network: + self.api.delete_network(network) + break + + def api_subnet_delete(self, subnet_name): + subnets = self.api.list_subnets()['subnets'] + for subnet in subnets: + if subnet['name'] == subnet_name: + self.api.delete_subnet(subnet['id']) + break + if subnet['id'] == subnet_name: + self.api.delete_subnet(subnet_name) + break + + def api_port_delete(self, port_name): + ports = self.api.list_ports()['ports'] + for port in ports: + if port['name'] == port_name: + self.api.delete_port(port['id']) + break + if port['id'] == port_name: + self.api.delete_port(port_name) + break + + def api_random_port_create(self): + net_name = self.random_name() + port_name = self.random_name() + network = self.api.create_network({'network': {'name': net_name}}) + self.addCleanup(self.api_network_delete, net_name) + network_id = network['network']['id'] + self.api.create_port({'port': {'name': port_name, + 'network_id': network_id}}) + self.addCleanup(self.api_port_delete, port_name) + return port_name + + def api_random_subnet_create(self): + net_name = self.random_name() + subnet_name = self.random_name() + network = self.api.create_network({'network': {'name': net_name}}) + self.addCleanup(self.api_network_delete, net_name) + network_id = network['network']['id'] + self.api.create_subnet({'subnet': {'name': subnet_name, + 'network_id': network_id, + 'ip_version': 4, + 'cidr': '123.123.123.0/24'}}) + return subnet_name + + def api_random_network_create(self): + name = self.random_name() + self.api.create_network({'network': {'name': name}}) + self.addCleanup(self.api_network_delete, name) + return name + + def random_name(self, length=16): + letters = 'abcdefghijklmnopqrstuvwxyz' + random_string = ''.join(random.choice(letters) for i in range(length)) + return f'{self.__class__.__name__}-{random_string}' + + +class NeutronCliNetwork(BaseCliTest): + + def test_network_creation(self): + net_name = self.random_name() + output = openstackclient.network_create(net_name) + self.addCleanup(self.api_network_delete, net_name) + self.assertEqual(output['name'], net_name) # pylint: disable=E1126 + self.assertEqual(output['status'], 'ACTIVE') # pylint: disable=E1126 + + def test_network_deletion(self): + net_name_1 = self.api_random_network_create() + net_name_2 = self.api_random_network_create() + openstackclient.network_delete([net_name_1, net_name_2]) + nets = self.api.list_networks()['networks'] + for net in nets: + self.assertNotEqual(net['name'], net_name_1) + self.assertNotEqual(net['name'], net_name_2) + + def test_network_list(self): + net_name = self.api_random_network_create() + nets = openstackclient.network_list() + found = False + for net in nets: + if net['Name'] == net_name: + found = True + break + self.assertTrue(found) + + def test_network_show(self): + net_name = self.api_random_network_create() + net = openstackclient.network_show(net_name) + self.assertEqual(net['name'], net_name) # pylint: disable=E1126 + + +class NeutronCliSubnet(BaseCliTest): + + def test_subnet_creation(self): + subnet_name = self.random_name() + net_name = self.api_random_network_create() + output = openstackclient.subnet_create( + subnet_name, net_name, **{'subnet-range': '123.123.123.0/24'}) + self.assertEqual(output['name'], subnet_name) # pylint: disable=E1126 + + def test_subnet_deletion(self): + subnet_name_1 = self.api_random_subnet_create() + subnet_name_2 = self.api_random_subnet_create() + openstackclient.subnet_delete([subnet_name_1, subnet_name_2]) + subnets = self.api.list_subnets()['subnets'] + for subnet in subnets: + self.assertNotEqual(subnet['name'], subnet_name_1) + self.assertNotEqual(subnet['name'], subnet_name_2) + + def test_subnet_list(self): + subnet_name = self.api_random_subnet_create() + subnets = openstackclient.subnet_list() + found = False + for subnet in subnets: + if subnet['Name'] == subnet_name: + found = True + break + self.assertTrue(found) + + def test_subnet_show(self): + subnet_name = self.api_random_subnet_create() + subnet = openstackclient.subnet_show(subnet_name) + self.assertEqual(subnet['name'], subnet_name) # pylint: disable=E1126 + + +class NeutronCliPort(BaseCliTest): + + def test_port_creation(self): + port_name = self.random_name() + net_name = self.api_random_network_create() + output = openstackclient.port_create(port_name, net_name) + self.addCleanup(self.api_port_delete, port_name) + self.assertEqual(output['name'], port_name) # pylint: disable=E1126 + + def test_port_deletion(self): + port_name_1 = self.api_random_port_create() + port_name_2 = self.api_random_port_create() + openstackclient.port_delete([port_name_1, port_name_2]) + ports = self.api.list_ports()['ports'] + for port in ports: + self.assertNotEqual(port['name'], port_name_1) + self.assertNotEqual(port['name'], port_name_2) + + def test_port_list(self): + port_name = self.api_random_port_create() + ports = openstackclient.port_list() + found = False + for port in ports: + if port['Name'] == port_name: + found = True + break + self.assertTrue(found) + + def test_port_show(self): + port_name = self.api_random_port_create() + port = openstackclient.port_show(port_name) + self.assertEqual(port['name'], port_name) # pylint: disable=E1126 diff --git a/tobiko/tripleo/__init__.py b/tobiko/tripleo/__init__.py index 26cff75f8..d1aac2d69 100644 --- a/tobiko/tripleo/__init__.py +++ b/tobiko/tripleo/__init__.py @@ -38,6 +38,7 @@ skip_if_missing_overcloud = overcloud.skip_if_missing_overcloud TripleoTopology = topology.TripleoTopology load_undercloud_rcfile = undercloud.load_undercloud_rcfile +has_undercloud = undercloud.has_undercloud skip_if_missing_undercloud = undercloud.skip_if_missing_undercloud undercloud_host_config = undercloud.undercloud_host_config undercloud_keystone_client = undercloud.undercloud_keystone_client