summaryrefslogtreecommitdiffstats
path: root/nova/api
diff options
context:
space:
mode:
authorJason Koelker <jason@koelker.net>2011-09-20 16:13:12 -0500
committerJason Kölker <jason@koelker.net>2011-09-25 12:24:52 -0500
commit8be1c68f809b55088c1ad00ef86cb13b0103aab0 (patch)
tree7d5a5be076d679d70d84b2afcbf73828b17e6d50 /nova/api
parentbca7dd3e1d8bec758faf511338617f6d4121e0b8 (diff)
* Rework osapi to use network API not FK backref
* Fixes lp854585 Change-Id: I270794a08a1bfafe7af427cd31f1f60df1faa4ba
Diffstat (limited to 'nova/api')
-rw-r--r--nova/api/openstack/ips.py93
-rw-r--r--nova/api/openstack/servers.py23
-rw-r--r--nova/api/openstack/views/addresses.py98
-rw-r--r--nova/api/openstack/views/servers.py43
4 files changed, 145 insertions, 112 deletions
diff --git a/nova/api/openstack/ips.py b/nova/api/openstack/ips.py
index b805c53f8..49aa81958 100644
--- a/nova/api/openstack/ips.py
+++ b/nova/api/openstack/ips.py
@@ -16,15 +16,19 @@
# under the License.
from lxml import etree
-import time
from webob import exc
import nova
import nova.api.openstack.views.addresses
+from nova import log as logging
+from nova import flags
from nova.api.openstack import wsgi
from nova.api.openstack import xmlutil
-from nova import db
+
+
+LOG = logging.getLogger('nova.api.openstack.ips')
+FLAGS = flags.FLAGS
class Controller(object):
@@ -32,13 +36,14 @@ class Controller(object):
def __init__(self):
self.compute_api = nova.compute.API()
+ self.network_api = nova.network.API()
- def _get_instance(self, req, server_id):
+ def _get_instance(self, context, server_id):
try:
- instance = self.compute_api.get(
- req.environ['nova.context'], server_id)
+ instance = self.compute_api.get(context, server_id)
except nova.exception.NotFound:
- raise exc.HTTPNotFound()
+ msg = _("Instance does not exist")
+ raise exc.HTTPNotFound(explanation=msg)
return instance
def create(self, req, server_id, body):
@@ -51,17 +56,23 @@ class Controller(object):
class ControllerV10(Controller):
def index(self, req, server_id):
- instance = self._get_instance(req, server_id)
+ context = req.environ['nova.context']
+ instance = self._get_instance(context, server_id)
+ networks = _get_networks_for_instance(context, self.network_api,
+ instance)
builder = nova.api.openstack.views.addresses.ViewBuilderV10()
- return {'addresses': builder.build(instance)}
+ return {'addresses': builder.build(networks)}
def show(self, req, server_id, id):
- instance = self._get_instance(req, server_id)
+ context = req.environ['nova.context']
+ instance = self._get_instance(context, server_id)
+ networks = _get_networks_for_instance(context, self.network_api,
+ instance)
builder = self._get_view_builder(req)
if id == 'private':
- view = builder.build_private_parts(instance)
+ view = builder.build_private_parts(networks)
elif id == 'public':
- view = builder.build_public_parts(instance)
+ view = builder.build_public_parts(networks)
else:
msg = _("Only private and public networks available")
raise exc.HTTPNotFound(explanation=msg)
@@ -76,14 +87,18 @@ class ControllerV11(Controller):
def index(self, req, server_id):
context = req.environ['nova.context']
- interfaces = self._get_virtual_interfaces(context, server_id)
- networks = self._get_view_builder(req).build(interfaces)
- return {'addresses': networks}
+ instance = self._get_instance(context, server_id)
+ networks = _get_networks_for_instance(context, self.network_api,
+ instance)
+ return {'addresses': self._get_view_builder(req).build(networks)}
def show(self, req, server_id, id):
context = req.environ['nova.context']
- interfaces = self._get_virtual_interfaces(context, server_id)
- network = self._get_view_builder(req).build_network(interfaces, id)
+ instance = self._get_instance(context, server_id)
+ networks = _get_networks_for_instance(context, self.network_api,
+ instance)
+
+ network = self._get_view_builder(req).build_network(networks, id)
if network is None:
msg = _("Instance is not a member of specified network")
@@ -91,13 +106,6 @@ class ControllerV11(Controller):
return network
- def _get_virtual_interfaces(self, context, server_id):
- try:
- return db.api.virtual_interface_get_by_instance(context, server_id)
- except nova.exception.InstanceNotFound:
- msg = _("Instance does not exist")
- raise exc.HTTPNotFound(explanation=msg)
-
def _get_view_builder(self, req):
return nova.api.openstack.views.addresses.ViewBuilderV11()
@@ -135,6 +143,45 @@ class IPXMLSerializer(wsgi.XMLDictSerializer):
return self._to_xml(addresses)
+def _get_networks_for_instance(context, network_api, instance):
+ """Returns a prepared nw_info list for passing into the view
+ builders
+
+ We end up with a datastructure like:
+ {'public': {'ips': [{'addr': '10.0.0.1', 'version': 4},
+ {'addr': '2001::1', 'version': 6}],
+ 'floating_ips': [{'addr': '172.16.0.1', 'version': 4},
+ {'addr': '172.16.2.1', 'version': 4}]},
+ ...}
+ """
+ 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}
+
+ if FLAGS.stub_network:
+ return {}
+
+ nw_info = network_api.get_instance_nw_info(context, instance)
+
+ networks = {}
+ for net, info in nw_info:
+ network = {'ips': []}
+ network['floating_ips'] = []
+ if 'ip6s' in info:
+ network['ips'].extend([_emit_addr(ip['ip'],
+ 6) for ip in info['ip6s']])
+
+ 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)
+ networks[info['label']] = network
+ return networks
+
+
def create_resource(version):
controller = {
'1.0': ControllerV10,
diff --git a/nova/api/openstack/servers.py b/nova/api/openstack/servers.py
index 6f55aef9e..e92ab9bda 100644
--- a/nova/api/openstack/servers.py
+++ b/nova/api/openstack/servers.py
@@ -23,6 +23,7 @@ from webob import exc
import webob
from nova import compute
+from nova import network
from nova import db
from nova import exception
from nova import flags
@@ -32,7 +33,6 @@ from nova.api.openstack import common
from nova.api.openstack import create_instance_helper as helper
from nova.api.openstack import ips
from nova.api.openstack import wsgi
-from nova.compute import instance_types
from nova.scheduler import api as scheduler_api
import nova.api.openstack
import nova.api.openstack.views.addresses
@@ -72,6 +72,7 @@ class Controller(object):
def __init__(self):
self.compute_api = compute.API()
+ self.network_api = network.API()
self.helper = helper.CreateInstanceHelper(self)
def index(self, req):
@@ -106,6 +107,11 @@ class Controller(object):
def _action_rebuild(self, info, request, instance_id):
raise NotImplementedError()
+ def _get_networks_for_instance(self, req, instance):
+ return ips._get_networks_for_instance(req.environ['nova.context'],
+ self.network_api,
+ instance)
+
def _get_servers(self, req, is_detail):
"""Returns a list of servers, taking into account any search
options specified.
@@ -639,12 +645,15 @@ class ControllerV10(Controller):
def _build_view(self, req, instance, is_detail=False):
addresses = nova.api.openstack.views.addresses.ViewBuilderV10()
builder = nova.api.openstack.views.servers.ViewBuilderV10(addresses)
- return builder.build(instance, is_detail=is_detail)
+ networks = self._get_networks_for_instance(req, instance)
+ return builder.build(instance, networks, is_detail=is_detail)
def _build_list(self, req, instances, is_detail=False):
addresses = nova.api.openstack.views.addresses.ViewBuilderV10()
builder = nova.api.openstack.views.servers.ViewBuilderV10(addresses)
- return builder.build_list(instances, is_detail=is_detail)
+ get_nw = self._get_networks_for_instance
+ inst_data = [(inst, get_nw(req, inst)) for inst in instances]
+ return builder.build_list(inst_data, is_detail=is_detail)
def _limit_items(self, items, req):
return common.limited(items, req)
@@ -741,8 +750,8 @@ class ControllerV11(Controller):
builder = nova.api.openstack.views.servers.ViewBuilderV11(
addresses_builder, flavor_builder, image_builder,
base_url, project_id)
-
- return builder.build(instance, is_detail=is_detail)
+ networks = self._get_networks_for_instance(req, instance)
+ return builder.build(instance, networks, is_detail=is_detail)
def _build_list(self, req, instances, is_detail=False):
params = req.GET.copy()
@@ -761,7 +770,9 @@ class ControllerV11(Controller):
builder = nova.api.openstack.views.servers.ViewBuilderV11(
addresses_builder, flavor_builder, image_builder,
base_url, project_id)
- return builder.build_list(instances, is_detail=is_detail, **params)
+ get_nw = self._get_networks_for_instance
+ inst_data = [(inst, get_nw(req, inst)) for inst in instances]
+ return builder.build_list(inst_data, is_detail=is_detail, **params)
def _action_change_password(self, input_dict, req, id):
context = req.environ['nova.context']
diff --git a/nova/api/openstack/views/addresses.py b/nova/api/openstack/views/addresses.py
index 8d38bc9c3..3454f50c8 100644
--- a/nova/api/openstack/views/addresses.py
+++ b/nova/api/openstack/views/addresses.py
@@ -15,10 +15,11 @@
# License for the specific language governing permissions and limitations
# under the License.
+import itertools
+
from nova import flags
-from nova import utils
from nova import log as logging
-from nova.api.openstack import common
+
FLAGS = flags.FLAGS
LOG = logging.getLogger('nova.api.openstack.views.addresses')
@@ -30,76 +31,55 @@ class ViewBuilder(object):
def build(self, inst):
raise NotImplementedError()
+ def _extract_ips(self, network, key=None):
+ if key:
+ chain = network[key]
+ else:
+ chain = itertools.chain(network['ips'], network['floating_ips'])
+ for ip in chain:
+ if not FLAGS.use_ipv6 and ip['version'] == 6:
+ continue
+ yield ip
-class ViewBuilderV10(ViewBuilder):
-
- def build(self, inst):
- private_ips = self.build_private_parts(inst)
- public_ips = self.build_public_parts(inst)
- return dict(public=public_ips, private=private_ips)
-
- def build_public_parts(self, inst):
- return utils.get_from_path(inst, 'fixed_ips/floating_ips/address')
-
- def build_private_parts(self, inst):
- return utils.get_from_path(inst, 'fixed_ips/address')
+class ViewBuilderV10(ViewBuilder):
-class ViewBuilderV11(ViewBuilder):
+ def build(self, networks):
+ if not networks:
+ return dict(public=[], private=[])
- def build(self, interfaces):
- networks = {}
- for interface in interfaces:
- try:
- network_label = self._extract_network_label(interface)
- except TypeError:
- continue
+ return dict(public=self.build_public_parts(networks),
+ private=self.build_private_parts(networks))
- if network_label not in networks:
- networks[network_label] = []
+ def build_public_parts(self, nets):
+ ips = [self._extract_ips(nets[label],
+ key='floating_ips') for label in nets]
+ return [ip['addr'] for ip in itertools.chain(*ips)]
- ip_addresses = list(self._extract_ipv4_addresses(interface))
+ def build_private_parts(self, nets):
+ ips = [self._extract_ips(nets[label], key='ips') for label in nets]
+ return [ip['addr'] for ip in itertools.chain(*ips)]
- if FLAGS.use_ipv6:
- ipv6_address = self._extract_ipv6_address(interface)
- if ipv6_address is not None:
- ip_addresses.append(ipv6_address)
- networks[network_label].extend(ip_addresses)
+class ViewBuilderV11(ViewBuilder):
- return networks
+ def build(self, networks):
+ result = {}
+ for network in networks:
+ if network not in result:
+ result[network] = []
- def build_network(self, interfaces, requested_network):
- for interface in interfaces:
- try:
- network_label = self._extract_network_label(interface)
- except TypeError:
- continue
+ result[network].extend(self._extract_ips(networks[network]))
+ return result
- if network_label == requested_network:
- ips = list(self._extract_ipv4_addresses(interface))
- ipv6 = self._extract_ipv6_address(interface)
- if ipv6 is not None:
- ips.append(ipv6)
- return {network_label: ips}
+ def build_network(self, networks, requested_network):
+ for network in networks:
+ if network == requested_network:
+ return {network: list(self._extract_ips(networks[network]))}
return None
- def _extract_network_label(self, interface):
+ def _extract_network_label(self, network):
try:
- return interface['network']['label']
+ return network['label']
except (TypeError, KeyError) as exc:
raise TypeError
-
- def _extract_ipv4_addresses(self, interface):
- for fixed_ip in interface['fixed_ips']:
- yield self._build_ip_entity(fixed_ip['address'], 4)
- for floating_ip in fixed_ip.get('floating_ips', []):
- yield self._build_ip_entity(floating_ip['address'], 4)
-
- def _extract_ipv6_address(self, interface):
- fixed_ipv6 = interface.get('fixed_ipv6')
- if fixed_ipv6 is not None:
- return self._build_ip_entity(fixed_ipv6, 6)
-
- def _build_ip_entity(self, address, version):
- return {'addr': address, 'version': version}
diff --git a/nova/api/openstack/views/servers.py b/nova/api/openstack/views/servers.py
index f3666eb6b..127a50c78 100644
--- a/nova/api/openstack/views/servers.py
+++ b/nova/api/openstack/views/servers.py
@@ -16,19 +16,19 @@
# License for the specific language governing permissions and limitations
# under the License.
-import datetime
import hashlib
import os
from nova import exception
-from nova.api.openstack import common
-from nova.api.openstack.views import addresses as addresses_view
-from nova.api.openstack.views import flavors as flavors_view
-from nova.api.openstack.views import images as images_view
+from nova import log as logging
from nova import utils
+from nova.api.openstack import common
from nova.compute import vm_states
+LOG = logging.getLogger('nova.api.openstack.views.servers')
+
+
class ViewBuilder(object):
"""Model a server response as a python dictionary.
@@ -40,13 +40,13 @@ class ViewBuilder(object):
def __init__(self, addresses_builder):
self.addresses_builder = addresses_builder
- def build(self, inst, is_detail=False):
+ def build(self, inst, networks, is_detail=False):
"""Return a dict that represenst a server."""
if inst.get('_is_precooked', False):
server = dict(server=inst)
else:
if is_detail:
- server = self._build_detail(inst)
+ server = self._build_detail(inst, networks)
else:
server = self._build_simple(inst)
@@ -59,8 +59,9 @@ class ViewBuilder(object):
servers = []
servers_links = []
- for server_obj in server_objs:
- servers.append(self.build(server_obj, is_detail)['server'])
+ for server_obj, networks in server_objs:
+ servers.append(self.build(server_obj, networks,
+ is_detail)['server'])
return dict(servers=servers)
@@ -68,7 +69,7 @@ class ViewBuilder(object):
"""Return a simple model of a server."""
return dict(server=dict(id=inst['id'], name=inst['display_name']))
- def _build_detail(self, inst):
+ def _build_detail(self, inst, networks):
"""Returns a detailed model of a server."""
vm_state = inst.get('vm_state', vm_states.BUILDING)
task_state = inst.get('task_state')
@@ -92,13 +93,13 @@ class ViewBuilder(object):
self._build_image(inst_dict, inst)
self._build_flavor(inst_dict, inst)
- self._build_addresses(inst_dict, inst)
+ self._build_addresses(inst_dict, networks)
return dict(server=inst_dict)
- def _build_addresses(self, response, inst):
+ def _build_addresses(self, response, networks):
"""Return the addresses sub-resource of a server."""
- raise NotImplementedError()
+ response['addresses'] = self.addresses_builder.build(networks)
def _build_image(self, response, inst):
"""Return the image sub-resource of a server."""
@@ -129,9 +130,6 @@ class ViewBuilderV10(ViewBuilder):
if inst.get('instance_type', None):
response['flavorId'] = inst['instance_type']['flavorid']
- def _build_addresses(self, response, inst):
- response['addresses'] = self.addresses_builder.build(inst)
-
class ViewBuilderV11(ViewBuilder):
"""Model an Openstack API V1.0 server response."""
@@ -143,8 +141,8 @@ class ViewBuilderV11(ViewBuilder):
self.base_url = base_url
self.project_id = project_id
- def _build_detail(self, inst):
- response = super(ViewBuilderV11, self)._build_detail(inst)
+ def _build_detail(self, inst, network):
+ response = super(ViewBuilderV11, self)._build_detail(inst, network)
response['server']['created'] = utils.isotime(inst['created_at'])
response['server']['updated'] = utils.isotime(inst['updated_at'])
@@ -190,10 +188,6 @@ class ViewBuilderV11(ViewBuilder):
]
}
- def _build_addresses(self, response, inst):
- interfaces = inst.get('virtual_interfaces', [])
- response['addresses'] = self.addresses_builder.build(interfaces)
-
def _build_extra(self, response, inst):
self._build_links(response, inst)
response['uuid'] = inst['uuid']
@@ -220,8 +214,9 @@ class ViewBuilderV11(ViewBuilder):
servers = []
servers_links = []
- for server_obj in server_objs:
- servers.append(self.build(server_obj, is_detail)['server'])
+ for server_obj, networks in server_objs:
+ servers.append(self.build(server_obj, networks,
+ is_detail)['server'])
if (len(servers) and limit) and (limit == len(servers)):
next_link = self.generate_next_link(servers[-1]['id'],