diff options
| author | Jenkins <jenkins@review.openstack.org> | 2012-09-03 07:38:23 +0000 |
|---|---|---|
| committer | Gerrit Code Review <review@openstack.org> | 2012-09-03 07:38:23 +0000 |
| commit | ca6505ef66ecdd948325ee37b627e813cc5ad56d (patch) | |
| tree | b816796216b330790f98dde4f01e077e0633500b /nova | |
| parent | 5f17495ac66dfaec329fa4484efba4bd57a625c2 (diff) | |
| parent | 8e09b93f4ff4c782e6552638f0099b92523000ab (diff) | |
Merge "Add public network support when launching an instance."
Diffstat (limited to 'nova')
| -rw-r--r-- | nova/network/quantumv2/api.py | 57 | ||||
| -rw-r--r-- | nova/tests/network/test_quantumv2.py | 95 |
2 files changed, 117 insertions, 35 deletions
diff --git a/nova/network/quantumv2/api.py b/nova/network/quantumv2/api.py index 990af4c37..50c517f7d 100644 --- a/nova/network/quantumv2/api.py +++ b/nova/network/quantumv2/api.py @@ -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)] diff --git a/nova/tests/network/test_quantumv2.py b/nova/tests/network/test_quantumv2.py index 7ee814b6b..4c41cfd39 100644 --- a/nova/tests/network/test_quantumv2.py +++ b/nova/tests/network/test_quantumv2.py @@ -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) |
