Add HA mode support for Neutron router
HA (high availability) mode support is one of the important topics in Neutron Juno, and this patch adds HA router mode support to Horizon. This commit also changes the default value of enable_distributed_router in the example local_settings.py to False. In Juno release of Neutron, the distributed router and L3 HA mode cannot be enabled at the same time and only L3-agent deployment with L3 Router service plugin support both features. Thus I believe it is reasonable to make both options default to False to avoid unnecessary confusions to operators. Closes-Bug: #1370110 Change-Id: I77b0292b761f08b4580846f6d58443f7df9a1f6b
This commit is contained in:
parent
43bdf4647d
commit
f06e401adf
@ -474,6 +474,7 @@ Default::
|
||||
{
|
||||
'enable_router': True,
|
||||
'enable_distributed_router': False,
|
||||
'enable_ha_router': False,
|
||||
'enable_lb': True,
|
||||
'enable_quotas': False,
|
||||
'enable_firewall': True,
|
||||
@ -512,6 +513,19 @@ when your Neutron plugin (like ML2 plugin) supports DVR feature, DVR
|
||||
feature depends on l3-agent configuration, so deployers should set this
|
||||
option appropriately depending on your deployment.
|
||||
|
||||
``enable_ha_router``:
|
||||
|
||||
.. versionadded:: 2014.2(Juno)
|
||||
|
||||
Default: ``False``
|
||||
|
||||
Enable or disable HA (High Availability) mode in Neutron virtual router
|
||||
in the Router panel. For the HA router mode to be enabled, this option needs
|
||||
to be set to True and your Neutron deployment must support HA router mode.
|
||||
Even when your Neutron plugin (like ML2 plugin) supports HA router mode,
|
||||
the feature depends on l3-agent configuration, so deployers should set this
|
||||
option appropriately depending on your deployment.
|
||||
|
||||
``enable_lb``:
|
||||
|
||||
.. versionadded:: 2013.1(Grizzly)
|
||||
|
@ -943,31 +943,90 @@ def is_port_profiles_supported():
|
||||
return True
|
||||
|
||||
|
||||
def get_dvr_permission(request, operation):
|
||||
"""Check if "distributed" field can be displayed.
|
||||
# FEATURE_MAP is used to define:
|
||||
# - related neutron extension name (key: "extension")
|
||||
# - corresponding dashboard config (key: "config")
|
||||
# - RBAC policies (key: "poclies")
|
||||
# If a key is not contained, the corresponding permission check is skipped.
|
||||
FEATURE_MAP = {
|
||||
'dvr': {
|
||||
'extension': 'dvr',
|
||||
'config': {
|
||||
'name': 'enable_distributed_router',
|
||||
'default': False,
|
||||
},
|
||||
'policies': {
|
||||
'get': 'get_router:distributed',
|
||||
'create': 'create_router:distributed',
|
||||
'update': 'update_router:distributed',
|
||||
}
|
||||
},
|
||||
'l3-ha': {
|
||||
'extension': 'l3-ha',
|
||||
'config': {'name': 'enable_ha_router',
|
||||
'default': False},
|
||||
'policies': {
|
||||
'get': 'get_router:ha',
|
||||
'create': 'create_router:ha',
|
||||
'update': 'update_router:ha',
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def get_feature_permission(request, feature, operation=None):
|
||||
"""Check if a feature-specific field can be displayed.
|
||||
|
||||
This method check a permission for a feature-specific field.
|
||||
Such field is usually provided through Neutron extension.
|
||||
|
||||
:param request: Request Object
|
||||
:param operation: Operation type. The valid value is "get" or "create"
|
||||
:param feature: feature name defined in FEATURE_MAP
|
||||
:param operation (optional): Operation type. The valid value should be
|
||||
defined in FEATURE_MAP[feature]['policies']
|
||||
It must be specified if FEATURE_MAP[feature] has 'policies'.
|
||||
"""
|
||||
network_config = getattr(settings, 'OPENSTACK_NEUTRON_NETWORK', {})
|
||||
if not network_config.get('enable_distributed_router', False):
|
||||
return False
|
||||
feature_info = FEATURE_MAP.get(feature)
|
||||
if not feature_info:
|
||||
# Translators: Only used inside Horizon code and invisible to users
|
||||
raise ValueError(_("The requested feature '%(feature)s' is unknown. "
|
||||
"Please make sure to specify a feature defined "
|
||||
"in FEATURE_MAP."))
|
||||
|
||||
# Check dashboard settings
|
||||
feature_config = feature_info.get('config')
|
||||
if feature_config:
|
||||
if not network_config.get(feature_config['name'],
|
||||
feature_config['default']):
|
||||
return False
|
||||
|
||||
# Check policy
|
||||
feature_policies = feature_info.get('policies')
|
||||
policy_check = getattr(settings, "POLICY_CHECK_FUNCTION", None)
|
||||
allowed_operations = ("get", "create", "update")
|
||||
if operation not in allowed_operations:
|
||||
raise ValueError(_("The 'operation' parameter for get_dvr_permission "
|
||||
"is invalid. It should be one of %s")
|
||||
% ' '.join(allowed_operations))
|
||||
role = (("network", "%s_router:distributed" % operation),)
|
||||
if policy_check:
|
||||
has_permission = policy.check(role, request)
|
||||
else:
|
||||
has_permission = True
|
||||
if not has_permission:
|
||||
return False
|
||||
try:
|
||||
return is_extension_supported(request, 'dvr')
|
||||
except Exception:
|
||||
msg = _('Failed to check Neutron "dvr" extension is not supported')
|
||||
LOG.info(msg)
|
||||
return False
|
||||
if feature_policies and policy_check:
|
||||
policy_name = feature_policies.get(operation)
|
||||
if not policy_name:
|
||||
# Translators: Only used inside Horizon code and invisible to users
|
||||
raise ValueError(_("The 'operation' parameter for "
|
||||
"get_feature_permission '%(feature)s' "
|
||||
"is invalid. It should be one of %(allowed)s")
|
||||
% {'feature': feature,
|
||||
'allowed': ' '.join(feature_policies.keys())})
|
||||
role = (('network', policy_name),)
|
||||
if not policy.check(role, request):
|
||||
return False
|
||||
|
||||
# Check if a required extension is enabled
|
||||
feature_extension = feature_info.get('extension')
|
||||
if feature_extension:
|
||||
try:
|
||||
return is_extension_supported(request, feature_extension)
|
||||
except Exception:
|
||||
msg = (_("Failed to check Neutron '%s' extension is not supported")
|
||||
% feature_extension)
|
||||
LOG.info(msg)
|
||||
return False
|
||||
|
||||
# If all checks are passed, now a given feature is allowed.
|
||||
return True
|
||||
|
@ -148,6 +148,9 @@
|
||||
"get_router:distributed": "rule:admin_only",
|
||||
"create_router:distributed": "rule:admin_only",
|
||||
"update_router:distributed": "rule:admin_only",
|
||||
"get_router:ha": "rule:admin_only",
|
||||
"create_router:ha": "rule:admin_only",
|
||||
"update_router:ha": "rule:admin_only",
|
||||
|
||||
"create_floatingip": "rule:regular_user",
|
||||
"update_floatingip": "rule:admin_or_owner",
|
||||
|
@ -18,6 +18,10 @@
|
||||
<dt>{% trans "Distributed" %}</dt>
|
||||
<dd>{{ router.distributed|yesno|capfirst }}</dd>
|
||||
{% endif %}
|
||||
{% if ha_supported %}
|
||||
<dt>{% trans "High Availability Mode" %}</dt>
|
||||
<dd>{{ router.ha|yesno|capfirst }}</dd>
|
||||
{% endif %}
|
||||
{% if router.external_gateway_info %}
|
||||
<dt>{% trans "External Gateway Information" %}</dt>
|
||||
<dd>{% trans "Connected External Network" %}:
|
||||
|
@ -34,26 +34,38 @@ LOG = logging.getLogger(__name__)
|
||||
class CreateForm(forms.SelfHandlingForm):
|
||||
name = forms.CharField(max_length=255, label=_("Router Name"))
|
||||
mode = forms.ChoiceField(label=_("Router Type"))
|
||||
ha = forms.ChoiceField(label=_("High Availability Mode"))
|
||||
failure_url = 'horizon:project:routers:index'
|
||||
|
||||
def __init__(self, request, *args, **kwargs):
|
||||
super(CreateForm, self).__init__(request, *args, **kwargs)
|
||||
self.dvr_enabled = api.neutron.get_dvr_permission(self.request,
|
||||
"create")
|
||||
if self.dvr_enabled:
|
||||
self.dvr_allowed = api.neutron.get_feature_permission(self.request,
|
||||
"dvr", "create")
|
||||
if self.dvr_allowed:
|
||||
mode_choices = [('server_default', _('Use Server Default')),
|
||||
('centralized', _('Centralized')),
|
||||
('distributed', _('Distributed'))]
|
||||
self.fields['mode'].choices = mode_choices
|
||||
else:
|
||||
self.fields['mode'].widget = forms.HiddenInput()
|
||||
self.fields['mode'].required = False
|
||||
del self.fields['mode']
|
||||
|
||||
self.ha_allowed = api.neutron.get_feature_permission(self.request,
|
||||
"l3-ha", "create")
|
||||
if self.ha_allowed:
|
||||
ha_choices = [('server_default', _('Use Server Default')),
|
||||
('enabled', _('Enable HA mode')),
|
||||
('disabled', _('Disable HA mode'))]
|
||||
self.fields['ha'].choices = ha_choices
|
||||
else:
|
||||
del self.fields['ha']
|
||||
|
||||
def handle(self, request, data):
|
||||
try:
|
||||
params = {'name': data['name']}
|
||||
if (self.dvr_enabled and data['mode'] != 'server_default'):
|
||||
if (self.dvr_allowed and data['mode'] != 'server_default'):
|
||||
params['distributed'] = (data['mode'] == 'distributed')
|
||||
if (self.ha_allowed and data['ha'] != 'server_default'):
|
||||
params['ha'] = (data['ha'] == 'enabled')
|
||||
router = api.neutron.router_create(request, **params)
|
||||
message = _('Router %s was successfully created.') % data['name']
|
||||
messages.success(request, message)
|
||||
@ -77,13 +89,14 @@ class UpdateForm(forms.SelfHandlingForm):
|
||||
router_id = forms.CharField(label=_("ID"),
|
||||
widget=forms.HiddenInput())
|
||||
mode = forms.ChoiceField(label=_("Router Type"))
|
||||
ha = forms.BooleanField(label=_("High Availability Mode"), required=False)
|
||||
|
||||
redirect_url = reverse_lazy('horizon:project:routers:index')
|
||||
|
||||
def __init__(self, request, *args, **kwargs):
|
||||
super(UpdateForm, self).__init__(request, *args, **kwargs)
|
||||
self.dvr_allowed = api.neutron.get_dvr_permission(self.request,
|
||||
"update")
|
||||
self.dvr_allowed = api.neutron.get_feature_permission(self.request,
|
||||
"dvr", "update")
|
||||
if not self.dvr_allowed:
|
||||
del self.fields['mode']
|
||||
elif kwargs.get('initial', {}).get('mode') == 'distributed':
|
||||
@ -98,12 +111,19 @@ class UpdateForm(forms.SelfHandlingForm):
|
||||
('distributed', _('Distributed'))]
|
||||
self.fields['mode'].choices = mode_choices
|
||||
|
||||
self.ha_allowed = api.neutron.get_feature_permission(self.request,
|
||||
"l3-ha", "update")
|
||||
if not self.ha_allowed:
|
||||
del self.fields['ha']
|
||||
|
||||
def handle(self, request, data):
|
||||
try:
|
||||
params = {'admin_state_up': (data['admin_state'] == 'True'),
|
||||
'name': data['name']}
|
||||
if self.dvr_allowed:
|
||||
params['distributed'] = (data['mode'] == 'distributed')
|
||||
if self.ha_allowed:
|
||||
params['ha'] = data['ha']
|
||||
router = api.neutron.router_update(request, data['router_id'],
|
||||
**params)
|
||||
msg = _('Router %s was successfully updated.') % data['name']
|
||||
|
@ -159,6 +159,10 @@ class RoutersTable(tables.DataTable):
|
||||
distributed = tables.Column("distributed",
|
||||
filters=(filters.yesno, filters.capfirst),
|
||||
verbose_name=_("Distributed"))
|
||||
ha = tables.Column("ha",
|
||||
filters=(filters.yesno, filters.capfirst),
|
||||
# Translators: High Availability mode of Neutron router
|
||||
verbose_name=_("HA mode"))
|
||||
ext_net = tables.Column(get_external_network,
|
||||
verbose_name=_("External Network"))
|
||||
|
||||
@ -168,8 +172,10 @@ class RoutersTable(tables.DataTable):
|
||||
data=data,
|
||||
needs_form_wrapper=needs_form_wrapper,
|
||||
**kwargs)
|
||||
if not api.neutron.get_dvr_permission(request, "get"):
|
||||
if not api.neutron.get_feature_permission(request, "dvr", "get"):
|
||||
del self.columns["distributed"]
|
||||
if not api.neutron.get_feature_permission(request, "l3-ha", "get"):
|
||||
del self.columns["ha"]
|
||||
|
||||
def get_object_display(self, obj):
|
||||
return obj.name
|
||||
|
@ -16,6 +16,10 @@
|
||||
<dt>{% trans "Distributed" %}</dt>
|
||||
<dd>{{ router.distributed|yesno|capfirst }}</dd>
|
||||
{% endif %}
|
||||
{% if ha_supported %}
|
||||
<dt>{% trans "High Availability Mode" %}</dt>
|
||||
<dd>{{ router.ha|yesno|capfirst }}</dd>
|
||||
{% endif %}
|
||||
{% if router.external_gateway_info %}
|
||||
<dt>{% trans "External Gateway Information" %}</dt>
|
||||
<dd>{% trans "Connected External Network" %}:
|
||||
|
@ -133,10 +133,14 @@ class RouterActionTests(test.TestCase):
|
||||
DETAIL_PATH = 'horizon:%s:routers:detail' % DASHBOARD
|
||||
|
||||
@test.create_stubs({api.neutron: ('router_create',
|
||||
'get_dvr_permission',)})
|
||||
'get_feature_permission',)})
|
||||
def test_router_create_post(self):
|
||||
router = self.routers.first()
|
||||
api.neutron.get_dvr_permission(IsA(http.HttpRequest), "create")\
|
||||
api.neutron.get_feature_permission(IsA(http.HttpRequest),
|
||||
"dvr", "create")\
|
||||
.AndReturn(False)
|
||||
api.neutron.get_feature_permission(IsA(http.HttpRequest),
|
||||
"l3-ha", "create")\
|
||||
.AndReturn(False)
|
||||
api.neutron.router_create(IsA(http.HttpRequest), name=router.name)\
|
||||
.AndReturn(router)
|
||||
@ -150,17 +154,22 @@ class RouterActionTests(test.TestCase):
|
||||
self.assertRedirectsNoFollow(res, self.INDEX_URL)
|
||||
|
||||
@test.create_stubs({api.neutron: ('router_create',
|
||||
'get_dvr_permission',)})
|
||||
'get_feature_permission',)})
|
||||
def test_router_create_post_mode_server_default(self):
|
||||
router = self.routers.first()
|
||||
api.neutron.get_dvr_permission(IsA(http.HttpRequest), "create")\
|
||||
api.neutron.get_feature_permission(IsA(http.HttpRequest),
|
||||
"dvr", "create")\
|
||||
.AndReturn(True)
|
||||
api.neutron.get_feature_permission(IsA(http.HttpRequest),
|
||||
"l3-ha", "create")\
|
||||
.AndReturn(True)
|
||||
api.neutron.router_create(IsA(http.HttpRequest), name=router.name)\
|
||||
.AndReturn(router)
|
||||
|
||||
self.mox.ReplayAll()
|
||||
form_data = {'name': router.name,
|
||||
'mode': 'server_default'}
|
||||
'mode': 'server_default',
|
||||
'ha': 'server_default'}
|
||||
url = reverse('horizon:%s:routers:create' % self.DASHBOARD)
|
||||
res = self.client.post(url, form_data)
|
||||
|
||||
@ -168,19 +177,25 @@ class RouterActionTests(test.TestCase):
|
||||
self.assertRedirectsNoFollow(res, self.INDEX_URL)
|
||||
|
||||
@test.create_stubs({api.neutron: ('router_create',
|
||||
'get_dvr_permission',)})
|
||||
def test_dvr_router_create_post(self):
|
||||
'get_feature_permission',)})
|
||||
def test_dvr_ha_router_create_post(self):
|
||||
router = self.routers.first()
|
||||
api.neutron.get_dvr_permission(IsA(http.HttpRequest), "create")\
|
||||
api.neutron.get_feature_permission(IsA(http.HttpRequest),
|
||||
"dvr", "create")\
|
||||
.MultipleTimes().AndReturn(True)
|
||||
api.neutron.get_feature_permission(IsA(http.HttpRequest),
|
||||
"l3-ha", "create")\
|
||||
.MultipleTimes().AndReturn(True)
|
||||
param = {'name': router.name,
|
||||
'distributed': True}
|
||||
'distributed': True,
|
||||
'ha': True}
|
||||
api.neutron.router_create(IsA(http.HttpRequest), **param)\
|
||||
.AndReturn(router)
|
||||
|
||||
self.mox.ReplayAll()
|
||||
form_data = {'name': router.name,
|
||||
'mode': 'distributed'}
|
||||
'mode': 'distributed',
|
||||
'ha': 'enabled'}
|
||||
url = reverse('horizon:%s:routers:create' % self.DASHBOARD)
|
||||
res = self.client.post(url, form_data)
|
||||
|
||||
@ -188,11 +203,15 @@ class RouterActionTests(test.TestCase):
|
||||
self.assertRedirectsNoFollow(res, self.INDEX_URL)
|
||||
|
||||
@test.create_stubs({api.neutron: ('router_create',
|
||||
'get_dvr_permission',)})
|
||||
'get_feature_permission',)})
|
||||
def test_router_create_post_exception_error_case_409(self):
|
||||
router = self.routers.first()
|
||||
api.neutron.get_dvr_permission(IsA(http.HttpRequest), "create")\
|
||||
api.neutron.get_feature_permission(IsA(http.HttpRequest),
|
||||
"dvr", "create")\
|
||||
.MultipleTimes().AndReturn(False)
|
||||
api.neutron.get_feature_permission(IsA(http.HttpRequest),
|
||||
"l3-ha", "create")\
|
||||
.AndReturn(False)
|
||||
self.exceptions.neutron.status_code = 409
|
||||
api.neutron.router_create(IsA(http.HttpRequest), name=router.name)\
|
||||
.AndRaise(self.exceptions.neutron)
|
||||
@ -206,10 +225,14 @@ class RouterActionTests(test.TestCase):
|
||||
self.assertRedirectsNoFollow(res, self.INDEX_URL)
|
||||
|
||||
@test.create_stubs({api.neutron: ('router_create',
|
||||
'get_dvr_permission',)})
|
||||
'get_feature_permission',)})
|
||||
def test_router_create_post_exception_error_case_non_409(self):
|
||||
router = self.routers.first()
|
||||
api.neutron.get_dvr_permission(IsA(http.HttpRequest), "create")\
|
||||
api.neutron.get_feature_permission(IsA(http.HttpRequest),
|
||||
"dvr", "create")\
|
||||
.MultipleTimes().AndReturn(False)
|
||||
api.neutron.get_feature_permission(IsA(http.HttpRequest),
|
||||
"l3-ha", "create")\
|
||||
.MultipleTimes().AndReturn(False)
|
||||
self.exceptions.neutron.status_code = 999
|
||||
api.neutron.router_create(IsA(http.HttpRequest), name=router.name)\
|
||||
@ -224,15 +247,20 @@ class RouterActionTests(test.TestCase):
|
||||
self.assertRedirectsNoFollow(res, self.INDEX_URL)
|
||||
|
||||
@test.create_stubs({api.neutron: ('router_get',
|
||||
'get_dvr_permission')})
|
||||
'get_feature_permission')})
|
||||
def _test_router_update_get(self, dvr_enabled=False,
|
||||
current_dvr=False):
|
||||
current_dvr=False,
|
||||
ha_enabled=False):
|
||||
router = [r for r in self.routers.list()
|
||||
if r.distributed == current_dvr][0]
|
||||
api.neutron.router_get(IsA(http.HttpRequest), router.id)\
|
||||
.AndReturn(router)
|
||||
api.neutron.get_dvr_permission(IsA(http.HttpRequest), "update")\
|
||||
api.neutron.get_feature_permission(IsA(http.HttpRequest),
|
||||
"dvr", "update")\
|
||||
.AndReturn(dvr_enabled)
|
||||
api.neutron.get_feature_permission(IsA(http.HttpRequest),
|
||||
"l3-ha", "update")\
|
||||
.AndReturn(ha_enabled)
|
||||
self.mox.ReplayAll()
|
||||
|
||||
url = reverse('horizon:%s:routers:update' % self.DASHBOARD,
|
||||
@ -276,10 +304,14 @@ class RouterActionTests(test.TestCase):
|
||||
|
||||
@test.create_stubs({api.neutron: ('router_get',
|
||||
'router_update',
|
||||
'get_dvr_permission')})
|
||||
def test_router_update_post_dvr_disabled(self):
|
||||
'get_feature_permission')})
|
||||
def test_router_update_post_dvr_ha_disabled(self):
|
||||
router = self.routers.first()
|
||||
api.neutron.get_dvr_permission(IsA(http.HttpRequest), "update")\
|
||||
api.neutron.get_feature_permission(IsA(http.HttpRequest),
|
||||
"dvr", "update")\
|
||||
.AndReturn(False)
|
||||
api.neutron.get_feature_permission(IsA(http.HttpRequest),
|
||||
"l3-ha", "update")\
|
||||
.AndReturn(False)
|
||||
api.neutron.router_update(IsA(http.HttpRequest), router.id,
|
||||
name=router.name,
|
||||
@ -300,15 +332,20 @@ class RouterActionTests(test.TestCase):
|
||||
|
||||
@test.create_stubs({api.neutron: ('router_get',
|
||||
'router_update',
|
||||
'get_dvr_permission')})
|
||||
def test_router_update_post_dvr_enabled(self):
|
||||
'get_feature_permission')})
|
||||
def test_router_update_post_dvr_ha_enabled(self):
|
||||
router = self.routers.first()
|
||||
api.neutron.get_dvr_permission(IsA(http.HttpRequest), "update")\
|
||||
api.neutron.get_feature_permission(IsA(http.HttpRequest),
|
||||
"dvr", "update")\
|
||||
.AndReturn(True)
|
||||
api.neutron.get_feature_permission(IsA(http.HttpRequest),
|
||||
"l3-ha", "update")\
|
||||
.AndReturn(True)
|
||||
api.neutron.router_update(IsA(http.HttpRequest), router.id,
|
||||
name=router.name,
|
||||
admin_state_up=router.admin_state_up,
|
||||
distributed=True)\
|
||||
distributed=True,
|
||||
ha=True)\
|
||||
.AndReturn(router)
|
||||
api.neutron.router_get(IsA(http.HttpRequest), router.id)\
|
||||
.AndReturn(router)
|
||||
@ -317,7 +354,8 @@ class RouterActionTests(test.TestCase):
|
||||
form_data = {'router_id': router.id,
|
||||
'name': router.name,
|
||||
'admin_state': router.admin_state_up,
|
||||
'mode': 'distributed'}
|
||||
'mode': 'distributed',
|
||||
'ha': True}
|
||||
url = reverse('horizon:%s:routers:update' % self.DASHBOARD,
|
||||
args=[router.id])
|
||||
res = self.client.post(url, form_data)
|
||||
|
@ -126,8 +126,10 @@ class DetailView(tabs.TabbedTableView):
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(DetailView, self).get_context_data(**kwargs)
|
||||
context["router"] = self._get_data()
|
||||
context['dvr_supported'] = api.neutron.get_dvr_permission(self.request,
|
||||
"get")
|
||||
context['dvr_supported'] = api.neutron.get_feature_permission(
|
||||
self.request, "dvr", "get")
|
||||
context['ha_supported'] = api.neutron.get_feature_permission(
|
||||
self.request, "l3-ha", "get")
|
||||
return context
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
@ -170,4 +172,6 @@ class UpdateView(forms.ModalFormView):
|
||||
if hasattr(router, 'distributed'):
|
||||
initial['mode'] = ('distributed' if router.distributed
|
||||
else 'centralized')
|
||||
if hasattr(router, 'ha'):
|
||||
initial['ha'] = router.ha
|
||||
return initial
|
||||
|
@ -182,7 +182,8 @@ OPENSTACK_NEUTRON_NETWORK = {
|
||||
'enable_router': True,
|
||||
'enable_quotas': True,
|
||||
'enable_ipv6': True,
|
||||
'enable_distributed_router': True,
|
||||
'enable_distributed_router': False,
|
||||
'enable_ha_router': False,
|
||||
'enable_lb': True,
|
||||
'enable_firewall': True,
|
||||
'enable_vpn': True,
|
||||
|
@ -283,6 +283,11 @@ class NeutronApiTests(test.APITestCase):
|
||||
self.assertFalse(
|
||||
api.neutron.is_extension_supported(self.request, 'doesntexist'))
|
||||
|
||||
# NOTE(amotoki): "dvr" permission tests check most of
|
||||
# get_feature_permission features.
|
||||
# These tests are not specific to "dvr" extension.
|
||||
# Please be careful if you drop "dvr" extension in future.
|
||||
|
||||
@override_settings(OPENSTACK_NEUTRON_NETWORK={'enable_distributed_router':
|
||||
True},
|
||||
POLICY_CHECK_FUNCTION=None)
|
||||
@ -295,10 +300,11 @@ class NeutronApiTests(test.APITestCase):
|
||||
.AndReturn({'extensions': extensions})
|
||||
self.mox.ReplayAll()
|
||||
self.assertEqual(dvr_enabled,
|
||||
api.neutron.get_dvr_permission(self.request, 'get'))
|
||||
api.neutron.get_feature_permission(self.request,
|
||||
'dvr', 'get'))
|
||||
|
||||
def test_get_dvr_permission_dvr_supported(self):
|
||||
self._test_get_dvr_permission_dvr_supported(dvr_enabled=True, )
|
||||
self._test_get_dvr_permission_dvr_supported(dvr_enabled=True)
|
||||
|
||||
def test_get_dvr_permission_dvr_not_supported(self):
|
||||
self._test_get_dvr_permission_dvr_supported(dvr_enabled=False)
|
||||
@ -320,8 +326,8 @@ class NeutronApiTests(test.APITestCase):
|
||||
.AndReturn({'extensions': self.api_extensions.list()})
|
||||
self.mox.ReplayAll()
|
||||
self.assertEqual(policy_check_allowed,
|
||||
api.neutron.get_dvr_permission(self.request,
|
||||
operation))
|
||||
api.neutron.get_feature_permission(self.request,
|
||||
'dvr', operation))
|
||||
|
||||
def test_get_dvr_permission_with_policy_check_allowed(self):
|
||||
self._test_get_dvr_permission_with_policy_check(True, "get")
|
||||
@ -338,11 +344,49 @@ class NeutronApiTests(test.APITestCase):
|
||||
@override_settings(OPENSTACK_NEUTRON_NETWORK={'enable_distributed_router':
|
||||
False})
|
||||
def test_get_dvr_permission_dvr_disabled_by_config(self):
|
||||
self.assertFalse(api.neutron.get_dvr_permission(self.request, 'get'))
|
||||
self.assertFalse(api.neutron.get_feature_permission(self.request,
|
||||
'dvr', 'get'))
|
||||
|
||||
@override_settings(OPENSTACK_NEUTRON_NETWORK={'enable_distributed_router':
|
||||
True})
|
||||
True},
|
||||
POLICY_CHECK_FUNCTION=policy.check)
|
||||
def test_get_dvr_permission_dvr_unsupported_operation(self):
|
||||
self.assertRaises(ValueError,
|
||||
api.neutron.get_dvr_permission,
|
||||
self.request, 'unSupported')
|
||||
api.neutron.get_feature_permission,
|
||||
self.request, 'dvr', 'unSupported')
|
||||
|
||||
@override_settings(OPENSTACK_NEUTRON_NETWORK={})
|
||||
def test_get_dvr_permission_dvr_default_config(self):
|
||||
self.assertFalse(api.neutron.get_feature_permission(self.request,
|
||||
'dvr', 'get'))
|
||||
|
||||
@override_settings(OPENSTACK_NEUTRON_NETWORK={})
|
||||
def test_get_dvr_permission_router_ha_default_config(self):
|
||||
self.assertFalse(api.neutron.get_feature_permission(self.request,
|
||||
'l3-ha', 'get'))
|
||||
|
||||
# NOTE(amotoki): Most of get_feature_permission are checked by "dvr" check
|
||||
# above. l3-ha check only checks l3-ha specific code.
|
||||
|
||||
@override_settings(OPENSTACK_NEUTRON_NETWORK={'enable_ha_router': True},
|
||||
POLICY_CHECK_FUNCTION=policy.check)
|
||||
def _test_get_router_ha_permission_with_policy_check(self, ha_enabled):
|
||||
self.mox.StubOutWithMock(policy, 'check')
|
||||
role = (("network", "create_router:ha"),)
|
||||
policy.check(role, self.request).AndReturn(True)
|
||||
neutronclient = self.stub_neutronclient()
|
||||
if ha_enabled:
|
||||
extensions = self.api_extensions.list()
|
||||
else:
|
||||
extensions = {}
|
||||
neutronclient.list_extensions().AndReturn({'extensions': extensions})
|
||||
self.mox.ReplayAll()
|
||||
self.assertEqual(ha_enabled,
|
||||
api.neutron.get_feature_permission(self.request,
|
||||
'l3-ha', 'create'))
|
||||
|
||||
def test_get_router_ha_permission_with_l3_ha_extension(self):
|
||||
self._test_get_router_ha_permission_with_policy_check(True)
|
||||
|
||||
def test_get_router_ha_permission_without_l3_ha_extension(self):
|
||||
self._test_get_router_ha_permission_with_policy_check(False)
|
||||
|
@ -642,10 +642,14 @@ def data(TEST):
|
||||
"alias": "dvr",
|
||||
"description":
|
||||
"Enables configuration of Distributed Virtual Routers."}
|
||||
extension_5 = {"name": "HA Router extension",
|
||||
"alias": "l3-ha",
|
||||
"description": "Add HA capability to routers."}
|
||||
TEST.api_extensions.add(extension_1)
|
||||
TEST.api_extensions.add(extension_2)
|
||||
TEST.api_extensions.add(extension_3)
|
||||
TEST.api_extensions.add(extension_4)
|
||||
TEST.api_extensions.add(extension_5)
|
||||
|
||||
# 1st agent.
|
||||
agent_dict = {"binary": "neutron-openvswitch-agent",
|
||||
|
Loading…
Reference in New Issue
Block a user