Use neutron client for server.addresses
The server.addresses (/servers/{server_id}/ips)
endpoint can contain stale data causing attribute
lookups to fail.
This change replaces the use of server.addresses
and instead uses the neutron client to list ports
with 'device_id' matching the server id.
Story: 2008632
Task: 41843
Related: RHBZ#1902230
Change-Id: I1b9293041f2ad92eac0e9bc9646e7b2d7c6f7fd0
(cherry picked from commit 45750c603a
)
This commit is contained in:
parent
bd38beda66
commit
0937375643
|
@ -12,6 +12,7 @@
|
|||
# under the License.
|
||||
|
||||
import copy
|
||||
import ipaddress
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
|
@ -948,8 +949,8 @@ class Server(server_base.BaseServer, sh.SchedulerHintsMixin,
|
|||
return result
|
||||
|
||||
def _get_live_networks(self, server, props):
|
||||
reality_nets = self._add_attrs_for_address(server,
|
||||
extend_networks=False)
|
||||
reality_nets = self._get_server_addresses(server,
|
||||
extend_networks=False)
|
||||
reality_net_ids = {}
|
||||
client_plugin = self.client_plugin('neutron')
|
||||
for net_key in reality_nets:
|
||||
|
@ -1117,7 +1118,7 @@ class Server(server_base.BaseServer, sh.SchedulerHintsMixin,
|
|||
LOG.warning("Failed to fetch resource attributes: %s", ex)
|
||||
return
|
||||
|
||||
def _add_attrs_for_address(self, server, extend_networks=True):
|
||||
def _get_server_addresses(self, server, extend_networks=True):
|
||||
"""Adds port id, subnets and network attributes to addresses list.
|
||||
|
||||
This method is used only for resolving attributes.
|
||||
|
@ -1126,31 +1127,48 @@ class Server(server_base.BaseServer, sh.SchedulerHintsMixin,
|
|||
the net is returned without replacing name on
|
||||
id.
|
||||
"""
|
||||
nets = copy.deepcopy(server.addresses) or {}
|
||||
ifaces = server.interface_list()
|
||||
ip_mac_mapping_on_port_id = dict(((iface.fixed_ips[0]['ip_address'],
|
||||
iface.mac_addr), iface.port_id)
|
||||
for iface in ifaces)
|
||||
for net_name in nets:
|
||||
for addr in nets[net_name]:
|
||||
addr['port'] = ip_mac_mapping_on_port_id.get(
|
||||
(addr['addr'], addr['OS-EXT-IPS-MAC:mac_addr']))
|
||||
nets = {}
|
||||
ifaces = self.client('neutron').list_ports(device_id=server.id)
|
||||
for port in ifaces['ports']:
|
||||
net_label = self.client('neutron').list_networks(
|
||||
id=port['network_id'])['networks'][0]['name']
|
||||
net = nets.setdefault(net_label, [])
|
||||
for fixed_ip in port['fixed_ips']:
|
||||
addr = {'addr': fixed_ip.get('ip_address'),
|
||||
'OS-EXT-IPS-MAC:mac_addr': port['mac_address'],
|
||||
'OS-EXT-IPS:type': 'fixed',
|
||||
'port': port['id']}
|
||||
|
||||
try:
|
||||
addr['version'] = ipaddress.ip_address(
|
||||
addr['addr']).version,
|
||||
except ValueError:
|
||||
addr['version'] = None
|
||||
|
||||
if addr['addr']:
|
||||
fips = self.client('neutron').list_floatingips(
|
||||
fixed_ip_address=addr['addr'])
|
||||
for fip in fips['floatingips']:
|
||||
net.append({
|
||||
'addr': fip['floating_ip_address'],
|
||||
'version': addr['version'],
|
||||
'OS-EXT-IPS-MAC:mac_addr': port['mac_address'],
|
||||
'OS-EXT-IPS:type': 'floating',
|
||||
'port': None})
|
||||
|
||||
# _get_live_networks() uses this method to get reality_nets.
|
||||
# We don't need to get subnets and network in that case. Only
|
||||
# do the external calls if extend_networks is true, i.e called
|
||||
# from _resolve_attribute()
|
||||
if not extend_networks:
|
||||
net.append(addr)
|
||||
continue
|
||||
try:
|
||||
port = self.client('neutron').show_port(
|
||||
addr['port'])['port']
|
||||
except Exception as ex:
|
||||
addr['subnets'], addr['network'] = None, None
|
||||
LOG.warning("Failed to fetch resource attributes: %s", ex)
|
||||
continue
|
||||
|
||||
addr['subnets'] = self._get_subnets_attr(port['fixed_ips'])
|
||||
addr['network'] = self._get_network_attr(port['network_id'])
|
||||
|
||||
net.append(addr)
|
||||
|
||||
if extend_networks:
|
||||
return self._extend_networks(nets)
|
||||
else:
|
||||
|
@ -1194,7 +1212,7 @@ class Server(server_base.BaseServer, sh.SchedulerHintsMixin,
|
|||
self.client_plugin().ignore_not_found(e)
|
||||
return ''
|
||||
if name == self.ADDRESSES:
|
||||
return self._add_attrs_for_address(server)
|
||||
return self._get_server_addresses(server)
|
||||
if name == self.NETWORKS_ATTR:
|
||||
return self._extend_networks(server.networks)
|
||||
if name == self.INSTANCE_NAME:
|
||||
|
|
|
@ -447,42 +447,48 @@ class ServersTest(common.HeatTestCase):
|
|||
ip='5.6.9.8'),
|
||||
create_fake_iface(port='1013',
|
||||
mac='fa:16:3e:8c:44:cc',
|
||||
ip='10.13.12.13')]
|
||||
ip='10.13.12.13',
|
||||
subnet='private_subnet_id')]
|
||||
ports = [dict(id=interfaces[0].port_id,
|
||||
mac_address=interfaces[0].mac_addr,
|
||||
fixed_ips=interfaces[0].fixed_ips,
|
||||
network_id='public_id'),
|
||||
dict(id=interfaces[1].port_id,
|
||||
mac_address=interfaces[1].mac_addr,
|
||||
fixed_ips=interfaces[1].fixed_ips,
|
||||
network_id='public_id'),
|
||||
dict(id=interfaces[2].port_id,
|
||||
mac_address=interfaces[2].mac_addr,
|
||||
fixed_ips=interfaces[2].fixed_ips,
|
||||
network_id='private_id')]
|
||||
public_net = dict(id='public_id',
|
||||
name='public',
|
||||
mtu=1500,
|
||||
subnets=['public_subnet_id'])
|
||||
private_net = dict(id='private_id',
|
||||
name='private',
|
||||
mtu=1500,
|
||||
subnets=['private_subnet_id'])
|
||||
private_subnet = dict(id='private_subnet_id',
|
||||
name='private_subnet',
|
||||
cidr='private_cidr',
|
||||
allocation_pools=[{'start': 'start_addr',
|
||||
'end': 'end_addr'}],
|
||||
gateway_ip='private_gateway',
|
||||
network_id='private_id')
|
||||
|
||||
self.patchobject(self.fc.servers, 'get', return_value=return_server)
|
||||
self.patchobject(return_server, 'interface_list',
|
||||
return_value=interfaces)
|
||||
self.patchobject(neutronclient.Client, 'list_ports',
|
||||
return_value={'ports': ports})
|
||||
self.patchobject(neutronclient.Client, 'list_networks',
|
||||
side_effect=[{'networks': [public_net]},
|
||||
{'networks': [public_net]},
|
||||
{'networks': [private_net]}])
|
||||
self.patchobject(neutronclient.Client, 'list_floatingips',
|
||||
return_value={'floatingips': []})
|
||||
self.patchobject(self.fc.servers, 'tag_list', return_value=['test'])
|
||||
|
||||
self.port_show.return_value = {
|
||||
'port': {'id': '1234',
|
||||
'network_id': 'the_network',
|
||||
'fixed_ips': [{
|
||||
'ip_address': '4.5.6.7',
|
||||
'subnet_id': 'the_subnet'}]
|
||||
}
|
||||
}
|
||||
subnet_dict = {
|
||||
'subnet': {
|
||||
'name': 'subnet_name',
|
||||
'cidr': '10.0.0.0/24',
|
||||
'allocation_pools': [{'start': '10.0.0.2',
|
||||
'end': u'10.0.0.254'}],
|
||||
'gateway_ip': '10.0.0.1',
|
||||
'id': 'the_subnet',
|
||||
'network_id': 'the_network'
|
||||
}
|
||||
}
|
||||
network_dict = {
|
||||
'network': {
|
||||
'name': 'network_name',
|
||||
'mtu': 1500,
|
||||
'subnets': [subnet_dict['subnet']['id']],
|
||||
'id': 'the_network'
|
||||
}
|
||||
}
|
||||
self.subnet_show.return_value = subnet_dict
|
||||
self.network_show.return_value = network_dict
|
||||
self.subnet_show.return_value = {'subnet': private_subnet}
|
||||
self.network_show.return_value = {'network': private_net}
|
||||
|
||||
public_ip = return_server.networks['public'][0]
|
||||
self.assertEqual('1234',
|
||||
|
@ -499,9 +505,9 @@ class ServersTest(common.HeatTestCase):
|
|||
server.FnGetAtt('addresses')['private'][0]['port'])
|
||||
self.assertEqual(private_ip,
|
||||
server.FnGetAtt('addresses')['private'][0]['addr'])
|
||||
self.assertEqual([subnet_dict['subnet']],
|
||||
self.assertEqual([private_subnet],
|
||||
server.FnGetAtt('addresses')['private'][0]['subnets'])
|
||||
self.assertEqual(network_dict['network'],
|
||||
self.assertEqual(private_net,
|
||||
server.FnGetAtt('addresses')['private'][0]['network'])
|
||||
self.assertEqual(private_ip,
|
||||
server.FnGetAtt('networks')['private'][0])
|
||||
|
@ -522,21 +528,6 @@ class ServersTest(common.HeatTestCase):
|
|||
self.assertIsNone(server.FnGetAtt('tags'))
|
||||
self.assertEqual({}, server.FnGetAtt('os_collect_config'))
|
||||
|
||||
def test_server_network_subnet_address_attr_port_not_found(self):
|
||||
return_server = self.fc.servers.list()[1]
|
||||
server_name = 'network-subnet-attr-server'
|
||||
server = self._create_test_server(return_server, server_name)
|
||||
interfaces = [create_fake_iface(port='1234',
|
||||
mac='fa:16:3e:8c:22:aa',
|
||||
ip='4.5.6.7')]
|
||||
self.patchobject(return_server, 'interface_list',
|
||||
return_value=interfaces)
|
||||
self.port_show.side_effect = neutron.exceptions.NotFound()
|
||||
self.assertEqual(None,
|
||||
server.FnGetAtt('addresses')['private'][0]['subnets'])
|
||||
self.assertEqual(None,
|
||||
server.FnGetAtt('addresses')['private'][0]['network'])
|
||||
|
||||
def test_server_create_metadata(self):
|
||||
stack_name = 'create_metadata_test_stack'
|
||||
self.patchobject(nova.NovaClientPlugin, 'client',
|
||||
|
@ -643,10 +634,30 @@ class ServersTest(common.HeatTestCase):
|
|||
create_fake_iface(port='1013',
|
||||
mac='fa:16:3e:8c:44:cc',
|
||||
ip='10.13.12.13')]
|
||||
ports = [dict(id=interfaces[0].port_id,
|
||||
mac_address=interfaces[0].mac_addr,
|
||||
fixed_ips=interfaces[0].fixed_ips,
|
||||
network_id='public_id'),
|
||||
dict(id=interfaces[1].port_id,
|
||||
mac_address=interfaces[1].mac_addr,
|
||||
fixed_ips=interfaces[1].fixed_ips,
|
||||
network_id='public_id'),
|
||||
dict(id=interfaces[2].port_id,
|
||||
mac_address=interfaces[2].mac_addr,
|
||||
fixed_ips=interfaces[2].fixed_ips,
|
||||
network_id='private_id')]
|
||||
public_net = dict(id='public_id', name='public')
|
||||
private_net = dict(id='private_id', name='private')
|
||||
|
||||
self.patchobject(self.fc.servers, 'get', return_value=return_server)
|
||||
self.patchobject(return_server, 'interface_list',
|
||||
return_value=interfaces)
|
||||
self.patchobject(neutronclient.Client, 'list_ports',
|
||||
return_value={'ports': ports})
|
||||
self.patchobject(neutronclient.Client, 'list_networks',
|
||||
side_effect=[{'networks': [public_net]},
|
||||
{'networks': [public_net]},
|
||||
{'networks': [private_net]}])
|
||||
self.patchobject(neutronclient.Client, 'list_floatingips',
|
||||
return_value={'floatingips': []})
|
||||
self.patchobject(return_server, 'interface_detach')
|
||||
self.patchobject(return_server, 'interface_attach')
|
||||
|
||||
|
@ -2041,20 +2052,42 @@ class ServersTest(common.HeatTestCase):
|
|||
server.properties.data['networks'] = [{'network': 'public_id',
|
||||
'fixed_ip': '5.6.9.8'}]
|
||||
|
||||
public_net = dict(id='public_id', name='public')
|
||||
private_net = dict(id='private_id', name='private')
|
||||
iface0 = create_fake_iface(port='aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa',
|
||||
net='public',
|
||||
ip='5.6.9.8',
|
||||
mac='fa:16:3e:8c:33:aa')
|
||||
port0 = dict(id=iface0.port_id,
|
||||
network_id=iface0.net_id,
|
||||
mac_address=iface0.mac_addr,
|
||||
fixed_ips=iface0.fixed_ips)
|
||||
iface1 = create_fake_iface(port='bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb',
|
||||
net='public',
|
||||
ip='4.5.6.7',
|
||||
mac='fa:16:3e:8c:22:aa')
|
||||
port1 = dict(id=iface1.port_id,
|
||||
network_id=iface1.net_id,
|
||||
mac_address=iface1.mac_addr,
|
||||
fixed_ips=iface1.fixed_ips)
|
||||
iface2 = create_fake_iface(port='cccccccc-cccc-cccc-cccc-cccccccccccc',
|
||||
net='private',
|
||||
ip='10.13.12.13',
|
||||
mac='fa:16:3e:8c:44:cc')
|
||||
port2 = dict(id=iface2.port_id,
|
||||
network_id=iface2.net_id,
|
||||
mac_address=iface2.mac_addr,
|
||||
fixed_ips=iface2.fixed_ips)
|
||||
self.patchobject(return_server, 'interface_list',
|
||||
return_value=[iface0, iface1, iface2])
|
||||
self.patchobject(neutronclient.Client, 'list_ports',
|
||||
return_value={'ports': [port0, port1, port2]})
|
||||
self.patchobject(neutronclient.Client, 'list_networks',
|
||||
side_effect=[{'networks': [public_net]},
|
||||
{'networks': [public_net]},
|
||||
{'networks': [private_net]}])
|
||||
self.patchobject(neutronclient.Client, 'list_floatingips',
|
||||
return_value={'floatingips': []})
|
||||
|
||||
self.patchobject(neutron.NeutronClientPlugin,
|
||||
'find_resourceid_by_name_or_id',
|
||||
|
@ -2677,6 +2710,14 @@ class ServersTest(common.HeatTestCase):
|
|||
self.patchobject(neutron.NeutronClientPlugin,
|
||||
'find_resourceid_by_name_or_id',
|
||||
return_value=None)
|
||||
self.patchobject(neutronclient.Client, 'list_ports',
|
||||
return_value={'ports': [{'id': 'p_id',
|
||||
'name': 'p_name',
|
||||
'fixed_ips': [],
|
||||
'network_id': 'n_id'}]})
|
||||
self.patchobject(neutronclient.Client, 'list_networks',
|
||||
return_value={'networks': [{'id': 'n_id',
|
||||
'name': 'empty_net'}]})
|
||||
self.patchobject(self.fc.servers, 'get', return_value=return_server)
|
||||
self.patchobject(return_server, 'interface_list', return_value=[])
|
||||
mock_detach = self.patchobject(return_server, 'interface_detach')
|
||||
|
|
Loading…
Reference in New Issue