Merge "Add a checkbox to disable SNAT on routers"

This commit is contained in:
Zuul 2017-10-24 16:24:52 +00:00 committed by Gerrit Code Review
commit 5d386afb1a
6 changed files with 104 additions and 10 deletions

View File

@ -1264,8 +1264,10 @@ def router_remove_interface(request, router_id, subnet_id=None, port_id=None):
@profiler.trace
def router_add_gateway(request, router_id, network_id):
def router_add_gateway(request, router_id, network_id, enable_snat=None):
body = {'network_id': network_id}
if enable_snat is not None:
body['enable_snat'] = enable_snat
neutronclient(request).add_gateway_router(router_id, body)
@ -1640,6 +1642,15 @@ FEATURE_MAP = {
'update': 'update_router:ha',
}
},
'ext-gw-mode': {
'extension': 'ext-gw-mode',
'policies': {
'create_router_enable_snat':
'create_router:external_gateway_info:enable_snat',
'update_router_enable_snat':
'update_router:external_gateway_info:enable_snat',
}
},
}

View File

@ -39,6 +39,9 @@ class CreateForm(forms.SelfHandlingForm):
required=False)
external_network = forms.ThemableChoiceField(label=_("External Network"),
required=False)
enable_snat = forms.BooleanField(label=_("Enable SNAT"),
initial=True,
required=False)
mode = forms.ChoiceField(label=_("Router Type"))
ha = forms.ChoiceField(label=_("High Availability Mode"))
az_hints = forms.MultipleChoiceField(
@ -76,6 +79,10 @@ class CreateForm(forms.SelfHandlingForm):
else:
del self.fields['external_network']
self.enable_snat_allowed = self.initial['enable_snat_allowed']
if (not networks or not self.enable_snat_allowed):
del self.fields['enable_snat']
try:
az_supported = api.neutron.is_extension_supported(
self.request, 'router_availability_zone')
@ -116,6 +123,9 @@ class CreateForm(forms.SelfHandlingForm):
if 'external_network' in data and data['external_network']:
params['external_gateway_info'] = {'network_id':
data['external_network']}
if self.ext_gw_mode_supported and self.enable_snat_allowed:
params['external_gateway_info']['enable_snat'] = \
data['enable_snat']
if 'az_hints' in data and data['az_hints']:
params['availability_zone_hints'] = data['az_hints']
if (self.dvr_allowed and data['mode'] != 'server_default'):

View File

@ -145,12 +145,23 @@ class AddInterface(forms.SelfHandlingForm):
class SetGatewayForm(forms.SelfHandlingForm):
network_id = forms.ThemableChoiceField(label=_("External Network"))
enable_snat = forms.BooleanField(label=_("Enable SNAT"),
initial=True,
required=False)
failure_url = 'horizon:project:routers:index'
def __init__(self, request, *args, **kwargs):
super(SetGatewayForm, self).__init__(request, *args, **kwargs)
c = self.populate_network_id_choices(request)
self.fields['network_id'].choices = c
networks = self.populate_network_id_choices(request)
self.fields['network_id'].choices = networks
self.ext_gw_mode = api.neutron.is_extension_supported(
self.request, 'ext-gw-mode')
self.enable_snat_allowed = api.neutron.get_feature_permission(
self.request,
"ext-gw-mode",
"update_router_enable_snat")
if not self.ext_gw_mode or not self.enable_snat_allowed:
del self.fields['enable_snat']
def populate_network_id_choices(self, request):
search_opts = {'router:external': True}
@ -173,9 +184,13 @@ class SetGatewayForm(forms.SelfHandlingForm):
def handle(self, request, data):
try:
enable_snat = None
if 'enable_snat' in data:
enable_snat = data['enable_snat']
api.neutron.router_add_gateway(request,
self.initial['router_id'],
data['network_id'])
data['network_id'],
enable_snat)
msg = _('Gateway interface is added')
messages.success(request, msg)
return True

View File

@ -4,4 +4,7 @@
{% block modal-body-right %}
<h3>{% trans "Description:" %}</h3>
<p>{% trans "Creates a router with specified parameters." %}</p>
{% if enable_snat_allowed %}
<p>{% trans "Enable SNAT will only have an effect if an external network is set." %}</p>
{% endif %}
{% endblock %}

View File

