summaryrefslogtreecommitdiffstats
path: root/nova/api
diff options
context:
space:
mode:
authorChris Behrens <cbehrens@codestud.com>2011-10-21 00:29:54 -0700
committerChris Behrens <cbehrens@codestud.com>2011-10-26 19:17:42 -0700
commit61e5b8e7da3b36db9a09f80d62ebf2e276bbe88b (patch)
treeb9bc052b15c5e98464296bf5af66dfbf9e597aad /nova/api
parent5e9e3873e5ee3cf87b8aec801705ee24cedcd1aa (diff)
Revert how APIs get IP address info for instances
Fixes bug 862839 listing instances with IPs is extremely inefficient after changes were made to query the network manager for IP information for each instance. I tried adding a network manager call that said 'give me IP information for 'x' instances', but that was also too slow. We need a solution that caches IP info from the network manager before we can fully untie things. So, this reverts APIs to use instance['fixed_ips'] which hasn't been untied in the DB yet. Change-Id: I37d21105d6306f0a812c5eb0f0717a5094cd17b9
Diffstat (limited to 'nova/api')
-rw-r--r--nova/api/ec2/cloud.py96
-rw-r--r--nova/api/openstack/common.py62
2 files changed, 70 insertions, 88 deletions
diff --git a/nova/api/ec2/cloud.py b/nova/api/ec2/cloud.py
index b0130a0ad..a2bd2c32f 100644
--- a/nova/api/ec2/cloud.py
+++ b/nova/api/ec2/cloud.py
@@ -238,58 +238,43 @@ class CloudController(object):
utils.runthis(_("Generating root CA: %s"), "sh", genrootca_sh_path)
os.chdir(start)
- def _get_floaters_for_fixed_ip(self, context, fixed_ip):
- """Return all floating IPs given a fixed IP"""
- return self.network_api.get_floating_ips_by_fixed_address(context,
- fixed_ip)
-
- def _get_fixed_ips_for_instance(self, context, instance):
+ def _get_ip_info_for_instance(self, context, instance):
"""Return a list of all fixed IPs for an instance"""
- ret_ips = []
- ret_ip6s = []
- nw_info = self.network_api.get_instance_nw_info(context, instance)
- for net, info in nw_info:
- if not info:
+ ip_info = dict(fixed_ips=[], fixed_ip6s=[], floating_ips=[])
+
+ fixed_ips = instance['fixed_ips']
+ for fixed_ip in fixed_ips:
+ fixed_addr = fixed_ip['address']
+ network = fixed_ip.get('network')
+ vif = fixed_ip.get('virtual_interface')
+ if not network or not vif:
+ name = instance['name']
+ ip = fixed_ip['address']
+ LOG.warn(_("Instance %(name)s has stale IP "
+ "address: %(ip)s (no network or vif)") % locals())
continue
- ips = info.get('ips', [])
- for ip in ips:
- try:
- ret_ips.append(ip['ip'])
- except KeyError:
- pass
- if FLAGS.use_ipv6:
- ip6s = info.get('ip6s', [])
- for ip6 in ip6s:
- try:
- ret_ip6s.append(ip6['ip'])
- except KeyError:
- pass
- return (ret_ips, ret_ip6s)
-
- def _get_floaters_for_instance(self, context, instance, return_all=True):
- """Return all floating IPs for an instance"""
-
- ret_floaters = []
- # only loop through ipv4 addresses
- fixed_ips = self._get_fixed_ips_for_instance(context, instance)[0]
- for ip in fixed_ips:
- floaters = self._get_floaters_for_fixed_ip(context, ip)
- # Allows a short circuit if we just need any floater.
- if floaters and not return_all:
- return floaters
- ret_floaters.extend(floaters)
- if floaters and only_one:
- return ret_floaters
- return ret_floaters
+ cidr_v6 = network.get('cidr_v6')
+ if FLAGS.use_ipv6 and cidr_v6:
+ ipv6_addr = ipv6.to_global(cidr_v6, vif['address'],
+ network['project_id'])
+ if ipv6_addr not in ip_info['fixed_ip6s']:
+ ip_info['fixed_ip6s'].append(ipv6_addr)
+
+ for floating_ip in fixed_ip.get('floating_ips', []):
+ float_addr = floating_ip['address']
+ ip_info['floating_ips'].append(float_addr)
+ ip_info['fixed_ips'].append(fixed_addr)
+ return ip_info
def _get_mpi_data(self, context, project_id):
result = {}
search_opts = {'project_id': project_id, 'deleted': False}
for instance in self.compute_api.get_all(context,
search_opts=search_opts):
+ ip_info = self._get_ip_info_for_instance(context, instance)
# only look at ipv4 addresses
- fixed_ips = self._get_fixed_ips_for_instance(context, instance)[0]
+ fixed_ips = ip_info['fixed_ips']
if fixed_ips:
line = '%s slots=%d' % (fixed_ips[0], instance['vcpus'])
key = str(instance['key_name'])
@@ -378,9 +363,9 @@ class CloudController(object):
host = instance_ref['host']
availability_zone = self._get_availability_zone_by_host(ctxt, host)
- floaters = self._get_floaters_for_instance(ctxt, instance_ref,
- return_all=False)
- floating_ip = floaters and floaters[0] or ''
+ ip_info = self._get_ip_info_for_instance(ctxt, instance_ref)
+ floating_ips = ip_info['floating_ips']
+ floating_ip = floating_ips and floating_ips[0] or ''
ec2_id = ec2utils.id_to_ec2_id(instance_ref['id'])
image_ec2_id = self.image_ec2_id(instance_ref['image_ref'])
@@ -1309,20 +1294,13 @@ class CloudController(object):
fixed_ip = None
floating_ip = None
- (fixed_ips, fixed_ip6s) = self._get_fixed_ips_for_instance(context,
- instance)
- if fixed_ips:
- fixed_ip = fixed_ips[0]
- # Now look for a floater.
- for ip in fixed_ips:
- floating_ips = self._get_floaters_for_fixed_ip(context, ip)
- # NOTE(comstud): Will it float?
- if floating_ips:
- floating_ip = floating_ips[0]
- # Got one, exit out.
- break
- if fixed_ip6s:
- i['dnsNameV6'] = fixed_ip6s[0]
+ ip_info = self._get_ip_info_for_instance(context, instance)
+ if ip_info['fixed_ips']:
+ fixed_ip = ip_info['fixed_ips'][0]
+ if ip_info['floating_ips']:
+ floating_ip = ip_info['floating_ips'][0]
+ if ip_info['fixed_ip6s']:
+ i['dnsNameV6'] = ip_info['fixed_ip6s'][0]
i['privateDnsName'] = fixed_ip
i['privateIpAddress'] = fixed_ip
i['publicDnsName'] = floating_ip
diff --git a/nova/api/openstack/common.py b/nova/api/openstack/common.py
index 45987d40e..0f3f1fff7 100644
--- a/nova/api/openstack/common.py
+++ b/nova/api/openstack/common.py
@@ -16,9 +16,10 @@
# under the License.
import functools
-from lxml import etree
import re
import urlparse
+
+from lxml import etree
import webob
from xml.dom import minidom
@@ -28,6 +29,7 @@ from nova.compute import vm_states
from nova.compute import task_states
from nova import exception
from nova import flags
+from nova import ipv6
from nova import log as logging
import nova.network
from nova import quota
@@ -293,40 +295,42 @@ def get_networks_for_instance(context, instance):
...}
"""
- network_api = nova.network.API()
-
- def _get_floats(ip):
- return network_api.get_floating_ips_by_fixed_address(context, ip)
-
def _emit_addr(ip, version):
return {'addr': ip, 'version': version}
- nw_info = network_api.get_instance_nw_info(context, instance)
-
networks = {}
- for net, info in nw_info:
- if not info:
- continue
- try:
- network = {'ips': []}
- network['floating_ips'] = []
- for ip in info['ips']:
- network['ips'].append(_emit_addr(ip['ip'], 4))
- floats = [_emit_addr(addr, 4)
- for addr in _get_floats(ip['ip'])]
- network['floating_ips'].extend(floats)
- if FLAGS.use_ipv6 and 'ip6s' in info:
- network['ips'].extend([_emit_addr(ip['ip'], 6)
- for ip in info['ip6s']])
- # NOTE(comstud): These exception checks are for lp830817
- # (Restoring them after a refactoring removed)
- except TypeError:
- raise
+ fixed_ips = instance['fixed_ips']
+ ipv6_addrs_seen = {}
+ for fixed_ip in fixed_ips:
+ fixed_addr = fixed_ip['address']
+ network = fixed_ip['network']
+ vif = fixed_ip.get('virtual_interface')
+ if not network or not vif:
+ name = instance['name']
+ ip = fixed_ip['address']
+ LOG.warn(_("Instance %(name)s has stale IP "
+ "address: %(ip)s (no network or vif)") % locals())
continue
- except KeyError:
- raise
+ label = network.get('label', None)
+ if label is None:
continue
- networks[info['label']] = network
+ if label not in networks:
+ networks[label] = {'ips': [], 'floating_ips': []}
+ nw_dict = networks[label]
+ cidr_v6 = network.get('cidr_v6')
+ if FLAGS.use_ipv6 and cidr_v6:
+ ipv6_addr = ipv6.to_global(cidr_v6, vif['address'],
+ network['project_id'])
+ # Only add same IPv6 address once. It's possible we've
+ # seen it before if there was a previous fixed_ip with
+ # same network and vif as this one
+ if not ipv6_addrs_seen.get(ipv6_addr):
+ nw_dict['ips'].append(_emit_addr(ipv6_addr, 6))
+ ipv6_addrs_seen[ipv6_addr] = True
+ nw_dict['ips'].append(_emit_addr(fixed_addr, 4))
+ for floating_ip in fixed_ip.get('floating_ips', []):
+ float_addr = floating_ip['address']
+ nw_dict['floating_ips'].append(_emit_addr(float_addr, 4))
return networks