Copy default nameservers from external network

Change-Id: I2afec8527e14e11c929b55c2883d6e96ff1176ef
This commit is contained in:
Federico Ressi 2020-11-28 05:38:19 +01:00
parent 0cc9d75f32
commit 521212c816
4 changed files with 90 additions and 81 deletions

View File

@ -17,7 +17,6 @@ from tobiko.openstack.neutron import _agent
from tobiko.openstack.neutron import _client
from tobiko.openstack.neutron import _cidr
from tobiko.openstack.neutron import _extension
from tobiko.openstack.neutron import _nameservers
from tobiko.openstack.neutron import _port
from tobiko.openstack.neutron import _network
@ -67,9 +66,6 @@ has_networking_extensions = _extension.has_networking_extensions
skip_if_missing_networking_extensions = (
_extension.skip_if_missing_networking_extensions)
DefaultNameserversFixture = _nameservers.DefaultNameserversFixture
default_nameservers = _nameservers.default_nameservers
find_port_ip_address = _port.find_port_ip_address
list_port_ip_addresses = _port.list_port_ip_addresses
find_device_ip_address = _port.find_device_ip_address
@ -82,3 +78,4 @@ delete_network = _network.delete_network
get_network = _network.get_network
find_network = _network.find_network
list_networks = _network.list_networks
list_network_nameservers = _network.list_network_nameservers

View File

@ -1,75 +0,0 @@
# Copyright 2020 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
from oslo_log import log
import netaddr
import tobiko
from tobiko.shell import ip
from tobiko.shell import sh
from tobiko.shell import ssh
LOG = log.getLogger(__name__)
class DefaultNameserversFixture(sh.ListNameserversFixture):
remove_local_ips = True
max_count = 3
ip_version = None
@property
def ssh_client(self):
host = tobiko.tobiko_config().neutron.nameservers_host
if host is None:
return ssh.ssh_proxy_client()
else:
return ssh.ssh_client(host)
@property
def filenames(self):
return tuple(tobiko.tobiko_config().neutron.nameservers_filenames)
def setup_fixture(self):
super(DefaultNameserversFixture, self).setup_fixture()
if self.remove_local_ips:
local_ips = ip.list_ip_addresses(scope='host')
if local_ips:
# Filter out all local IPs
self.nameservers = tobiko.select(
nameserver for nameserver in self.nameservers
if nameserver not in local_ips)
if self.max_count:
actual_count = len(self.nameservers)
if actual_count > self.max_count:
LOG.waring("Limit the number of nameservers from "
f"{actual_count} to {self.max_count}")
self.nameservers = self.nameservers[:3]
DEFAULT_NAMESERVERS_FIXTURE = DefaultNameserversFixture
def default_nameservers(
ip_version: typing.Optional[int] = None) -> \
tobiko.Selection[netaddr.IPAddress]:
nameservers = tobiko.setup_fixture(
DEFAULT_NAMESERVERS_FIXTURE).nameservers
if ip_version is not None:
nameservers = nameservers.with_attributes(version=ip_version)
return nameservers

View File

@ -15,6 +15,8 @@ from __future__ import absolute_import
import typing
import netaddr
import tobiko
from tobiko.openstack.neutron import _client
@ -86,3 +88,16 @@ class NeutronNetworkFixture(_client.HasNeutronClientFixture):
self.name = self.fixture_name
self.details = create_network(client=self.client, name=self.name)
self.addCleanup(delete_network, network=self.id, client=self.client)
def list_network_nameservers(network_id: typing.Optional[str] = None,
ip_version: typing.Optional[int] = None) -> \
tobiko.Selection[netaddr.IPAddress]:
subnets = _client.list_subnets(network_id=network_id)
nameservers = tobiko.Selection[netaddr.IPAddress](
netaddr.IPAddress(nameserver)
for subnets in subnets
for nameserver in subnets['dns_nameservers'])
if ip_version is not None:
nameservers = nameservers.with_attributes(version=ip_version)
return nameservers

View File

@ -26,6 +26,9 @@ from tobiko import config
from tobiko.openstack import heat
from tobiko.openstack import neutron
from tobiko.openstack.stacks import _hot
from tobiko.shell import ip
from tobiko.shell import sh
from tobiko.shell import ssh
LOG = log.getLogger(__name__)
@ -201,7 +204,7 @@ class NetworkStackFixture(heat.HeatStackFixture):
def ipv4_dns_nameservers(self):
nameservers = CONF.tobiko.neutron.ipv4_dns_nameservers
if nameservers is None:
nameservers = neutron.default_nameservers(ip_version=4)
nameservers = default_nameservers(ip_version=4)
return ','.join(str(nameserver) for nameserver in nameservers)
@property
@ -220,7 +223,7 @@ class NetworkStackFixture(heat.HeatStackFixture):
def ipv6_dns_nameservers(self):
nameservers = CONF.tobiko.neutron.ipv6_dns_nameservers
if nameservers is None:
nameservers = neutron.default_nameservers(ip_version=6)
nameservers = default_nameservers(ip_version=6)
return ','.join(str(nameserver) for nameserver in nameservers)
@property
@ -351,3 +354,72 @@ def has_floating_network():
skip_unless_has_floating_network = tobiko.skip_unless(
'Floating network not found', has_floating_network)
class DefaultNameserversFixture(tobiko.SharedFixture):
remove_local_ips = True
max_count = 3
ip_version = None
nameservers: typing.Optional[tobiko.Selection[netaddr.IPAddress]] = None
@property
def ssh_client(self):
host = tobiko.tobiko_config().neutron.nameservers_host
if host is None:
return ssh.ssh_proxy_client()
else:
return ssh.ssh_client(host)
@property
def filenames(self):
return tuple(tobiko.tobiko_config().neutron.nameservers_filenames)
def setup_fixture(self):
self.nameservers = self.list_nameservers()
def list_nameservers(self) -> tobiko.Selection[netaddr.IPAddress]:
nameservers: tobiko.Selection[netaddr.IPAddress]
if has_external_network():
network_id = get_external_network_id()
nameservers = neutron.list_network_nameservers(
network_id=network_id)
LOG.debug("Nameservers copied from external network: "
f"{nameservers}")
else:
# Copy nameservers from target host
nameservers = sh.list_nameservers(ssh_client=self.ssh_client,
ip_version=self.ip_version,
filenames=self.filenames)
if self.remove_local_ips:
local_ips = ip.list_ip_addresses(scope='host')
if local_ips:
# Filter out all local IPs
nameservers = tobiko.Selection[netaddr.IPAddress](
nameserver for nameserver in nameservers
if nameserver not in local_ips)
LOG.debug(f"Nameservers copied from host: {nameservers}")
if self.max_count:
# Keep only up to max_count nameservers
actual_count = len(nameservers)
if actual_count > self.max_count:
LOG.waring("Limit the number of nameservers from "
f"{actual_count} to {self.max_count}: "
f"{nameservers}")
nameservers = tobiko.Selection[netaddr.IPAddress](
nameservers[:self.max_count])
return nameservers
DEFAULT_NAMESERVERS_FIXTURE = DefaultNameserversFixture
def default_nameservers(
ip_version: typing.Optional[int] = None) -> \
tobiko.Selection[netaddr.IPAddress]:
nameservers = tobiko.setup_fixture(
DEFAULT_NAMESERVERS_FIXTURE).nameservers
if ip_version is not None:
nameservers = nameservers.with_attributes(version=ip_version)
return nameservers