Add Metalsmith client
In OSP-17 and newer, there is no Nova running as undercloud service and instead of Nova client, Metalsmith client has to be used to e.g. get overcloud nodes and its IP addresses. This adds Metalsmith client with Metalsmith client support Change-Id: Iaeef3e87a29513e97f1702085928aa05e1aa82ad
This commit is contained in:
parent
24230f8ecf
commit
682011c1f6
@ -5,6 +5,7 @@ docker==4.4.1
|
||||
fixtures==3.0.0
|
||||
Jinja2==2.11.2
|
||||
keystoneauth1==4.3.0
|
||||
metalsmith==1.6.2
|
||||
mock==3.0.5
|
||||
netaddr==0.8.0
|
||||
neutron-lib==2.7.0
|
||||
|
@ -6,6 +6,7 @@ docker>=4.4.1 # Apache-2.0
|
||||
fixtures>=3.0.0 # Apache-2.0/BSD
|
||||
Jinja2>=2.11.2 # BSD
|
||||
keystoneauth1>=4.3.0 # Apache-2.0
|
||||
metalsmith>=1.6.2 # Apache-2.0
|
||||
netaddr>=0.8.0 # BSD
|
||||
neutron-lib>=2.7.0 # Apache-2.0
|
||||
oslo.config>=8.4.0 # Apache-2.0
|
||||
|
31
tobiko/openstack/metalsmith/__init__.py
Normal file
31
tobiko/openstack/metalsmith/__init__.py
Normal file
@ -0,0 +1,31 @@
|
||||
# Copyright 2022 Red Hat
|
||||
#
|
||||
# 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.metalsmith import _client
|
||||
from tobiko.openstack.metalsmith import _instance
|
||||
|
||||
|
||||
CLIENT_CLASSES = _client.CLIENT_CLASSES
|
||||
MetalsmithClient = _client.MetalsmithClient
|
||||
MetalsmithClientFixture = _client.MetalsmithClientFixture
|
||||
MetalsmithClientType = _client.MetalsmithClientType
|
||||
metalsmith_client = _client.metalsmith_client
|
||||
get_metalsmith_client = _client.get_metalsmith_client
|
||||
|
||||
MetalsmithInstance = _instance.MetalsmithInstance
|
||||
list_instances = _instance.list_instances
|
||||
find_instance = _instance.find_instance
|
||||
list_instance_ip_addresses = _instance.list_instance_ip_addresses
|
||||
find_instance_ip_address = _instance.find_instance_ip_address
|
88
tobiko/openstack/metalsmith/_client.py
Normal file
88
tobiko/openstack/metalsmith/_client.py
Normal file
@ -0,0 +1,88 @@
|
||||
# Copyright 2022 Red Hat
|
||||
#
|
||||
# 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 typing
|
||||
|
||||
import metalsmith
|
||||
from oslo_log import log
|
||||
|
||||
import tobiko
|
||||
from tobiko.openstack import keystone
|
||||
from tobiko.openstack import _client
|
||||
|
||||
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
|
||||
CLIENT_CLASSES = (metalsmith.Provisioner,)
|
||||
MetalsmithClient = typing.Union[metalsmith.Provisioner]
|
||||
|
||||
|
||||
class MetalsmithClientFixture(_client.OpenstackClientFixture):
|
||||
|
||||
def init_client(self, session) -> MetalsmithClient:
|
||||
return metalsmith.Provisioner(session=session)
|
||||
|
||||
|
||||
class MetalsmithClientManager(_client.OpenstackClientManager):
|
||||
|
||||
def create_client(self, session) -> MetalsmithClientFixture:
|
||||
return MetalsmithClientFixture(session=session)
|
||||
|
||||
|
||||
CLIENTS = MetalsmithClientManager()
|
||||
|
||||
|
||||
def metalsmith_client_manager(manager: MetalsmithClientManager = None) \
|
||||
-> MetalsmithClientManager:
|
||||
if manager is None:
|
||||
manager = CLIENTS
|
||||
return manager
|
||||
|
||||
|
||||
MetalsmithClientType = typing.Union[
|
||||
MetalsmithClient,
|
||||
MetalsmithClientFixture,
|
||||
typing.Type[MetalsmithClientFixture]]
|
||||
|
||||
|
||||
def metalsmith_client(obj: MetalsmithClientType = None) \
|
||||
-> MetalsmithClient:
|
||||
if obj is None:
|
||||
return get_metalsmith_client()
|
||||
|
||||
if isinstance(obj, CLIENT_CLASSES):
|
||||
return obj
|
||||
|
||||
fixture = tobiko.setup_fixture(obj)
|
||||
if isinstance(fixture, MetalsmithClientFixture):
|
||||
assert fixture.client is not None
|
||||
return fixture.client
|
||||
|
||||
message = f"Object '{obj}' is not a MetalsmithProvisionerFixture"
|
||||
raise TypeError(message)
|
||||
|
||||
|
||||
def get_metalsmith_client(session: keystone.KeystoneSessionType = None,
|
||||
shared=True,
|
||||
init_client=None,
|
||||
manager: MetalsmithClientManager = None) \
|
||||
-> MetalsmithClient:
|
||||
manager = metalsmith_client_manager(manager)
|
||||
client = manager.get_client(session=session,
|
||||
shared=shared,
|
||||
init_client=init_client)
|
||||
tobiko.setup_fixture(client)
|
||||
return client.client
|
81
tobiko/openstack/metalsmith/_instance.py
Normal file
81
tobiko/openstack/metalsmith/_instance.py
Normal file
@ -0,0 +1,81 @@
|
||||
# Copyright 2022 Red Hat
|
||||
#
|
||||
# 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 typing
|
||||
|
||||
import metalsmith
|
||||
import netaddr
|
||||
|
||||
import tobiko
|
||||
from tobiko.shell import ping
|
||||
from tobiko.shell import ssh
|
||||
from tobiko.openstack.metalsmith import _client
|
||||
|
||||
|
||||
MetalsmithInstance = typing.Union[metalsmith.Instance]
|
||||
|
||||
|
||||
def list_instances(client: _client.MetalsmithClientType = None,
|
||||
**params) \
|
||||
-> tobiko.Selection[MetalsmithInstance]:
|
||||
instances = tobiko.select(
|
||||
_client.metalsmith_client(client).list_instances())
|
||||
if params:
|
||||
instances = instances.with_attributes(**params)
|
||||
return instances
|
||||
|
||||
|
||||
def find_instance(client: _client.MetalsmithClientType = None,
|
||||
unique=False, **params) -> MetalsmithInstance:
|
||||
servers = list_instances(client=client, **params)
|
||||
if unique:
|
||||
return servers.unique
|
||||
else:
|
||||
return servers.first
|
||||
|
||||
|
||||
def list_instance_ip_addresses(instance: MetalsmithInstance,
|
||||
ip_version: int = None,
|
||||
network_name: str = None,
|
||||
check_connectivity=False,
|
||||
ssh_client: ssh.SSHClientType = None)\
|
||||
-> tobiko.Selection[netaddr.IPAddress]:
|
||||
ip_addresses = tobiko.Selection[netaddr.IPAddress]()
|
||||
for _network, addresses in instance.ip_addresses().items():
|
||||
if network_name not in [None, _network]:
|
||||
continue
|
||||
|
||||
for address in addresses:
|
||||
ip_address = netaddr.IPAddress(address)
|
||||
if ip_version not in [None, ip_address.version]:
|
||||
continue
|
||||
ip_addresses.append(ip_address)
|
||||
|
||||
# check ICMP connectivity
|
||||
if check_connectivity:
|
||||
ip_addresses = ping.list_reachable_hosts(
|
||||
ip_addresses, ssh_client=ssh_client)
|
||||
|
||||
return ip_addresses
|
||||
|
||||
|
||||
def find_instance_ip_address(instance: MetalsmithInstance,
|
||||
unique=False,
|
||||
**params) -> netaddr.IPAddress:
|
||||
addresses = list_instance_ip_addresses(instance=instance, **params)
|
||||
if unique:
|
||||
return addresses.unique
|
||||
else:
|
||||
return addresses.first
|
0
tobiko/tests/unit/openstack/metalsmith/__init__.py
Normal file
0
tobiko/tests/unit/openstack/metalsmith/__init__.py
Normal file
47
tobiko/tests/unit/openstack/metalsmith/test_client.py
Normal file
47
tobiko/tests/unit/openstack/metalsmith/test_client.py
Normal file
@ -0,0 +1,47 @@
|
||||
# Copyright 2022 Red Hat
|
||||
#
|
||||
# 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 import keystone
|
||||
from tobiko.openstack import metalsmith
|
||||
from tobiko.tests.unit import openstack
|
||||
from tobiko.tests.unit.openstack import test_client
|
||||
|
||||
|
||||
class MetalsmithClientFixtureTest(test_client.OpenstackClientFixtureTest):
|
||||
|
||||
def create_client(self, session=None):
|
||||
return metalsmith.MetalsmithClientFixture(session=session)
|
||||
|
||||
|
||||
class GetMetalsmithClientTest(openstack.OpenstackTest):
|
||||
|
||||
def test_get_metalsmith_client(self, session=None, shared=True):
|
||||
client1 = metalsmith.get_metalsmith_client(
|
||||
session=session, shared=shared)
|
||||
client2 = metalsmith.get_metalsmith_client(
|
||||
session=session, shared=shared)
|
||||
if shared:
|
||||
self.assertIs(client1, client2)
|
||||
else:
|
||||
self.assertIsNot(client1, client2)
|
||||
self.assertIsInstance(client1, metalsmith.CLIENT_CLASSES)
|
||||
self.assertIsInstance(client2, metalsmith.CLIENT_CLASSES)
|
||||
|
||||
def test_get_metalsmith_client_with_not_shared(self):
|
||||
self.test_get_metalsmith_client(shared=False)
|
||||
|
||||
def test_get_metalsmith_client_with_session(self):
|
||||
session = keystone.get_keystone_session()
|
||||
self.test_get_metalsmith_client(session=session)
|
@ -192,7 +192,7 @@ Mako===1.1.6
|
||||
marathon===0.13.0
|
||||
MarkupSafe===2.0.1
|
||||
mbstrdecoder===1.1.0
|
||||
metalsmith===1.6.1
|
||||
metalsmith===1.6.2
|
||||
microversion-parse===1.0.1
|
||||
mistral-lib===2.5.0
|
||||
mitba===1.1.1
|
||||
|
Loading…
x
Reference in New Issue
Block a user