Akihiro Motoki 1340904d47 quota: Use network quota field names consistently
Previously neutron quota names and nova-network quota names are
mixly used and this makes the readability terrible.
We no longer supports nova-network, so it looks simple to use
neutron quota names consistently.

Neutron quota names use singular form and it is different
from nova and cinder (which adopt plural form as quota names).
Although it might be confusing, the mixed usage is much worse.
Some wrapper layer may address singular vs plural form issue,
but it can be solved later. Let's use neutron quota names
directly now to simplify the code.

blueprint make-quotas-great-again
Change-Id: Ie31414ada34cbdbd046063b512d3cef0a6e68acf
2017-12-13 20:27:02 +09:00

243 lines
7.8 KiB
Python

# Copyright 2012 Nebula, Inc.
#
# 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.conf import settings
from django.core.urlresolvers import reverse
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import ungettext_lazy
import six
from horizon import tables
from openstack_dashboard import api
from openstack_dashboard import policy
from openstack_dashboard.usage import quotas
from openstack_dashboard.utils import filters
# TODO(amotoki): [drop-nova-network] Add neutron policy support
class DeleteGroup(policy.PolicyTargetMixin, tables.DeleteAction):
@staticmethod
def action_present(count):
return ungettext_lazy(
u"Delete Security Group",
u"Delete Security Groups",
count
)
@staticmethod
def action_past(count):
return ungettext_lazy(
u"Deleted Security Group",
u"Deleted Security Groups",
count
)
def allowed(self, request, security_group=None):
if not security_group:
return True
return security_group.name != 'default'
def delete(self, request, obj_id):
api.neutron.security_group_delete(request, obj_id)
class CreateGroup(tables.LinkAction):
name = "create"
verbose_name = _("Create Security Group")
url = "horizon:project:security_groups:create"
classes = ("ajax-modal",)
icon = "plus"
def allowed(self, request, security_group=None):
usages = quotas.tenant_quota_usages(request,
targets=('security_group', ))
if usages['security_group'].get('available', 1) <= 0:
if "disabled" not in self.classes:
self.classes = [c for c in self.classes] + ["disabled"]
self.verbose_name = _("Create Security Group (Quota exceeded)")
else:
self.verbose_name = _("Create Security Group")
self.classes = [c for c in self.classes if c != "disabled"]
return True
class EditGroup(policy.PolicyTargetMixin, tables.LinkAction):
name = "edit"
verbose_name = _("Edit Security Group")
url = "horizon:project:security_groups:update"
classes = ("ajax-modal",)
icon = "pencil"
def allowed(self, request, security_group=None):
if not security_group:
return True
return security_group.name != 'default'
class ManageRules(policy.PolicyTargetMixin, tables.LinkAction):
name = "manage_rules"
verbose_name = _("Manage Rules")
url = "horizon:project:security_groups:detail"
icon = "pencil"
class SecurityGroupsFilterAction(tables.FilterAction):
def filter(self, table, security_groups, filter_string):
"""Naive case-insensitive search."""
query = filter_string.lower()
return [security_group for security_group in security_groups
if query in security_group.name.lower()]
class SecurityGroupsTable(tables.DataTable):
name = tables.Column("name", verbose_name=_("Name"))
security_group_id = tables.Column("id",
verbose_name=_("Security Group ID"))
description = tables.Column("description", verbose_name=_("Description"))
def sanitize_id(self, obj_id):
return filters.get_int_or_uuid(obj_id)
class Meta(object):
name = "security_groups"
verbose_name = _("Security Groups")
table_actions = (CreateGroup, DeleteGroup, SecurityGroupsFilterAction)
row_actions = (ManageRules, EditGroup, DeleteGroup)
class CreateRule(tables.LinkAction):
name = "add_rule"
verbose_name = _("Add Rule")
url = "horizon:project:security_groups:add_rule"
classes = ("ajax-modal",)
icon = "plus"
def get_link_url(self):
return reverse(self.url, args=[self.table.kwargs['security_group_id']])
class DeleteRule(tables.DeleteAction):
@staticmethod
def action_present(count):
return ungettext_lazy(
u"Delete Rule",
u"Delete Rules",
count
)
@staticmethod
def action_past(count):
return ungettext_lazy(
u"Deleted Rule",
u"Deleted Rules",
count
)
def delete(self, request, obj_id):
api.neutron.security_group_rule_delete(request, obj_id)
def get_success_url(self, request):
sg_id = self.table.kwargs['security_group_id']
return reverse("horizon:project:security_groups:detail", args=[sg_id])
def get_remote_ip_prefix(rule):
if 'cidr' in rule.ip_range:
if rule.ip_range['cidr'] is None:
range = '::/0' if rule.ethertype == 'IPv6' else '0.0.0.0/0'
else:
range = rule.ip_range['cidr']
return range
else:
return None
def get_remote_security_group(rule):
return rule.group.get('name')
def get_port_range(rule):
# There is no case where from_port is None and to_port has a value,
# so it is enough to check only from_port.
if rule.from_port is None:
return _('Any')
ip_proto = rule.ip_protocol
if rule.from_port == rule.to_port:
return check_rule_template(rule.from_port, ip_proto)
else:
return (u"%(from)s - %(to)s" %
{'from': check_rule_template(rule.from_port, ip_proto),
'to': check_rule_template(rule.to_port, ip_proto)})
def filter_direction(direction):
if direction is None or direction.lower() == 'ingress':
return _('Ingress')
else:
return _('Egress')
def filter_protocol(protocol):
if protocol is None:
return _('Any')
return six.text_type.upper(protocol)
def check_rule_template(port, ip_proto):
rules_dict = getattr(settings, 'SECURITY_GROUP_RULES', {})
if not rules_dict:
return port
templ_rule = [rule for rule in rules_dict.values()
if (str(port) == rule['from_port']
and str(port) == rule['to_port']
and ip_proto == rule['ip_protocol'])]
if templ_rule:
return u"%(from_port)s (%(name)s)" % templ_rule[0]
return port
class RulesTable(tables.DataTable):
direction = tables.Column("direction",
verbose_name=_("Direction"),
filters=(filter_direction,))
ethertype = tables.Column("ethertype",
verbose_name=_("Ether Type"))
protocol = tables.Column("ip_protocol",
verbose_name=_("IP Protocol"),
filters=(filter_protocol,))
port_range = tables.Column(get_port_range,
verbose_name=_("Port Range"))
remote_ip_prefix = tables.Column(get_remote_ip_prefix,
verbose_name=_("Remote IP Prefix"))
remote_security_group = tables.Column(get_remote_security_group,
verbose_name=_("Remote Security"
" Group"))
def sanitize_id(self, obj_id):
return filters.get_int_or_uuid(obj_id)
def get_object_display(self, rule):
return six.text_type(rule)
class Meta(object):
name = "rules"
verbose_name = _("Security Group Rules")
table_actions = (CreateRule, DeleteRule)
row_actions = (DeleteRule,)