Implement setting availability zone hint on network creation
If the 'network_availability_zone'-extension is enabled, this patch adds a field to the Create Network-workflow named 'Availability Zone Hints'. Change-Id: Ic4206d5765c2d01afedf0e64f9aa50ffce76b661 Closes-Bug: #1725617
This commit is contained in:
parent
5d386afb1a
commit
b5896d6fbb
|
@ -139,6 +139,12 @@ class CreateNetwork(forms.SelfHandlingForm):
|
|||
}),
|
||||
initial=True,
|
||||
required=False)
|
||||
az_hints = forms.MultipleChoiceField(
|
||||
label=_("Availability Zone Hints"),
|
||||
required=False,
|
||||
help_text=_("Availability zones where the DHCP agents may be "
|
||||
"scheduled. Leaving this unset is equivalent to "
|
||||
"selecting all availability zones"))
|
||||
|
||||
@classmethod
|
||||
def _instantiate(cls, request, *args, **kwargs):
|
||||
|
@ -237,6 +243,20 @@ class CreateNetwork(forms.SelfHandlingForm):
|
|||
else:
|
||||
self.fields['network_type'].choices = network_type_choices
|
||||
|
||||
try:
|
||||
if api.neutron.is_extension_supported(request,
|
||||
'network_availability_zone'):
|
||||
zones = api.neutron.list_availability_zones(
|
||||
self.request, 'network', 'available')
|
||||
self.fields['az_hints'].choices = [(zone['name'], zone['name'])
|
||||
for zone in zones]
|
||||
else:
|
||||
del self.fields['az_hints']
|
||||
except Exception:
|
||||
msg = _('Failed to get availability zone list.')
|
||||
messages.warning(request, msg)
|
||||
del self.fields['az_hints']
|
||||
|
||||
def _hide_provider_network_type(self):
|
||||
self.fields['network_type'].widget = forms.HiddenInput()
|
||||
self.fields['physical_network'].widget = forms.HiddenInput()
|
||||
|
@ -261,6 +281,8 @@ class CreateNetwork(forms.SelfHandlingForm):
|
|||
if network_type in self.nettypes_with_seg_id:
|
||||
params['provider:segmentation_id'] = (
|
||||
data['segmentation_id'])
|
||||
if 'az_hints' in data and data['az_hints']:
|
||||
params['availability_zone_hints'] = data['az_hints']
|
||||
network = api.neutron.network_create(request, **params)
|
||||
LOG.debug('Network %s was successfully created.', data['name'])
|
||||
return network
|
||||
|
|
|
@ -463,6 +463,9 @@ class NetworkTests(test.BaseAdminViewTests):
|
|||
'with_subnet': False}
|
||||
api.neutron.is_extension_supported(IsA(http.HttpRequest), 'provider').\
|
||||
MultipleTimes().AndReturn(True)
|
||||
api.neutron.is_extension_supported(IsA(http.HttpRequest),
|
||||
'network_availability_zone').\
|
||||
MultipleTimes().AndReturn(False)
|
||||
api.neutron.is_extension_supported(IsA(http.HttpRequest),
|
||||
'subnet_allocation').\
|
||||
MultipleTimes().AndReturn(True)
|
||||
|
@ -485,6 +488,57 @@ class NetworkTests(test.BaseAdminViewTests):
|
|||
self.assertNoFormErrors(res)
|
||||
self.assertRedirectsNoFollow(res, INDEX_URL)
|
||||
|
||||
@test.create_stubs({api.neutron: ('network_create',
|
||||
'is_extension_supported',
|
||||
'list_availability_zones',
|
||||
'subnetpool_list'),
|
||||
api.keystone: ('tenant_list',)})
|
||||
def test_network_create_post_with_az(self):
|
||||
tenants = self.tenants.list()
|
||||
tenant_id = self.tenants.first().id
|
||||
network = self.networks.first()
|
||||
|
||||
api.keystone.tenant_list(IsA(http.HttpRequest))\
|
||||
.AndReturn([tenants, False])
|
||||
params = {'name': network.name,
|
||||
'tenant_id': tenant_id,
|
||||
'admin_state_up': network.admin_state_up,
|
||||
'router:external': True,
|
||||
'shared': True,
|
||||
'provider:network_type': 'local',
|
||||
'with_subnet': False,
|
||||
'az_hints': ['nova']}
|
||||
api.neutron.is_extension_supported(IsA(http.HttpRequest), 'provider').\
|
||||
MultipleTimes().AndReturn(True)
|
||||
api.neutron.is_extension_supported(IsA(http.HttpRequest),
|
||||
'network_availability_zone').\
|
||||
MultipleTimes().AndReturn(True)
|
||||
api.neutron.list_availability_zones(IsA(http.HttpRequest),
|
||||
"network", "available")\
|
||||
.AndReturn(self.neutron_availability_zones.list())
|
||||
api.neutron.is_extension_supported(IsA(http.HttpRequest),
|
||||
'subnet_allocation').\
|
||||
MultipleTimes().AndReturn(True)
|
||||
api.neutron.subnetpool_list(IsA(http.HttpRequest)).\
|
||||
AndReturn(self.subnetpools.list())
|
||||
api.neutron.network_create(IsA(http.HttpRequest), **params)\
|
||||
.AndReturn(network)
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
form_data = {'tenant_id': tenant_id,
|
||||
'name': network.name,
|
||||
'admin_state': network.admin_state_up,
|
||||
'external': True,
|
||||
'shared': True,
|
||||
'network_type': 'local',
|
||||
'availability_zone_hints': ['nova']}
|
||||
url = reverse('horizon:admin:networks:create')
|
||||
res = self.client.post(url, form_data)
|
||||
|
||||
self.assertNoFormErrors(res)
|
||||
self.assertRedirectsNoFollow(res, INDEX_URL)
|
||||
|
||||
@test.create_stubs({api.neutron: ('network_create',
|
||||
'subnet_create',
|
||||
'is_extension_supported',
|
||||
|
@ -508,6 +562,9 @@ class NetworkTests(test.BaseAdminViewTests):
|
|||
|
||||
api.neutron.is_extension_supported(IsA(http.HttpRequest), 'provider').\
|
||||
MultipleTimes().AndReturn(True)
|
||||
api.neutron.is_extension_supported(IsA(http.HttpRequest),
|
||||
'network_availability_zone').\
|
||||
MultipleTimes().AndReturn(False)
|
||||
api.neutron.is_extension_supported(IsA(http.HttpRequest),
|
||||
'subnet_allocation').\
|
||||
MultipleTimes().AndReturn(True)
|
||||
|
@ -551,6 +608,9 @@ class NetworkTests(test.BaseAdminViewTests):
|
|||
'with_subnet': False}
|
||||
api.neutron.is_extension_supported(IsA(http.HttpRequest), 'provider').\
|
||||
MultipleTimes().AndReturn(True)
|
||||
api.neutron.is_extension_supported(IsA(http.HttpRequest),
|
||||
'network_availability_zone').\
|
||||
MultipleTimes().AndReturn(False)
|
||||
api.neutron.is_extension_supported(IsA(http.HttpRequest),
|
||||
'subnet_allocation').\
|
||||
MultipleTimes().AndReturn(True)
|
||||
|
@ -581,6 +641,9 @@ class NetworkTests(test.BaseAdminViewTests):
|
|||
api.keystone.tenant_list(
|
||||
IsA(http.HttpRequest)
|
||||
).MultipleTimes().AndReturn([tenants, False])
|
||||
api.neutron.is_extension_supported(IsA(http.HttpRequest),
|
||||
'network_availability_zone').\
|
||||
MultipleTimes().AndReturn(False)
|
||||
api.neutron.is_extension_supported(IsA(http.HttpRequest), 'provider')\
|
||||
.MultipleTimes().AndReturn(True)
|
||||
|
||||
|
@ -611,6 +674,9 @@ class NetworkTests(test.BaseAdminViewTests):
|
|||
IsA(http.HttpRequest)
|
||||
).MultipleTimes().AndReturn([tenants, False])
|
||||
|
||||
api.neutron.is_extension_supported(IsA(http.HttpRequest),
|
||||
'network_availability_zone').\
|
||||
MultipleTimes().AndReturn(False)
|
||||
api.neutron.is_extension_supported(IsA(http.HttpRequest), 'provider').\
|
||||
MultipleTimes().AndReturn(True)
|
||||
self.mox.ReplayAll()
|
||||
|
@ -642,6 +708,9 @@ class NetworkTests(test.BaseAdminViewTests):
|
|||
IsA(http.HttpRequest)
|
||||
).MultipleTimes().AndReturn([tenants, False])
|
||||
|
||||
api.neutron.is_extension_supported(IsA(http.HttpRequest),
|
||||
'network_availability_zone').\
|
||||
MultipleTimes().AndReturn(False)
|
||||
api.neutron.is_extension_supported(IsA(http.HttpRequest), 'provider')\
|
||||
.MultipleTimes().AndReturn(True)
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ class CreateNetworkInfoAction(network_workflows.CreateNetworkInfoAction):
|
|||
|
||||
class CreateNetworkInfo(network_workflows.CreateNetworkInfo):
|
||||
action_class = CreateNetworkInfoAction
|
||||
contributes = ("net_name", "admin_state", "with_subnet")
|
||||
contributes = ("net_name", "admin_state", "with_subnet", "az_hints")
|
||||
|
||||
def __init__(self, workflow):
|
||||
self.contributes = tuple(workflow.create_network_form.fields.keys())
|
||||
|
|
|
@ -362,6 +362,9 @@ class NetworkTests(test.TestCase, NetworkStubMixin):
|
|||
@test.create_stubs({api.neutron: ('is_extension_supported',
|
||||
'subnetpool_list')})
|
||||
def test_network_create_get(self):
|
||||
api.neutron.is_extension_supported(IsA(http.HttpRequest),
|
||||
'network_availability_zone').\
|
||||
AndReturn(False)
|
||||
api.neutron.is_extension_supported(IsA(http.HttpRequest),
|
||||
'subnet_allocation').\
|
||||
AndReturn(True)
|
||||
|
@ -388,6 +391,9 @@ class NetworkTests(test.TestCase, NetworkStubMixin):
|
|||
params = {'name': network.name,
|
||||
'admin_state_up': network.admin_state_up,
|
||||
'shared': False}
|
||||
api.neutron.is_extension_supported(IsA(http.HttpRequest),
|
||||
'network_availability_zone').\
|
||||
AndReturn(False)
|
||||
api.neutron.is_extension_supported(IsA(http.HttpRequest),
|
||||
'subnet_allocation').\
|
||||
AndReturn(True)
|
||||
|
@ -409,6 +415,43 @@ class NetworkTests(test.TestCase, NetworkStubMixin):
|
|||
self.assertNoFormErrors(res)
|
||||
self.assertRedirectsNoFollow(res, INDEX_URL)
|
||||
|
||||
@test.create_stubs({api.neutron: ('network_create',
|
||||
'is_extension_supported',
|
||||
'list_availability_zones',
|
||||
'subnetpool_list')})
|
||||
def test_network_create_post_with_az(self):
|
||||
network = self.networks.first()
|
||||
params = {'name': network.name,
|
||||
'admin_state_up': network.admin_state_up,
|
||||
'shared': False,
|
||||
'az_hints': ['nova']}
|
||||
api.neutron.is_extension_supported(IsA(http.HttpRequest),
|
||||
'network_availability_zone').\
|
||||
AndReturn(True)
|
||||
api.neutron.list_availability_zones(IsA(http.HttpRequest),
|
||||
"network", "available")\
|
||||
.AndReturn(self.neutron_availability_zones.list())
|
||||
api.neutron.is_extension_supported(IsA(http.HttpRequest),
|
||||
'subnet_allocation').\
|
||||
AndReturn(True)
|
||||
api.neutron.subnetpool_list(IsA(http.HttpRequest)).\
|
||||
AndReturn(self.subnetpools.list())
|
||||
api.neutron.network_create(IsA(http.HttpRequest),
|
||||
**params).AndReturn(network)
|
||||
self.mox.ReplayAll()
|
||||
|
||||
form_data = {'net_name': network.name,
|
||||
'admin_state': network.admin_state_up,
|
||||
'shared': False,
|
||||
'with_subnet': False,
|
||||
'availability_zone_hints': ['nova']}
|
||||
form_data.update(form_data_no_subnet())
|
||||
url = reverse('horizon:project:networks:create')
|
||||
res = self.client.post(url, form_data)
|
||||
|
||||
self.assertNoFormErrors(res)
|
||||
self.assertRedirectsNoFollow(res, INDEX_URL)
|
||||
|
||||
@test.create_stubs({api.neutron: ('network_create',
|
||||
'is_extension_supported',
|
||||
'subnetpool_list')})
|
||||
|
@ -417,6 +460,9 @@ class NetworkTests(test.TestCase, NetworkStubMixin):
|
|||
params = {'name': network.name,
|
||||
'admin_state_up': network.admin_state_up,
|
||||
'shared': True}
|
||||
api.neutron.is_extension_supported(IsA(http.HttpRequest),
|
||||
'network_availability_zone').\
|
||||
AndReturn(False)
|
||||
api.neutron.is_extension_supported(IsA(http.HttpRequest),
|
||||
'subnet_allocation').\
|
||||
AndReturn(True)
|
||||
|
@ -458,6 +504,9 @@ class NetworkTests(test.TestCase, NetworkStubMixin):
|
|||
if not test_with_ipv6:
|
||||
subnet.ip_version = 4
|
||||
subnet_params['ip_version'] = subnet.ip_version
|
||||
api.neutron.is_extension_supported(IsA(http.HttpRequest),
|
||||
'network_availability_zone').\
|
||||
AndReturn(False)
|
||||
api.neutron.is_extension_supported(IsA(http.HttpRequest),
|
||||
'subnet_allocation').\
|
||||
AndReturn(True)
|
||||
|
@ -492,6 +541,9 @@ class NetworkTests(test.TestCase, NetworkStubMixin):
|
|||
params = {'name': network.name,
|
||||
'shared': False,
|
||||
'admin_state_up': network.admin_state_up}
|
||||
api.neutron.is_extension_supported(IsA(http.HttpRequest),
|
||||
'network_availability_zone').\
|
||||
AndReturn(False)
|
||||
api.neutron.is_extension_supported(IsA(http.HttpRequest),
|
||||
'subnet_allocation').\
|
||||
AndReturn(True)
|
||||
|
@ -516,15 +568,15 @@ class NetworkTests(test.TestCase, NetworkStubMixin):
|
|||
@test.create_stubs({api.neutron: ('network_create',
|
||||
'is_extension_supported',
|
||||
'subnetpool_list')})
|
||||
def test_network_create_post_with_subnet_network_exception(
|
||||
self,
|
||||
test_with_subnetpool=False,
|
||||
):
|
||||
def test_network_create_post_with_subnet_network_exception(self):
|
||||
network = self.networks.first()
|
||||
subnet = self.subnets.first()
|
||||
params = {'name': network.name,
|
||||
'shared': False,
|
||||
'admin_state_up': network.admin_state_up}
|
||||
api.neutron.is_extension_supported(IsA(http.HttpRequest),
|
||||
'network_availability_zone').\
|
||||
AndReturn(False)
|
||||
api.neutron.is_extension_supported(IsA(http.HttpRequest),
|
||||
'subnet_allocation').\
|
||||
AndReturn(True)
|
||||
|
@ -556,6 +608,9 @@ class NetworkTests(test.TestCase, NetworkStubMixin):
|
|||
params = {'name': network.name,
|
||||
'shared': False,
|
||||
'admin_state_up': network.admin_state_up}
|
||||
api.neutron.is_extension_supported(IsA(http.HttpRequest),
|
||||
'network_availability_zone').\
|
||||
AndReturn(False)
|
||||
api.neutron.is_extension_supported(IsA(http.HttpRequest),
|
||||
'subnet_allocation').\
|
||||
AndReturn(True)
|
||||
|
@ -592,6 +647,9 @@ class NetworkTests(test.TestCase, NetworkStubMixin):
|
|||
test_with_snpool=False):
|
||||
network = self.networks.first()
|
||||
subnet = self.subnets.first()
|
||||
api.neutron.is_extension_supported(IsA(http.HttpRequest),
|
||||
'network_availability_zone').\
|
||||
AndReturn(False)
|
||||
api.neutron.is_extension_supported(IsA(http.HttpRequest),
|
||||
'subnet_allocation').\
|
||||
AndReturn(True)
|
||||
|
@ -627,6 +685,9 @@ class NetworkTests(test.TestCase, NetworkStubMixin):
|
|||
):
|
||||
network = self.networks.first()
|
||||
subnet = self.subnets.first()
|
||||
api.neutron.is_extension_supported(IsA(http.HttpRequest),
|
||||
'network_availability_zone').\
|
||||
AndReturn(False)
|
||||
api.neutron.is_extension_supported(IsA(http.HttpRequest),
|
||||
'subnet_allocation').\
|
||||
AndReturn(True)
|
||||
|
@ -665,6 +726,9 @@ class NetworkTests(test.TestCase, NetworkStubMixin):
|
|||
network = self.networks.first()
|
||||
subnet = self.subnets.first()
|
||||
|
||||
api.neutron.is_extension_supported(IsA(http.HttpRequest),
|
||||
'network_availability_zone').\
|
||||
AndReturn(False)
|
||||
api.neutron.is_extension_supported(IsA(http.HttpRequest),
|
||||
'subnet_allocation').\
|
||||
AndReturn(True)
|
||||
|
@ -707,6 +771,9 @@ class NetworkTests(test.TestCase, NetworkStubMixin):
|
|||
network = self.networks.first()
|
||||
subnet_v6 = self.subnets.list()[4]
|
||||
|
||||
api.neutron.is_extension_supported(IsA(http.HttpRequest),
|
||||
'network_availability_zone').\
|
||||
AndReturn(False)
|
||||
api.neutron.is_extension_supported(IsA(http.HttpRequest),
|
||||
'subnet_allocation').\
|
||||
AndReturn(True)
|
||||
|
@ -757,6 +824,9 @@ class NetworkTests(test.TestCase, NetworkStubMixin):
|
|||
'gateway_ip': gateway_ip,
|
||||
'enable_dhcp': subnet.enable_dhcp}
|
||||
|
||||
api.neutron.is_extension_supported(IsA(http.HttpRequest),
|
||||
'network_availability_zone').\
|
||||
AndReturn(False)
|
||||
api.neutron.is_extension_supported(IsA(http.HttpRequest),
|
||||
'subnet_allocation').\
|
||||
AndReturn(True)
|
||||
|
@ -791,6 +861,9 @@ class NetworkTests(test.TestCase, NetworkStubMixin):
|
|||
network = self.networks.first()
|
||||
subnet = self.subnets.first()
|
||||
|
||||
api.neutron.is_extension_supported(IsA(http.HttpRequest),
|
||||
'network_availability_zone').\
|
||||
AndReturn(False)
|
||||
api.neutron.is_extension_supported(IsA(http.HttpRequest),
|
||||
'subnet_allocation').\
|
||||
AndReturn(True)
|
||||
|
@ -828,7 +901,9 @@ class NetworkTests(test.TestCase, NetworkStubMixin):
|
|||
):
|
||||
network = self.networks.first()
|
||||
subnet = self.subnets.first()
|
||||
|
||||
api.neutron.is_extension_supported(IsA(http.HttpRequest),
|
||||
'network_availability_zone').\
|
||||
AndReturn(False)
|
||||
api.neutron.is_extension_supported(IsA(http.HttpRequest),
|
||||
'subnet_allocation').\
|
||||
AndReturn(True)
|
||||
|
|
|
@ -58,12 +58,31 @@ class CreateNetworkInfoAction(workflows.Action):
|
|||
}),
|
||||
initial=True,
|
||||
required=False)
|
||||
az_hints = forms.MultipleChoiceField(
|
||||
label=_("Availability Zone Hints"),
|
||||
required=False,
|
||||
help_text=_("Availability zones where the DHCP agents may be "
|
||||
"scheduled. Leaving this unset is equivalent to "
|
||||
"selecting all availability zones"))
|
||||
|
||||
def __init__(self, request, *args, **kwargs):
|
||||
super(CreateNetworkInfoAction, self).__init__(request,
|
||||
*args, **kwargs)
|
||||
if not policy.check((("network", "create_network:shared"),), request):
|
||||
self.fields['shared'].widget = forms.HiddenInput()
|
||||
try:
|
||||
if api.neutron.is_extension_supported(request,
|
||||
'network_availability_zone'):
|
||||
zones = api.neutron.list_availability_zones(
|
||||
self.request, 'network', 'available')
|
||||
self.fields['az_hints'].choices = [(zone['name'], zone['name'])
|
||||
for zone in zones]
|
||||
else:
|
||||
del self.fields['az_hints']
|
||||
except Exception:
|
||||
msg = _('Failed to get availability zone list.')
|
||||
messages.warning(request, msg)
|
||||
del self.fields['az_hints']
|
||||
|
||||
class Meta(object):
|
||||
name = _("Network")
|
||||
|
@ -74,7 +93,8 @@ class CreateNetworkInfoAction(workflows.Action):
|
|||
|
||||
class CreateNetworkInfo(workflows.Step):
|
||||
action_class = CreateNetworkInfoAction
|
||||
contributes = ("net_name", "admin_state", "with_subnet", "shared")
|
||||
contributes = ("net_name", "admin_state", "with_subnet", "shared",
|
||||
"az_hints")
|
||||
|
||||
|
||||
class CreateSubnetInfoAction(workflows.Action):
|
||||
|
@ -463,6 +483,8 @@ class CreateNetwork(workflows.Workflow):
|
|||
params = {'name': data['net_name'],
|
||||
'admin_state_up': data['admin_state'],
|
||||
'shared': data['shared']}
|
||||
if 'az_hints' in data and data['az_hints']:
|
||||
params['availability_zone_hints'] = data['az_hints']
|
||||
network = api.neutron.network_create(request, **params)
|
||||
self.context['net_id'] = network.id
|
||||
LOG.debug('Network "%s" was successfully created.',
|
||||
|
|
Loading…
Reference in New Issue