nameservers are obtained from nmcli
Before this patch, tobiko tried to obtain the list of nameservers from a machine from its resolv.conf file. With this patch, tobiko checks whether that machine has nmcli command available and, if so, tries to obtain the DNS server with it too. Change-Id: If83a8637dffa14dc712e605842e5d55713389dea
This commit is contained in:
parent
7b67ccba2e
commit
0a74f0e951
@ -24,6 +24,7 @@ from tobiko.shell.sh import _hostname
|
||||
from tobiko.shell.sh import _io
|
||||
from tobiko.shell.sh import _local
|
||||
from tobiko.shell.sh import _nameservers
|
||||
from tobiko.shell.sh import _nmcli
|
||||
from tobiko.shell.sh import _path
|
||||
from tobiko.shell.sh import _process
|
||||
from tobiko.shell.sh import _ps
|
||||
@ -135,3 +136,6 @@ get_file_size = _wc.get_file_size
|
||||
CommandNotFound = _which.CommandNotFound
|
||||
SkipOnCommandNotFound = _which.SkipOnCommandNotFound
|
||||
find_command = _which.find_command
|
||||
|
||||
get_nm_connection_ids = _nmcli.get_nm_connection_ids
|
||||
get_nm_connection_values = _nmcli.get_nm_connection_values
|
||||
|
@ -59,10 +59,23 @@ def list_nameservers(ssh_client: typing.Optional[ssh.SSHClientFixture] = None,
|
||||
filenames = ['/etc/resolv.conf']
|
||||
|
||||
nameservers: tobiko.Selection[netaddr.IPAddress] = tobiko.Selection()
|
||||
# obtain nameservers from the resolv.conf file
|
||||
for filename in filenames:
|
||||
nameservers.extend(parse_resolv_conf_file(ssh_client=ssh_client,
|
||||
filename=filename,
|
||||
**execute_params))
|
||||
|
||||
# obtain nameservers from nmcli, if available
|
||||
try:
|
||||
sh.find_command('nmcli', ssh_client=ssh_client)
|
||||
except sh.CommandNotFound:
|
||||
msg = 'nmcli command not available'
|
||||
if ssh_client:
|
||||
msg += f' on {ssh_client.host}'
|
||||
LOG.debug(msg)
|
||||
else:
|
||||
nameservers.extend(parse_dns_nmcli(ssh_client=ssh_client))
|
||||
|
||||
if ip_version:
|
||||
nameservers = nameservers.with_attributes(version=ip_version)
|
||||
return nameservers
|
||||
@ -71,8 +84,7 @@ def list_nameservers(ssh_client: typing.Optional[ssh.SSHClientFixture] = None,
|
||||
def parse_resolv_conf_file(
|
||||
filename: str,
|
||||
ssh_client: typing.Optional[ssh.SSHClientFixture] = None,
|
||||
**execute_params) -> \
|
||||
typing.Generator[netaddr.IPAddress, None, None]:
|
||||
**execute_params) -> typing.Generator[netaddr.IPAddress, None, None]:
|
||||
lines: typing.List[str] = \
|
||||
sh.execute(f"cat '{filename}'",
|
||||
ssh_client=ssh_client,
|
||||
@ -94,3 +106,18 @@ def parse_resolv_conf_file(
|
||||
yield netaddr.IPAddress(nameserver)
|
||||
except netaddr.AddrFormatError:
|
||||
LOG.exception(f"Invalid nameserver address: {nameserver}")
|
||||
|
||||
|
||||
def parse_dns_nmcli(
|
||||
ssh_client: typing.Optional[ssh.SSHClientFixture] = None) -> \
|
||||
typing.Generator[netaddr.IPAddress, None, None]:
|
||||
connections = sh.get_nm_connection_ids(ssh_client=ssh_client)
|
||||
for connection in connections:
|
||||
nameservers = sh.get_nm_connection_values(connection,
|
||||
'IP4.DNS,IP6.DNS',
|
||||
ssh_client=ssh_client)
|
||||
for nameserver in nameservers:
|
||||
try:
|
||||
yield netaddr.IPAddress(nameserver)
|
||||
except netaddr.AddrFormatError:
|
||||
LOG.exception(f"Invalid nameserver address: {nameserver}")
|
||||
|
45
tobiko/shell/sh/_nmcli.py
Normal file
45
tobiko/shell/sh/_nmcli.py
Normal file
@ -0,0 +1,45 @@
|
||||
# Copyright (c) 2025 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 oslo_log import log
|
||||
|
||||
from tobiko.shell.sh import _execute
|
||||
from tobiko.shell import ssh
|
||||
|
||||
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
|
||||
def get_nm_connection_ids(ssh_client: ssh.SSHClientType = None) -> list:
|
||||
result = _execute.execute('nmcli -g UUID con',
|
||||
ssh_client=ssh_client)
|
||||
return result.stdout.splitlines()
|
||||
|
||||
|
||||
def get_nm_connection_values(connection: str,
|
||||
values: str,
|
||||
ssh_client: ssh.SSHClientType = None) -> list:
|
||||
result = _execute.execute(f'nmcli -g {values} con show "{connection}"',
|
||||
ssh_client=ssh_client)
|
||||
return_values = []
|
||||
for line in result.stdout.splitlines():
|
||||
if line:
|
||||
for value in line.split('|'):
|
||||
# nmcli adds escape char before ":" and we need to remove it
|
||||
return_values.append(value.strip().replace('\\', ''))
|
||||
|
||||
return return_values
|
@ -15,6 +15,8 @@
|
||||
# under the License.
|
||||
from __future__ import absolute_import
|
||||
|
||||
import typing
|
||||
|
||||
import tobiko
|
||||
from tobiko.shell import sh
|
||||
from tobiko.openstack import stacks
|
||||
@ -27,7 +29,7 @@ class AdvancedServerStackTest(test_cirros.CirrosServerStackTest):
|
||||
#: Stack of resources with a server attached to a floating IP
|
||||
stack = tobiko.required_fixture(stacks.AdvancedServerStackFixture)
|
||||
|
||||
nameservers_filenames = ('/etc/resolv.conf',)
|
||||
nameservers_filenames: typing.Optional[typing.Sequence[str]] = []
|
||||
|
||||
def test_python(self):
|
||||
python_version = sh.execute(['python3', '--version'],
|
||||
|
Loading…
x
Reference in New Issue
Block a user