Merge "Allow subnet creation from admin networks panel"
This commit is contained in:
commit
39ed1d1a7a
@ -107,7 +107,7 @@ horizon.modals.init_wizard = function () {
|
||||
$form.find('.form-group.has-error').each(function () {
|
||||
var $group = $(this);
|
||||
$group.removeClass('has-error');
|
||||
$group.find('span.help-block.alert').remove();
|
||||
$group.find('span.help-block').remove();
|
||||
});
|
||||
|
||||
// Temporarilly remove "disabled" attribute to get the values serialized
|
||||
@ -153,7 +153,7 @@ horizon.modals.init_wizard = function () {
|
||||
$field = $fieldset.find('[name="' + field + '"]');
|
||||
$field.closest('.form-group').addClass('has-error');
|
||||
$.each(errors, function (index, error) {
|
||||
$field.after(
|
||||
$field.closest(".form-control").after(
|
||||
'<span class="help-block">' +
|
||||
error + '</span>');
|
||||
});
|
||||
|
@ -133,6 +133,20 @@ class CreateNetwork(forms.SelfHandlingForm):
|
||||
initial=False, required=False)
|
||||
external = forms.BooleanField(label=_("External Network"),
|
||||
initial=False, required=False)
|
||||
with_subnet = forms.BooleanField(label=_("Create Subnet"),
|
||||
widget=forms.CheckboxInput(attrs={
|
||||
'class': 'switchable',
|
||||
'data-slug': 'with_subnet',
|
||||
'data-hide-tab': 'create_network__'
|
||||
'createsubnetinfo'
|
||||
'action,'
|
||||
'create_network__'
|
||||
'createsubnetdetail'
|
||||
'action',
|
||||
'data-hide-on-checked': 'false'
|
||||
}),
|
||||
initial=True,
|
||||
required=False)
|
||||
|
||||
@classmethod
|
||||
def _instantiate(cls, request, *args, **kwargs):
|
||||
@ -263,7 +277,6 @@ class CreateNetwork(forms.SelfHandlingForm):
|
||||
network = api.neutron.network_create(request, **params)
|
||||
msg = _('Network %s was successfully created.') % data['name']
|
||||
LOG.debug(msg)
|
||||
messages.success(request, msg)
|
||||
return network
|
||||
except Exception:
|
||||
redirect = reverse('horizon:admin:networks:index')
|
||||
|
@ -1,22 +0,0 @@
|
||||
{% extends "horizon/common/_modal_form.html" %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block form_id %}create_network_form{% endblock %}
|
||||
{% block form_action %}{% url 'horizon:admin:networks:create' %}{% endblock %}
|
||||
|
||||
{% block modal_id %}create_network_modal{% endblock %}
|
||||
{% block modal-header %}{% trans "Create Network" %}{% endblock %}
|
||||
|
||||
{% block modal-body %}
|
||||
<div class="left">
|
||||
<fieldset>
|
||||
{% include "horizon/common/_form_fields.html" %}
|
||||
</fieldset>
|
||||
</div>
|
||||
<div class="right">
|
||||
<h3>{% trans "Description:" %}</h3>
|
||||
<p>{% trans "Create a new network for any project as you need."%}</p>
|
||||
<p>{% trans "Provider specified network can be created. You can specify a physical network type (like Flat, VLAN, GRE, and VXLAN) and its segmentation_id or physical network name for a new virtual network."%}</p>
|
||||
<p>{% trans "In addition, you can create an external network or a shared network by checking the corresponding checkbox."%}</p>
|
||||
</div>
|
||||
{% endblock %}
|
@ -1,7 +0,0 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load i18n %}
|
||||
{% block title %}{% trans "Create Network" %}{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
{% include "admin/networks/_create.html" %}
|
||||
{% endblock %}
|
@ -21,6 +21,7 @@ from django.utils.http import urlunquote
|
||||
from mox3.mox import IsA # noqa
|
||||
|
||||
from openstack_dashboard import api
|
||||
from openstack_dashboard.dashboards.project.networks import tests
|
||||
from openstack_dashboard.test import helpers as test
|
||||
|
||||
INDEX_TEMPLATE = 'horizon/common/_data_table_view.html'
|
||||
@ -381,7 +382,7 @@ class NetworkTests(test.BaseAdminViewTests):
|
||||
url = reverse('horizon:admin:networks:create')
|
||||
res = self.client.get(url)
|
||||
|
||||
self.assertTemplateUsed(res, 'admin/networks/create.html')
|
||||
self.assertTemplateUsed(res, 'horizon/common/_workflow_base.html')
|
||||
|
||||
@test.update_settings(
|
||||
OPENSTACK_NEUTRON_NETWORK={'profile_support': 'cisco'})
|
||||
@ -390,7 +391,8 @@ class NetworkTests(test.BaseAdminViewTests):
|
||||
|
||||
@test.create_stubs({api.neutron: ('network_create',
|
||||
'profile_list',
|
||||
'is_extension_supported',),
|
||||
'is_extension_supported',
|
||||
'subnetpool_list'),
|
||||
api.keystone: ('tenant_list',)})
|
||||
def test_network_create_post(self,
|
||||
test_with_profile=False):
|
||||
@ -405,7 +407,8 @@ class NetworkTests(test.BaseAdminViewTests):
|
||||
'admin_state_up': network.admin_state_up,
|
||||
'router:external': True,
|
||||
'shared': True,
|
||||
'provider:network_type': 'local'}
|
||||
'provider:network_type': 'local',
|
||||
'with_subnet': False}
|
||||
if test_with_profile:
|
||||
net_profiles = self.net_profiles.list()
|
||||
net_profile_id = self.net_profiles.first().id
|
||||
@ -414,8 +417,14 @@ class NetworkTests(test.BaseAdminViewTests):
|
||||
params['net_profile_id'] = net_profile_id
|
||||
api.neutron.is_extension_supported(IsA(http.HttpRequest), 'provider').\
|
||||
MultipleTimes().AndReturn(True)
|
||||
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,
|
||||
@ -432,6 +441,62 @@ class NetworkTests(test.BaseAdminViewTests):
|
||||
self.assertNoFormErrors(res)
|
||||
self.assertRedirectsNoFollow(res, INDEX_URL)
|
||||
|
||||
@test.create_stubs({api.neutron: ('network_create',
|
||||
'subnet_create',
|
||||
'profile_list',
|
||||
'is_extension_supported',
|
||||
'subnetpool_list'),
|
||||
api.keystone: ('tenant_list',)})
|
||||
def test_network_create_post_with_subnet(self,
|
||||
test_with_profile=False):
|
||||
tenants = self.tenants.list()
|
||||
tenant_id = self.tenants.first().id
|
||||
network = self.networks.first()
|
||||
subnet = self.subnets.first()
|
||||
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': True}
|
||||
|
||||
api.keystone.tenant_list(IsA(http.HttpRequest))\
|
||||
.AndReturn([tenants, False])
|
||||
|
||||
if test_with_profile:
|
||||
net_profiles = self.net_profiles.list()
|
||||
net_profile_id = self.net_profiles.first().id
|
||||
api.neutron.profile_list(IsA(http.HttpRequest),
|
||||
'network').AndReturn(net_profiles)
|
||||
params['net_profile_id'] = net_profile_id
|
||||
api.neutron.is_extension_supported(IsA(http.HttpRequest), 'provider').\
|
||||
MultipleTimes().AndReturn(True)
|
||||
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',
|
||||
'with_subnet': True}
|
||||
if test_with_profile:
|
||||
form_data['net_profile_id'] = net_profile_id
|
||||
form_data.update(tests.form_data_subnet(subnet, allocation_pools=[]))
|
||||
url = reverse('horizon:admin:networks:create')
|
||||
res = self.client.post(url, form_data)
|
||||
|
||||
self.assertNoFormErrors(res)
|
||||
self.assertRedirectsNoFollow(res, INDEX_URL)
|
||||
|
||||
@test.update_settings(
|
||||
OPENSTACK_NEUTRON_NETWORK={'profile_support': 'cisco'})
|
||||
def test_network_create_post_with_profile(self):
|
||||
@ -439,7 +504,8 @@ class NetworkTests(test.BaseAdminViewTests):
|
||||
|
||||
@test.create_stubs({api.neutron: ('network_create',
|
||||
'profile_list',
|
||||
'is_extension_supported',),
|
||||
'is_extension_supported',
|
||||
'subnetpool_list'),
|
||||
api.keystone: ('tenant_list',)})
|
||||
def test_network_create_post_network_exception(self,
|
||||
test_with_profile=False):
|
||||
@ -454,7 +520,8 @@ class NetworkTests(test.BaseAdminViewTests):
|
||||
'admin_state_up': network.admin_state_up,
|
||||
'router:external': True,
|
||||
'shared': False,
|
||||
'provider:network_type': 'local'}
|
||||
'provider:network_type': 'local',
|
||||
'with_subnet': False}
|
||||
if test_with_profile:
|
||||
net_profiles = self.net_profiles.list()
|
||||
net_profile_id = self.net_profiles.first().id
|
||||
@ -463,6 +530,11 @@ class NetworkTests(test.BaseAdminViewTests):
|
||||
params['net_profile_id'] = net_profile_id
|
||||
api.neutron.is_extension_supported(IsA(http.HttpRequest), 'provider').\
|
||||
MultipleTimes().AndReturn(True)
|
||||
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).AndRaise(self.exceptions.neutron)
|
||||
self.mox.ReplayAll()
|
||||
@ -593,7 +665,7 @@ class NetworkTests(test.BaseAdminViewTests):
|
||||
url = reverse('horizon:admin:networks:create')
|
||||
res = self.client.get(url)
|
||||
|
||||
self.assertTemplateUsed(res, 'admin/networks/create.html')
|
||||
self.assertTemplateUsed(res, 'horizon/common/_workflow_base.html')
|
||||
self.assertContains(
|
||||
res,
|
||||
'<input type="hidden" name="network_type" id="id_network_type" />',
|
||||
@ -615,7 +687,7 @@ class NetworkTests(test.BaseAdminViewTests):
|
||||
url = reverse('horizon:admin:networks:create')
|
||||
res = self.client.get(url)
|
||||
|
||||
self.assertTemplateUsed(res, 'admin/networks/create.html')
|
||||
self.assertTemplateUsed(res, 'horizon/common/_workflow_base.html')
|
||||
network_type = res.context['form'].fields['network_type']
|
||||
self.assertListEqual(list(network_type.choices), [('local', 'Local'),
|
||||
('flat', 'Flat'),
|
||||
|
@ -19,7 +19,6 @@ from django.core.urlresolvers import reverse_lazy
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from horizon import exceptions
|
||||
from horizon import forms
|
||||
from horizon import tables
|
||||
from horizon import tabs
|
||||
from horizon.utils import memoized
|
||||
@ -39,6 +38,9 @@ from openstack_dashboard.dashboards.admin.networks.subnets \
|
||||
import tables as subnets_tables
|
||||
from openstack_dashboard.dashboards.admin.networks \
|
||||
import tables as networks_tables
|
||||
from openstack_dashboard.dashboards.admin.networks import workflows
|
||||
from openstack_dashboard.dashboards.project.networks import views \
|
||||
as project_view
|
||||
|
||||
|
||||
class IndexView(tables.DataTableView):
|
||||
@ -122,11 +124,8 @@ class IndexView(tables.DataTableView):
|
||||
return filters
|
||||
|
||||
|
||||
class CreateView(forms.ModalFormView):
|
||||
form_class = project_forms.CreateNetwork
|
||||
template_name = 'admin/networks/create.html'
|
||||
success_url = reverse_lazy('horizon:admin:networks:index')
|
||||
page_title = _("Create Network")
|
||||
class CreateView(project_view.CreateView):
|
||||
workflow_class = workflows.CreateNetwork
|
||||
|
||||
|
||||
class UpdateView(user_views.UpdateView):
|
||||
|
87
openstack_dashboard/dashboards/admin/networks/workflows.py
Normal file
87
openstack_dashboard/dashboards/admin/networks/workflows.py
Normal file
@ -0,0 +1,87 @@
|
||||
# Copyright 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
|
||||
# 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.core.urlresolvers import reverse
|
||||
|
||||
from openstack_dashboard.dashboards.admin.networks import forms \
|
||||
as networks_forms
|
||||
from openstack_dashboard.dashboards.project.networks \
|
||||
import workflows as network_workflows
|
||||
|
||||
|
||||
class CreateNetworkInfoAction(network_workflows.CreateNetworkInfoAction):
|
||||
|
||||
def __init__(self, request, context, *args, **kwargs):
|
||||
self.create_network_form = context.get('create_network_form')
|
||||
self.base_fields = self.create_network_form.base_fields
|
||||
|
||||
super(CreateNetworkInfoAction, self).__init__(
|
||||
request, context, *args, **kwargs)
|
||||
self.fields = self.create_network_form.fields
|
||||
|
||||
def clean(self):
|
||||
self.create_network_form.cleaned_data = super(
|
||||
CreateNetworkInfoAction, self).clean()
|
||||
self.create_network_form._changed_data = self.changed_data
|
||||
self.create_network_form._errors = self.errors
|
||||
return self.create_network_form.clean()
|
||||
|
||||
class Meta(object):
|
||||
name = network_workflows.CreateNetworkInfoAction.name
|
||||
help_text = network_workflows.CreateNetworkInfoAction.help_text
|
||||
|
||||
|
||||
class CreateNetworkInfo(network_workflows.CreateNetworkInfo):
|
||||
action_class = CreateNetworkInfoAction
|
||||
contributes = ("net_name", "admin_state", "net_profile_id", "with_subnet")
|
||||
|
||||
def __init__(self, workflow):
|
||||
self.contributes = tuple(workflow.create_network_form.fields.keys())
|
||||
super(CreateNetworkInfo, self).__init__(workflow)
|
||||
|
||||
def prepare_action_context(self, request, context):
|
||||
context = super(CreateNetworkInfo, self).prepare_action_context(
|
||||
request, context)
|
||||
context['create_network_form'] = self.workflow.create_network_form
|
||||
return context
|
||||
|
||||
|
||||
class CreateNetwork(network_workflows.CreateNetwork):
|
||||
default_steps = (CreateNetworkInfo,
|
||||
network_workflows.CreateSubnetInfo,
|
||||
network_workflows.CreateSubnetDetail)
|
||||
|
||||
def __init__(self, request=None, context_seed=None, entry_point=None,
|
||||
*args, **kwargs):
|
||||
self.create_network_form = networks_forms.CreateNetwork(
|
||||
request, *args, **kwargs)
|
||||
super(CreateNetwork, self).__init__(
|
||||
request=request,
|
||||
context_seed=context_seed,
|
||||
entry_point=entry_point,
|
||||
*args, **kwargs)
|
||||
|
||||
def get_success_url(self):
|
||||
return reverse("horizon:admin:networks:index")
|
||||
|
||||
def get_failure_url(self):
|
||||
return reverse("horizon:admin:networks:index")
|
||||
|
||||
def _create_network(self, request, data):
|
||||
network = self.create_network_form.handle(request, data)
|
||||
# Replicate logic from parent CreateNetwork._create_network
|
||||
if network:
|
||||
self.context['net_id'] = network.id
|
||||
self.context['net_name'] = network.name
|
||||
return network
|
Loading…
Reference in New Issue
Block a user