Akihiro Motoki d16ed45e06 Support "Get me a network" in launch instance
"Get-me-a-network" feature is supported in Nova API 2.37 or later.
To support this in horizon, a dummy "auto_allocated_network" is shown
in the launch instance form. I believe this approach fits the current
way of the launch instance form. The dummy network is a special network ID
and if specified the nova API wrapper converts 'nics' parameter properly.

In addition, a dummy "auto_allocated_network" is now shown in the network
table. This is because Neutron creates an actual auto allocated network
once a server is created specifying nics=="auto".
I believe this fake behavior brings consistency in the network table
to some extent, while this is just a compromise.

Note that this patch does not cover the network topology integration.
"auto_allocated_network" is not shown until the actual auto allocated
network is created. The network topology integration requires more work.
For example, the link for the fake auto allocated network should be
disabled in the flat view. The pop-up for the fake auto allocated network
should be disabled in the graph view.

Change-Id: I062fc1b7ed75dc771ddc7f13c8324ed4ffab6808
Closes-Bug: #1690433
2018-05-07 20:49:29 +09:00

328 lines
13 KiB
Python

#
# (c) Copyright 2015 Hewlett-Packard Development Company, L.P.
#
# 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 a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from django.http import request as django_request
import mock
from openstack_dashboard import api
from openstack_dashboard.api import base
from openstack_dashboard.api.rest import neutron
from openstack_dashboard.test import helpers as test
from openstack_dashboard.usage import quotas
class NeutronNetworksTestCase(test.TestCase):
def _dictify_network(self, network):
net_dict = network.to_dict()
net_dict['subnets'] = [s.to_dict() for s in net_dict['subnets']]
return net_dict
@mock.patch.object(api.neutron, 'network_list_for_tenant')
def test_get_list_for_tenant(self, mock_network_list_for_tenant):
request = self.mock_rest_request()
mock_network_list_for_tenant.return_value = self.networks.list()
response = neutron.Networks().get(request)
self.assertStatusCode(response, 200)
exp_resp = [self._dictify_network(n) for n in self.networks.list()]
self.assertItemsCollectionEqual(response, exp_resp)
mock_network_list_for_tenant.assert_called_once_with(
request, request.user.tenant_id,
include_pre_auto_allocate=True)
def test_create(self):
self._test_create(
'{"name": "mynetwork"}',
{'name': 'mynetwork'}
)
def test_create_with_bogus_param(self):
self._test_create(
'{"name": "mynetwork","bilbo":"baggins"}',
{'name': 'mynetwork', 'bilbo': 'baggins'}
)
@mock.patch.object(api.neutron, 'network_create')
def _test_create(self, supplied_body, expected, mock_network_create):
request = self.mock_rest_request(body=supplied_body)
mock_network_create.return_value = self.networks.first()
response = neutron.Networks().post(request)
self.assertStatusCode(response, 201)
self.assertEqual(response['location'],
'/api/neutron/networks/' + self.networks.first().id)
exp_resp = self._dictify_network(self.networks.first())
self.assertEqual(response.json, exp_resp)
mock_network_create.assert_called_once_with(request, **expected)
#
# Services
#
@test.create_mocks({api.base: ['is_service_enabled'],
api.neutron: ['is_extension_supported',
'agent_list']})
def test_services_get(self):
params = django_request.QueryDict('network_id=the_network')
request = self.mock_rest_request(GET=params)
self.mock_is_service_enabled.return_value = True
self.mock_is_extension_supported.return_value = True
self.mock_agent_list.return_value = [
mock.Mock(**{'to_dict.return_value': {'id': '1'}}),
mock.Mock(**{'to_dict.return_value': {'id': '2'}})
]
response = neutron.Services().get(request)
self.assertStatusCode(response, 200)
self.mock_is_service_enabled.assert_called_once_with(
request, 'network')
self.mock_is_extension_supported.assert_called_once_with(
request, 'agent')
self.mock_agent_list.assert_called_once_with(
request, network_id='the_network')
self.assertEqual(response.content.decode('utf-8'),
'{"items": [{"id": "1"}, {"id": "2"}]}')
@mock.patch.object(api.base, 'is_service_enabled')
def test_services_get_disabled(self, mock_is_service_enabled):
request = self.mock_rest_request(
GET={"network_id": self.networks.first().id})
mock_is_service_enabled.return_value = False
response = neutron.Services().get(request)
self.assertStatusCode(response, 501)
mock_is_service_enabled.assert_called_once_with(request, 'network')
class NeutronSubnetsTestCase(test.TestCase):
@mock.patch.object(api.neutron, 'subnet_list')
def test_get(self, mock_subnet_list):
network_id = self.networks.first().id
params = django_request.QueryDict('network_id=%s' % network_id)
request = self.mock_rest_request(GET=params)
mock_subnet_list.return_value = self.subnets.list()
response = neutron.Subnets().get(request)
self.assertStatusCode(response, 200)
mock_subnet_list.assert_called_once_with(
request, network_id=network_id)
@mock.patch.object(api.neutron, 'subnet_create')
def test_create(self, mock_subnet_create):
network_id = self.networks.first().id
request = self.mock_rest_request(
body='{"network_id": "%s",'
' "ip_version": "4",'
' "cidr": "192.168.199.0/24"}' % network_id)
mock_subnet_create.return_value = self.subnets.first()
response = neutron.Subnets().post(request)
self.assertStatusCode(response, 201)
self.assertEqual(response['location'],
'/api/neutron/subnets/' +
self.subnets.first().id)
self.assertEqual(response.json, self.subnets.first().to_dict())
mock_subnet_create.assert_called_once_with(
request, cidr='192.168.199.0/24', ip_version='4',
network_id=network_id)
class NeutronPortsTestCase(test.TestCase):
@mock.patch.object(api.neutron, 'port_list_with_trunk_types')
def test_get(self, mock_port_list_with_trunk_types):
network_id = self.networks.first().id
params = django_request.QueryDict('network_id=%s' % network_id)
request = self.mock_rest_request(GET=params)
mock_port_list_with_trunk_types.return_value = self.ports.list()
response = neutron.Ports().get(request)
self.assertStatusCode(response, 200)
mock_port_list_with_trunk_types.assert_called_once_with(
request, network_id=network_id)
class NeutronTrunkTestCase(test.TestCase):
@mock.patch.object(api.neutron, 'trunk_delete')
def test_trunk_delete(self, mock_trunk_delete):
mock_trunk_delete.return_value = None
request = self.mock_rest_request()
response = neutron.Trunk().delete(request, 1)
self.assertStatusCode(response, 204)
mock_trunk_delete.assert_called_once_with(request, 1)
@mock.patch.object(api.neutron, 'trunk_show')
def test_trunk_get(self, mock_trunk_show):
trunk_id = self.trunks.first().id
request = self.mock_rest_request(GET={"trunk_id": trunk_id})
mock_trunk_show.return_value = self.trunks.first()
response = neutron.Trunk().get(request, trunk_id=trunk_id)
self.assertStatusCode(response, 200)
mock_trunk_show.assert_called_once_with(
request, trunk_id)
@mock.patch.object(api.neutron, 'trunk_update')
def test_trunk_patch(self, mock_trunk_update):
request = self.mock_rest_request(body='''
[{"name": "trunk1"}, {"name": "trunk2"}]
''')
mock_trunk_update.return_value = self.trunks.first()
response = neutron.Trunk().patch(request, '1')
self.assertStatusCode(response, 200)
mock_trunk_update.assert_called_once_with(
request, '1', {'name': 'trunk1'}, {'name': 'trunk2'}
)
class NeutronTrunksTestCase(test.TestCase):
@mock.patch.object(api.neutron, 'trunk_list')
def test_trunks_get(self, mock_trunk_list):
request = self.mock_rest_request(GET=django_request.QueryDict())
mock_trunk_list.return_value = self.trunks.list()
response = neutron.Trunks().get(request)
self.assertStatusCode(response, 200)
self.assertItemsCollectionEqual(
response,
[t.to_dict() for t in self.trunks.list()])
mock_trunk_list.assert_called_once_with(request)
@mock.patch.object(api.neutron, 'trunk_create')
def test_trunks_create(self, mock_trunk_create):
request = self.mock_rest_request(body='''
{"name": "trunk1", "port_id": "1"}
''')
trunk = self.trunks.first()
mock_trunk_create.return_value = trunk
response = neutron.Trunks().post(request)
self.assertStatusCode(response, 201)
self.assertEqual(response.json, trunk.to_dict())
mock_trunk_create.assert_called_once_with(request, name='trunk1',
port_id='1')
class NeutronExtensionsTestCase(test.TestCase):
@mock.patch.object(api.neutron, 'list_extensions')
def test_list_extensions(self, mock_list_extensions):
request = self.mock_rest_request(**{'GET': {}})
mock_list_extensions.return_value = self.api_extensions.list()
response = neutron.Extensions().get(request)
self.assertStatusCode(response, 200)
self.assertItemsCollectionEqual(response, self.api_extensions.list())
mock_list_extensions.assert_called_once_with(request)
class NeutronDefaultQuotasTestCase(test.TestCase):
@test.create_mocks({api.base: ['is_service_enabled'],
api.neutron: ['tenant_quota_get']})
def test_quotas_sets_defaults_get_when_service_is_enabled(self):
filters = {'user': {'tenant_id': 'tenant'}}
request = self.mock_rest_request(**{'GET': dict(filters)})
self.mock_is_service_enabled.return_value = True
self.mock_tenant_quota_get.return_value = [
base.Quota("network", 100),
base.Quota("q2", 101)]
response = neutron.DefaultQuotaSets().get(request)
self.assertStatusCode(response, 200)
self.assertItemsCollectionEqual(response, [
{'limit': 100, 'display_name': 'Networks', 'name': 'network'},
{'limit': 101, 'display_name': 'Q2', 'name': 'q2'}])
self.mock_is_service_enabled.assert_called_once_with(
request, 'network')
self.mock_tenant_quota_get.assert_called_once_with(
request,
request.user.tenant_id)
@mock.patch.object(api.base, 'is_service_enabled')
def test_quota_sets_defaults_get_when_service_is_disabled(
self, mock_is_service_enabled):
filters = {'user': {'tenant_id': 'tenant'}}
request = self.mock_rest_request(**{'GET': dict(filters)})
mock_is_service_enabled.return_value = False
response = neutron.DefaultQuotaSets().get(request)
self.assertStatusCode(response, 501)
self.assertEqual(response.content.decode('utf-8'),
'"Service Neutron is disabled."')
mock_is_service_enabled.assert_called_once_with(request, 'network')
class NeutronQuotaSetsTestCase(test.TestCase):
@test.create_mocks({api.base: ['is_service_enabled'],
api.neutron: ['is_extension_supported',
'tenant_quota_update'],
quotas: ['get_disabled_quotas']})
def test_quotas_sets_patch(self):
request = self.mock_rest_request(body='''
{"network": "5", "subnet": "5", "port": "50",
"router": "5", "floatingip": "50",
"security_group": "5", "security_group_rule": "50",
"volumes": "5", "cores": "50"}
''')
self.mock_get_disabled_quotas.return_value = []
self.mock_is_service_enabled.return_value = True
self.mock_is_extension_supported.return_value = True
self.mock_tenant_quota_update.return_value = None
response = neutron.QuotasSets().patch(request, 'spam123')
self.assertStatusCode(response, 204)
self.assertEqual(response.content.decode('utf-8'), '')
self.mock_get_disabled_quotas.assert_called_once_with(request)
self.mock_is_service_enabled.assert_called_once_with(
request, 'network')
self.mock_is_extension_supported.assert_called_once_with(
request, 'quotas')
self.mock_tenant_quota_update.assert_called_once_with(
request, 'spam123', network='5',
subnet='5', port='50', router='5',
floatingip='50', security_group='5',
security_group_rule='50')
@test.create_mocks({api.base: ['is_service_enabled'],
quotas: ['get_disabled_quotas']})
def test_quotas_sets_patch_when_service_is_disabled(self):
request = self.mock_rest_request(body='''
{"network": "5", "subnet": "5", "port": "50",
"router": "5", "floatingip": "50",
"security_group": "5", "security_group_rule": "50",
"volumes": "5", "cores": "50"}
''')
self.mock_get_disabled_quotas.return_value = []
self.mock_is_service_enabled.return_value = False
response = neutron.QuotasSets().patch(request, 'spam123')
message = ('"Service Neutron is disabled or '
'quotas extension not available."')
self.assertStatusCode(response, 501)
self.assertEqual(response.content.decode('utf-8'), message)
self.mock_get_disabled_quotas.assert_called_once_with(request)
self.mock_is_service_enabled.assert_called_once_with(
request, 'network')