Merge "Add public network support when launching an instance."
This commit is contained in:
commit
ca6505ef66
@ -1,5 +1,6 @@
|
||||
# Copyright 2012 OpenStack LLC.
|
||||
# All Rights Reserved
|
||||
# Copyright (c) 2012 NEC Corporation
|
||||
#
|
||||
# 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
|
||||
@ -60,27 +61,43 @@ class API(base.Base):
|
||||
teardown=False):
|
||||
"""Setup or teardown the network structures."""
|
||||
|
||||
def _get_available_networks(self, context, project_id,
|
||||
net_ids=None):
|
||||
"""Return a network list available for the tenant.
|
||||
The list contains networks owned by the tenant and public networks.
|
||||
If net_ids specified, it searches networks with requested IDs only.
|
||||
"""
|
||||
quantum = quantumv2.get_client(context)
|
||||
|
||||
# If user has specified to attach instance only to specific
|
||||
# networks, add them to **search_opts
|
||||
# (1) Retrieve non-public network list owned by the tenant.
|
||||
search_opts = {"tenant_id": project_id, 'shared': False}
|
||||
if net_ids:
|
||||
search_opts['id'] = net_ids
|
||||
nets = quantum.list_networks(**search_opts).get('networks', [])
|
||||
# (2) Retrieve public network list.
|
||||
search_opts = {'shared': True}
|
||||
if net_ids:
|
||||
search_opts['id'] = net_ids
|
||||
nets += quantum.list_networks(**search_opts).get('networks', [])
|
||||
|
||||
return nets
|
||||
|
||||
def allocate_for_instance(self, context, instance, **kwargs):
|
||||
"""Allocate all network resources for the instance."""
|
||||
quantum = quantumv2.get_client(context)
|
||||
LOG.debug(_('allocate_for_instance() for %s'),
|
||||
instance['display_name'])
|
||||
search_opts = {}
|
||||
if instance['project_id']:
|
||||
search_opts.update({"tenant_id": instance['project_id']})
|
||||
else:
|
||||
if not instance['project_id']:
|
||||
msg = _('empty project id for instance %s')
|
||||
raise exception.InvalidInput(
|
||||
reason=msg % instance['display_name'])
|
||||
|
||||
# If user has specified to attach instance only to specific
|
||||
# networks, add them to **search_opts
|
||||
# Tenant-only network only allowed so far
|
||||
requested_networks = kwargs.get('requested_networks')
|
||||
ports = {}
|
||||
fixed_ips = {}
|
||||
net_ids = []
|
||||
if requested_networks:
|
||||
net_ids = []
|
||||
for network_id, fixed_ip, port_id in requested_networks:
|
||||
if port_id:
|
||||
port = quantum.show_port(port_id).get('port')
|
||||
@ -89,10 +106,9 @@ class API(base.Base):
|
||||
elif fixed_ip:
|
||||
fixed_ips[network_id] = fixed_ip
|
||||
net_ids.append(network_id)
|
||||
search_opts['id'] = net_ids
|
||||
|
||||
data = quantum.list_networks(**search_opts)
|
||||
nets = data.get('networks', [])
|
||||
nets = self._get_available_networks(context, instance['project_id'],
|
||||
net_ids)
|
||||
|
||||
touched_port_ids = []
|
||||
created_port_ids = []
|
||||
@ -166,12 +182,11 @@ class API(base.Base):
|
||||
raise NotImplementedError()
|
||||
|
||||
def validate_networks(self, context, requested_networks):
|
||||
"""Validate that the tenant has the requested networks."""
|
||||
"""Validate that the tenant can use the requested networks."""
|
||||
LOG.debug(_('validate_networks() for %s'),
|
||||
requested_networks)
|
||||
if not requested_networks:
|
||||
return
|
||||
search_opts = {"tenant_id": context.project_id}
|
||||
net_ids = []
|
||||
|
||||
for (net_id, _i, port_id) in requested_networks:
|
||||
@ -188,9 +203,8 @@ class API(base.Base):
|
||||
raise exception.NetworkDuplicated(network_id=net_id)
|
||||
net_ids.append(net_id)
|
||||
|
||||
search_opts['id'] = net_ids
|
||||
data = quantumv2.get_client(context).list_networks(**search_opts)
|
||||
nets = data.get('networks', [])
|
||||
nets = self._get_available_networks(context, context.project_id,
|
||||
net_ids)
|
||||
if len(nets) != len(net_ids):
|
||||
requsted_netid_set = set(net_ids)
|
||||
returned_netid_set = set([net['id'] for net in nets])
|
||||
@ -294,11 +308,8 @@ class API(base.Base):
|
||||
data = quantumv2.get_client(context).list_ports(**search_opts)
|
||||
ports = data.get('ports', [])
|
||||
if not networks:
|
||||
search_opts = {}
|
||||
if instance['project_id']:
|
||||
search_opts.update({"tenant_id": instance['project_id']})
|
||||
data = quantumv2.get_client(context).list_networks(**search_opts)
|
||||
networks = data.get('networks', [])
|
||||
networks = self._get_available_networks(context,
|
||||
instance['project_id'])
|
||||
nw_info = network_model.NetworkInfo()
|
||||
for port in ports:
|
||||
network_name = None
|
||||
@ -307,12 +318,12 @@ class API(base.Base):
|
||||
network_name = net['name']
|
||||
break
|
||||
|
||||
subnets = self._get_subnets_from_port(context, port)
|
||||
network_IPs = [network_model.FixedIP(address=ip_address)
|
||||
for ip_address in [ip['ip_address']
|
||||
for ip in port['fixed_ips']]]
|
||||
# TODO(gongysh) get floating_ips for each fixed_ip
|
||||
|
||||
subnets = self._get_subnets_from_port(context, port)
|
||||
for subnet in subnets:
|
||||
subnet['ips'] = [fixed_ip for fixed_ip in network_IPs
|
||||
if fixed_ip.is_in_subnet(subnet)]
|
||||
|
@ -155,7 +155,10 @@ class TestQuantumv2(test.TestCase):
|
||||
self.nets3 = self.nets2 + [{'id': 'my_netid3',
|
||||
'name': 'my_netname3',
|
||||
'tenant_id': 'my_tenantid'}]
|
||||
self.nets = [self.nets1, self.nets2, self.nets3]
|
||||
self.nets4 = [{'id': 'his_netid4',
|
||||
'name': 'his_netname4',
|
||||
'tenant_id': 'his_tenantid'}]
|
||||
self.nets = [self.nets1, self.nets2, self.nets3, self.nets4]
|
||||
|
||||
self.port_data1 = [{'network_id': 'my_netid1',
|
||||
'device_id': 'device_id1',
|
||||
@ -214,8 +217,10 @@ class TestQuantumv2(test.TestCase):
|
||||
{'ports': port_data})
|
||||
nets = number == 1 and self.nets1 or self.nets2
|
||||
self.moxed_client.list_networks(
|
||||
tenant_id=self.instance['project_id']).AndReturn(
|
||||
{'networks': nets})
|
||||
tenant_id=self.instance['project_id'],
|
||||
shared=False).AndReturn({'networks': nets})
|
||||
self.moxed_client.list_networks(
|
||||
shared=True).AndReturn({'networks': []})
|
||||
for i in xrange(1, number + 1):
|
||||
subnet_data = i == 1 and self.subnet_data1 or self.subnet_data2
|
||||
self.moxed_client.list_subnets(
|
||||
@ -263,11 +268,10 @@ class TestQuantumv2(test.TestCase):
|
||||
self.instance,
|
||||
networks=nets).AndReturn(None)
|
||||
|
||||
mox_list_network_params = dict(tenant_id=self.instance['project_id'])
|
||||
ports = {}
|
||||
fixed_ips = {}
|
||||
req_net_ids = []
|
||||
if 'requested_networks' in kwargs:
|
||||
req_net_ids = []
|
||||
for id, fixed_ip, port_id in kwargs['requested_networks']:
|
||||
if port_id:
|
||||
self.moxed_client.show_port(port_id).AndReturn(
|
||||
@ -279,12 +283,21 @@ class TestQuantumv2(test.TestCase):
|
||||
else:
|
||||
fixed_ips[id] = fixed_ip
|
||||
req_net_ids.append(id)
|
||||
search_ids = [net['id'] for net in nets if net['id'] in req_net_ids]
|
||||
|
||||
mox_list_network_params['id'] = [net['id'] for net in nets
|
||||
if net['id'] in req_net_ids]
|
||||
mox_list_network_params = dict(tenant_id=self.instance['project_id'],
|
||||
shared=False)
|
||||
if search_ids:
|
||||
mox_list_network_params['id'] = search_ids
|
||||
self.moxed_client.list_networks(
|
||||
**mox_list_network_params).AndReturn({'networks': nets})
|
||||
|
||||
mox_list_network_params = dict(shared=True)
|
||||
if search_ids:
|
||||
mox_list_network_params['id'] = search_ids
|
||||
self.moxed_client.list_networks(
|
||||
**mox_list_network_params).AndReturn({'networks': []})
|
||||
|
||||
for network in nets:
|
||||
port_req_body = {
|
||||
'port': {
|
||||
@ -349,8 +362,11 @@ class TestQuantumv2(test.TestCase):
|
||||
"""
|
||||
api = quantumapi.API()
|
||||
self.moxed_client.list_networks(
|
||||
tenant_id=self.instance['project_id']).AndReturn(
|
||||
tenant_id=self.instance['project_id'],
|
||||
shared=False).AndReturn(
|
||||
{'networks': self.nets2})
|
||||
self.moxed_client.list_networks(shared=True).AndReturn(
|
||||
{'networks': []})
|
||||
index = 0
|
||||
for network in self.nets2:
|
||||
port_req_body = {
|
||||
@ -385,8 +401,11 @@ class TestQuantumv2(test.TestCase):
|
||||
"""
|
||||
api = quantumapi.API()
|
||||
self.moxed_client.list_networks(
|
||||
tenant_id=self.instance['project_id']).AndReturn(
|
||||
tenant_id=self.instance['project_id'],
|
||||
shared=False).AndReturn(
|
||||
{'networks': self.nets2})
|
||||
self.moxed_client.list_networks(shared=True).AndReturn(
|
||||
{'networks': []})
|
||||
port_req_body = {
|
||||
'port': {
|
||||
'network_id': self.nets2[0]['id'],
|
||||
@ -426,8 +445,13 @@ class TestQuantumv2(test.TestCase):
|
||||
('my_netid2', 'test2', None)]
|
||||
self.moxed_client.list_networks(
|
||||
id=mox.SameElementsAs(['my_netid1', 'my_netid2']),
|
||||
tenant_id=self.context.project_id).AndReturn(
|
||||
tenant_id=self.context.project_id,
|
||||
shared=False).AndReturn(
|
||||
{'networks': self.nets2})
|
||||
self.moxed_client.list_networks(
|
||||
id=mox.SameElementsAs(['my_netid1', 'my_netid2']),
|
||||
shared=True).AndReturn(
|
||||
{'networks': []})
|
||||
self.mox.ReplayAll()
|
||||
api = quantumapi.API()
|
||||
api.validate_networks(self.context, requested_networks)
|
||||
@ -437,8 +461,13 @@ class TestQuantumv2(test.TestCase):
|
||||
('my_netid2', 'test2', None)]
|
||||
self.moxed_client.list_networks(
|
||||
id=mox.SameElementsAs(['my_netid1', 'my_netid2']),
|
||||
tenant_id=self.context.project_id).AndReturn(
|
||||
tenant_id=self.context.project_id,
|
||||
shared=False).AndReturn(
|
||||
{'networks': self.nets1})
|
||||
self.moxed_client.list_networks(
|
||||
id=mox.SameElementsAs(['my_netid1', 'my_netid2']),
|
||||
shared=True).AndReturn(
|
||||
{'networks': []})
|
||||
self.mox.ReplayAll()
|
||||
api = quantumapi.API()
|
||||
try:
|
||||
@ -452,8 +481,13 @@ class TestQuantumv2(test.TestCase):
|
||||
('my_netid3', 'test3', None)]
|
||||
self.moxed_client.list_networks(
|
||||
id=mox.SameElementsAs(['my_netid1', 'my_netid2', 'my_netid3']),
|
||||
tenant_id=self.context.project_id).AndReturn(
|
||||
tenant_id=self.context.project_id,
|
||||
shared=False).AndReturn(
|
||||
{'networks': self.nets1})
|
||||
self.moxed_client.list_networks(
|
||||
id=mox.SameElementsAs(['my_netid1', 'my_netid2', 'my_netid3']),
|
||||
shared=True).AndReturn(
|
||||
{'networks': []})
|
||||
self.mox.ReplayAll()
|
||||
api = quantumapi.API()
|
||||
try:
|
||||
@ -471,3 +505,40 @@ class TestQuantumv2(test.TestCase):
|
||||
result = api.get_instance_uuids_by_ip_filter(self.context, filters)
|
||||
self.assertEquals('device_id1', result[0]['instance_uuid'])
|
||||
self.assertEquals('device_id2', result[1]['instance_uuid'])
|
||||
|
||||
def _get_available_networks(self, prv_nets, pub_nets, req_ids=None):
|
||||
api = quantumapi.API()
|
||||
nets = prv_nets + pub_nets
|
||||
mox_list_network_params = dict(tenant_id=self.instance['project_id'],
|
||||
shared=False)
|
||||
if req_ids:
|
||||
mox_list_network_params['id'] = req_ids
|
||||
self.moxed_client.list_networks(
|
||||
**mox_list_network_params).AndReturn({'networks': prv_nets})
|
||||
mox_list_network_params = dict(shared=True)
|
||||
if req_ids:
|
||||
mox_list_network_params['id'] = req_ids
|
||||
self.moxed_client.list_networks(
|
||||
**mox_list_network_params).AndReturn({'networks': pub_nets})
|
||||
|
||||
self.mox.ReplayAll()
|
||||
rets = api._get_available_networks(self.context,
|
||||
self.instance['project_id'],
|
||||
req_ids)
|
||||
self.assertEqual(rets, nets)
|
||||
|
||||
def test_get_available_networks_all_private(self):
|
||||
self._get_available_networks(prv_nets=self.nets2, pub_nets=[])
|
||||
|
||||
def test_get_available_networks_all_public(self):
|
||||
self._get_available_networks(prv_nets=[], pub_nets=self.nets2)
|
||||
|
||||
def test_get_available_networks_private_and_public(self):
|
||||
self._get_available_networks(prv_nets=self.nets1, pub_nets=self.nets4)
|
||||
|
||||
def test_get_available_networks_with_network_ids(self):
|
||||
prv_nets = [self.nets3[0]]
|
||||
pub_nets = [self.nets3[-1]]
|
||||
# specify only first and last network
|
||||
req_ids = [net['id'] for net in (self.nets3[0], self.nets3[-1])]
|
||||
self._get_available_networks(prv_nets, pub_nets, req_ids)
|
||||
|
Loading…
Reference in New Issue
Block a user