@ -284,6 +284,10 @@ class RouterActionTests(RouterMixin, test.TestCase):
'is_extension_supported')})
def test_router_create_post(self):
router = self.routers.first()
api.neutron.get_feature_permission(IsA(http.HttpRequest),
"ext-gw-mode",
"create_router_enable_snat")\
.AndReturn(True)
api.neutron.get_feature_permission(IsA(http.HttpRequest),
"dvr", "create")\
.AndReturn(False)
@ -315,6 +319,10 @@ class RouterActionTests(RouterMixin, test.TestCase):
'is_extension_supported')})
def test_router_create_post_mode_server_default(self):
router = self.routers.first()
api.neutron.get_feature_permission(IsA(http.HttpRequest),
"ext-gw-mode",
"create_router_enable_snat")\
.AndReturn(True)
api.neutron.get_feature_permission(IsA(http.HttpRequest),
"dvr", "create")\
.AndReturn(True)
@ -348,6 +356,10 @@ class RouterActionTests(RouterMixin, test.TestCase):
'is_extension_supported')})
def test_dvr_ha_router_create_post(self):
router = self.routers.first()
api.neutron.get_feature_permission(IsA(http.HttpRequest),
"ext-gw-mode",
"create_router_enable_snat")\
.AndReturn(True)
api.neutron.get_feature_permission(IsA(http.HttpRequest),
"dvr", "create")\
.MultipleTimes().AndReturn(True)
@ -384,6 +396,10 @@ class RouterActionTests(RouterMixin, test.TestCase):
'list_availability_zones')})
def test_az_router_create_post(self):
router = self.routers.first()
api.neutron.get_feature_permission(IsA(http.HttpRequest),
"ext-gw-mode",
"create_router_enable_snat")\
.AndReturn(True)
api.neutron.get_feature_permission(IsA(http.HttpRequest),
"dvr", "create")\
.MultipleTimes().AndReturn(False)
@ -422,6 +438,10 @@ class RouterActionTests(RouterMixin, test.TestCase):
'is_extension_supported')})
def test_router_create_post_exception_error_case_409(self):
router = self.routers.first()
api.neutron.get_feature_permission(IsA(http.HttpRequest),
"ext-gw-mode",
"create_router_enable_snat")\
.AndReturn(True)
api.neutron.get_feature_permission(IsA(http.HttpRequest),
"dvr", "create")\
.MultipleTimes().AndReturn(False)
@ -454,6 +474,10 @@ class RouterActionTests(RouterMixin, test.TestCase):
'network_list')})
def test_router_create_post_exception_error_case_non_409(self):
router = self.routers.first()
api.neutron.get_feature_permission(IsA(http.HttpRequest),
"ext-gw-mode",
"create_router_enable_snat")\
.AndReturn(True)
api.neutron.get_feature_permission(IsA(http.HttpRequest),
"dvr", "create")\
.MultipleTimes().AndReturn(False)
@ -730,24 +754,34 @@ class RouterActionTests(RouterMixin, test.TestCase):
@test.create_stubs({api.neutron: ('router_get',
'router_add_gateway',
'network_list')})
'network_list',
'is_extension_supported')})
def test_router_add_gateway(self):
router = self.routers.first()
network = self.networks.first()
api.neutron.router_add_gateway(
IsA(http.HttpRequest),
router.id,
network.id).AndReturn(None)
network.id,
True).AndReturn(None)
api.neutron.router_get(
IsA(http.HttpRequest), router.id).AndReturn(router)
search_opts = {'router:external': True}
api.neutron.network_list(
IsA(http.HttpRequest), **search_opts).AndReturn([network])
api.neutron.is_extension_supported(IsA(http.HttpRequest),
'ext-gw-mode')\
.AndReturn(True)
api.neutron.get_feature_permission(IsA(http.HttpRequest),
"ext-gw-mode",
"update_router_enable_snat")\
.AndReturn(True)
self.mox.ReplayAll()
form_data = {'router_id': router.id,
'router_name': router.name,
'network_id': network.id}
'network_id': network.id,
'enable_snat': True}
url = reverse('horizon:%s:routers:setgateway' % self.DASHBOARD,
args=[router.id])
@ -758,24 +792,34 @@ class RouterActionTests(RouterMixin, test.TestCase):
@test.create_stubs({api.neutron: ('router_get',
'router_add_gateway',
'network_list')})
'network_list',
'is_extension_supported')})
def test_router_add_gateway_exception(self):
router = self.routers.first()
network = self.networks.first()
api.neutron.router_add_gateway(
IsA(http.HttpRequest),
router.id,
network.id).AndRaise(self.exceptions.neutron)
network.id,
True).AndRaise(self.exceptions.neutron)
api.neutron.router_get(
IsA(http.HttpRequest), router.id).AndReturn(router)
search_opts = {'router:external': True}
api.neutron.network_list(
IsA(http.HttpRequest), **search_opts).AndReturn([network])
api.neutron.is_extension_supported(IsA(http.HttpRequest),
'ext-gw-mode')\
.AndReturn(True)
api.neutron.get_feature_permission(IsA(http.HttpRequest),
"ext-gw-mode",
"update_router_enable_snat")\
.AndReturn(True)
self.mox.ReplayAll()
form_data = {'router_id': router.id,
'router_name': router.name,
'network_id': network.id}
'network_id': network.id,
'enable_snat': True}
url = reverse('horizon:%s:routers:setgateway' % self.DASHBOARD,
args=[router.id])

View File

@ -180,6 +180,17 @@ class CreateView(forms.ModalFormView):
submit_label = _("Create Router")
submit_url = reverse_lazy("horizon:project:routers:create")
def get_context_data(self, **kwargs):
context = super(CreateView, self).get_context_data(**kwargs)
context['enable_snat_allowed'] = self.initial['enable_snat_allowed']
return context
def get_initial(self):
enable_snat_allowed = api.neutron.get_feature_permission(
self.request, 'ext-gw-mode', 'create_router_enable_snat')
self.initial['enable_snat_allowed'] = enable_snat_allowed
return super(CreateView, self).get_initial()
class UpdateView(forms.ModalFormView):
form_class = project_forms.UpdateForm