Add mixin to replace replicated get_policy_target

Fix adds a mixin to replace the replicated get_policy_target
function. Duplicated code is removed from many classes and mixin is
inherited.

project_id, user_id and domain_id are now default in the generated
policy_target dict but are set to None if the data doesn't support it,
this is to provide the most flexibility for operators writing policy.json
as discussed in the bug report.

policy_target_attrs attribute added by the mixin is overwrittable by
sub-classes of the mixin to override the defaults for custom policy_target
information.

Change-Id: I26759f145b8756bd1eef585c8107160277061523
Closes-Bug: 1317238
This commit is contained in:
Sam Betts 2014-08-19 10:27:47 +01:00 committed by Akihiro Motoki
parent 4fa1bbb15e
commit 107cf8b328
19 changed files with 147 additions and 507 deletions

View File

@ -22,13 +22,14 @@ from horizon.utils import filters
from openstack_dashboard import api
from openstack_dashboard.dashboards.project.instances \
import tables as project_tables
from openstack_dashboard import policy
class AdminEditInstance(project_tables.EditInstance):
url = "horizon:admin:instances:update"
class MigrateInstance(tables.BatchAction):
class MigrateInstance(policy.PolicyTargetMixin, tables.BatchAction):
name = "migrate"
action_present = _("Migrate")
action_past = _("Scheduled migration (pending confirmation) of")
@ -37,12 +38,6 @@ class MigrateInstance(tables.BatchAction):
classes = ("btn-migrate", "btn-danger")
policy_rules = (("compute", "compute_extension:admin_actions:migrate"),)
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum, 'tenant_id', None)
return {"project_id": project_id}
def allowed(self, request, instance):
return ((instance.status in project_tables.ACTIVE_STATES
or instance.status == 'SHUTOFF')
@ -52,7 +47,8 @@ class MigrateInstance(tables.BatchAction):
api.nova.server_migrate(request, obj_id)
class LiveMigrateInstance(tables.LinkAction):
class LiveMigrateInstance(policy.PolicyTargetMixin,
tables.LinkAction):
name = "live_migrate"
verbose_name = _("Live Migrate Instance")
url = "horizon:admin:instances:live_migrate"
@ -60,12 +56,6 @@ class LiveMigrateInstance(tables.LinkAction):
policy_rules = (
("compute", "compute_extension:admin_actions:migrateLive"),)
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum, 'tenant_id', None)
return {"project_id": project_id}
def allowed(self, request, instance):
return ((instance.status in project_tables.ACTIVE_STATES)
and not project_tables.is_deleting(instance))

View File

@ -24,12 +24,12 @@ from horizon import tables
from openstack_dashboard import api
from openstack_dashboard.dashboards.project.networks.ports import \
tables as project_tables
from openstack_dashboard import policy
LOG = logging.getLogger(__name__)
class DeletePort(tables.DeleteAction):
class DeletePort(policy.PolicyTargetMixin, tables.DeleteAction):
@staticmethod
def action_present(count):
return ungettext_lazy(
@ -48,12 +48,6 @@ class DeletePort(tables.DeleteAction):
policy_rules = (("network", "delete_port"),)
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum, 'tenant_id', None)
return {"project_id": project_id}
def delete(self, request, obj_id):
try:
api.neutron.port_delete(request, obj_id)
@ -79,7 +73,7 @@ class CreatePort(tables.LinkAction):
return reverse(self.url, args=(network_id,))
class UpdatePort(tables.LinkAction):
class UpdatePort(policy.PolicyTargetMixin, tables.LinkAction):
name = "update"
verbose_name = _("Edit Port")
url = "horizon:admin:networks:editport"
@ -87,12 +81,6 @@ class UpdatePort(tables.LinkAction):
icon = "pencil"
policy_rules = (("network", "update_port"),)
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum, 'tenant_id', None)
return {"project_id": project_id}
def get_link_url(self, port):
network_id = self.table.kwargs['network_id']
return reverse(self.url, args=(network_id, port.id))

View File

@ -23,12 +23,13 @@ from horizon import tables
from horizon.utils import memoized
from openstack_dashboard import api
from openstack_dashboard import policy
LOG = logging.getLogger(__name__)
class DeleteSubnet(tables.DeleteAction):
class DeleteSubnet(policy.PolicyTargetMixin, tables.DeleteAction):
@staticmethod
def action_present(count):
return ungettext_lazy(
@ -46,12 +47,7 @@ class DeleteSubnet(tables.DeleteAction):
)
policy_rules = (("network", "delete_subnet"),)
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum, 'tenant_id', None)
return {"network:project_id": project_id}
policy_target_attrs = (("network:project_id", "tenant_id"),)
def delete(self, request, obj_id):
try:
@ -65,39 +61,32 @@ class DeleteSubnet(tables.DeleteAction):
exceptions.handle(request, msg, redirect=redirect)
class CreateSubnet(tables.LinkAction):
class CreateSubnet(policy.PolicyTargetMixin, tables.LinkAction):
name = "create"
verbose_name = _("Create Subnet")
url = "horizon:admin:networks:addsubnet"
classes = ("ajax-modal",)
icon = "plus"
policy_rules = (("network", "create_subnet"),)
policy_target_attrs = (("network:project_id", "tenant_id"),)
def get_policy_target(self, request, datum=None):
project_id = None
network = self.table._get_network()
if network:
project_id = getattr(network, 'tenant_id', None)
return {"network:project_id": project_id}
return super(CreateSubnet, self)\
.get_policy_target(request, self.table._get_network())
def get_link_url(self, datum=None):
network_id = self.table.kwargs['network_id']
return reverse(self.url, args=(network_id,))
class UpdateSubnet(tables.LinkAction):
class UpdateSubnet(policy.PolicyTargetMixin, tables.LinkAction):
name = "update"
verbose_name = _("Edit Subnet")
url = "horizon:admin:networks:editsubnet"
classes = ("ajax-modal",)
icon = "pencil"
policy_rules = (("network", "update_subnet"),)
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum, 'tenant_id', None)
return {"network:project_id": project_id}
policy_target_attrs = (("network:project_id", "tenant_id"),)
def get_link_url(self, subnet):
network_id = self.table.kwargs['network_id']

View File

@ -25,12 +25,12 @@ from horizon import tables
from openstack_dashboard import api
from openstack_dashboard.dashboards.project.networks \
import tables as project_tables
from openstack_dashboard import policy
LOG = logging.getLogger(__name__)
class DeleteNetwork(tables.DeleteAction):
class DeleteNetwork(policy.PolicyTargetMixin, tables.DeleteAction):
@staticmethod
def action_present(count):
return ungettext_lazy(
@ -49,12 +49,6 @@ class DeleteNetwork(tables.DeleteAction):
policy_rules = (("network", "delete_network"),)
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum, 'tenant_id', None)
return {"project_id": project_id}
def delete(self, request, obj_id):
try:
api.neutron.network_delete(request, obj_id)
@ -74,7 +68,7 @@ class CreateNetwork(tables.LinkAction):
policy_rules = (("network", "create_network"),)
class EditNetwork(tables.LinkAction):
class EditNetwork(policy.PolicyTargetMixin, tables.LinkAction):
name = "update"
verbose_name = _("Edit Network")
url = "horizon:admin:networks:update"
@ -82,12 +76,6 @@ class EditNetwork(tables.LinkAction):
icon = "pencil"
policy_rules = (("network", "update_network"),)
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum, 'tenant_id', None)
return {"project_id": project_id}
# def _get_subnets(network):
# cidrs = [subnet.get('cidr') for subnet in network.subnets]

View File

@ -23,12 +23,6 @@ class DeleteRouter(r_tables.DeleteRouter):
redirect_url = "horizon:admin:routers:index"
policy_rules = (("network", "delete_router"),)
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum, 'tenant_id', None)
return {"project_id": project_id}
def delete(self, request, obj_id):
search_opts = {'device_owner': 'network:router_interface',
'device_id': obj_id}

View File

@ -18,6 +18,7 @@ from horizon import messages
from horizon import tables
from openstack_dashboard import api
from openstack_dashboard import policy
ENABLE = 0
@ -39,7 +40,7 @@ class CreateUserLink(tables.LinkAction):
return api.keystone.keystone_can_edit_user()
class EditUserLink(tables.LinkAction):
class EditUserLink(policy.PolicyTargetMixin, tables.LinkAction):
name = "edit"
verbose_name = _("Edit")
url = "horizon:identity:users:update"
@ -47,15 +48,13 @@ class EditUserLink(tables.LinkAction):
icon = "pencil"
policy_rules = (("identity", "identity:update_user"),
("identity", "identity:list_projects"),)
def get_policy_target(self, request, user):
return {"user_id": user.id}
policy_target_attrs = (("user_id", "id"),)
def allowed(self, request, user):
return api.keystone.keystone_can_edit_user()
class ToggleEnabled(tables.BatchAction):
class ToggleEnabled(policy.PolicyTargetMixin, tables.BatchAction):
name = "toggle"
@staticmethod
@ -89,11 +88,7 @@ class ToggleEnabled(tables.BatchAction):
)
classes = ("btn-toggle",)
policy_rules = (("identity", "identity:update_user"),)
def get_policy_target(self, request, user=None):
if user:
return {"user_id": user.id}
return {}
policy_target_attrs = (("user_id", "id"),)
def allowed(self, request, user=None):
if not api.keystone.keystone_can_edit_user():

View File

@ -20,6 +20,7 @@ from django.utils.translation import ungettext_lazy
from horizon import tables
from openstack_dashboard import api
from openstack_dashboard import policy
from openstack_dashboard.utils import filters
@ -27,7 +28,7 @@ POLICY_CHECK = getattr(settings, "POLICY_CHECK_FUNCTION",
lambda policy, request, target: True)
class DeleteGroup(tables.DeleteAction):
class DeleteGroup(policy.PolicyTargetMixin, tables.DeleteAction):
@staticmethod
def action_present(count):
@ -45,12 +46,6 @@ class DeleteGroup(tables.DeleteAction):
count
)
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum, 'tenant_id', None)
return {"project_id": project_id}
def allowed(self, request, security_group=None):
policy_target = self.get_policy_target(request, security_group)
if api.base.is_service_enabled(request, "network"):
@ -85,19 +80,13 @@ class CreateGroup(tables.LinkAction):
return POLICY_CHECK(policy, request, target={})
class EditGroup(tables.LinkAction):
class EditGroup(policy.PolicyTargetMixin, tables.LinkAction):
name = "edit"
verbose_name = _("Edit Security Group")
url = "horizon:project:access_and_security:security_groups:update"
classes = ("ajax-modal",)
icon = "pencil"
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum, 'tenant_id', None)
return {"project_id": project_id}
def allowed(self, request, security_group=None):
policy_target = self.get_policy_target(request, security_group)
if api.base.is_service_enabled(request, "network"):
@ -113,18 +102,12 @@ class EditGroup(tables.LinkAction):
return security_group.name != 'default'
class ManageRules(tables.LinkAction):
class ManageRules(policy.PolicyTargetMixin, tables.LinkAction):
name = "manage_rules"
verbose_name = _("Manage Rules")
url = "horizon:project:access_and_security:security_groups:detail"
icon = "pencil"
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum, 'tenant_id', None)
return {"project_id": project_id}
def allowed(self, request, security_group=None):
policy_target = self.get_policy_target(request, security_group)
if api.base.is_service_enabled(request, "network"):

View File

@ -19,6 +19,7 @@ from django.template import defaultfilters as filters
from django.utils.translation import ugettext_lazy as _
from horizon import tables
from openstack_dashboard import policy
class AddRuleLink(tables.LinkAction):
@ -47,7 +48,7 @@ class AddFirewallLink(tables.LinkAction):
policy_rules = (("network", "create_firewall"),)
class DeleteRuleLink(tables.DeleteAction):
class DeleteRuleLink(policy.PolicyTargetMixin, tables.DeleteAction):
name = "deleterule"
action_present = _("Delete")
action_past = _("Scheduled deletion of %(data_type)s")
@ -55,14 +56,8 @@ class DeleteRuleLink(tables.DeleteAction):
data_type_plural = _("Rules")
policy_rules = (("network", "delete_firewall_rule"),)
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum, 'tenant_id', None)
return {"project_id": project_id}
class DeletePolicyLink(tables.DeleteAction):
class DeletePolicyLink(policy.PolicyTargetMixin, tables.DeleteAction):
name = "deletepolicy"
action_present = _("Delete")
action_past = _("Scheduled deletion of %(data_type)s")
@ -70,14 +65,9 @@ class DeletePolicyLink(tables.DeleteAction):
data_type_plural = _("Policies")
policy_rules = (("network", "delete_firewall_policy"),)
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum, 'tenant_id', None)
return {"project_id": project_id}
class DeleteFirewallLink(tables.DeleteAction):
class DeleteFirewallLink(policy.PolicyTargetMixin,
tables.DeleteAction):
name = "deletefirewall"
action_present = _("Delete")
action_past = _("Scheduled deletion of %(data_type)s")
@ -85,99 +75,65 @@ class DeleteFirewallLink(tables.DeleteAction):
data_type_plural = _("Firewalls")
policy_rules = (("network", "delete_firewall"),)
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum, 'tenant_id', None)
return {"project_id": project_id}
class UpdateRuleLink(tables.LinkAction):
class UpdateRuleLink(policy.PolicyTargetMixin, tables.LinkAction):
name = "updaterule"
verbose_name = _("Edit Rule")
classes = ("ajax-modal", "btn-update",)
policy_rules = (("network", "update_firewall_rule"),)
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum, 'tenant_id', None)
return {"project_id": project_id}
def get_link_url(self, rule):
base_url = reverse("horizon:project:firewalls:updaterule",
kwargs={'rule_id': rule.id})
return base_url
class UpdatePolicyLink(tables.LinkAction):
class UpdatePolicyLink(policy.PolicyTargetMixin, tables.LinkAction):
name = "updatepolicy"
verbose_name = _("Edit Policy")
classes = ("ajax-modal", "btn-update",)
policy_rules = (("network", "update_firewall_policy"),)
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum, 'tenant_id', None)
return {"project_id": project_id}
def get_link_url(self, policy):
base_url = reverse("horizon:project:firewalls:updatepolicy",
kwargs={'policy_id': policy.id})
return base_url
class UpdateFirewallLink(tables.LinkAction):
class UpdateFirewallLink(policy.PolicyTargetMixin, tables.LinkAction):
name = "updatefirewall"
verbose_name = _("Edit Firewall")
classes = ("ajax-modal", "btn-update",)
policy_rules = (("network", "update_firewall"),)
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum, 'tenant_id', None)
return {"project_id": project_id}
def get_link_url(self, firewall):
base_url = reverse("horizon:project:firewalls:updatefirewall",
kwargs={'firewall_id': firewall.id})
return base_url
class InsertRuleToPolicyLink(tables.LinkAction):
class InsertRuleToPolicyLink(policy.PolicyTargetMixin,
tables.LinkAction):
name = "insertrule"
verbose_name = _("Insert Rule")
classes = ("ajax-modal", "btn-update",)
policy_rules = (("network", "get_firewall_policy"),
("network", "insert_rule"),)
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum, 'tenant_id', None)
return {"project_id": project_id}
def get_link_url(self, policy):
base_url = reverse("horizon:project:firewalls:insertrule",
kwargs={'policy_id': policy.id})
return base_url
class RemoveRuleFromPolicyLink(tables.LinkAction):
class RemoveRuleFromPolicyLink(policy.PolicyTargetMixin,
tables.LinkAction):
name = "removerule"
verbose_name = _("Remove Rule")
classes = ("ajax-modal", "btn-danger",)
policy_rules = (("network", "get_firewall_policy"),
("network", "remove_rule"),)
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum, 'tenant_id', None)
return {"project_id": project_id}
def get_link_url(self, policy):
base_url = reverse("horizon:project:firewalls:removerule",
kwargs={'policy_id': policy.id})

View File

@ -43,6 +43,7 @@ from openstack_dashboard.dashboards.project.instances.workflows \
import resize_instance
from openstack_dashboard.dashboards.project.instances.workflows \
import update_instance
from openstack_dashboard import policy
LOG = logging.getLogger(__name__)
@ -77,7 +78,7 @@ def is_deleting(instance):
return task_state.lower() == "deleting"
class TerminateInstance(tables.BatchAction):
class TerminateInstance(policy.PolicyTargetMixin, tables.BatchAction):
name = "terminate"
classes = ("btn-danger",)
icon = "off"
@ -99,12 +100,6 @@ class TerminateInstance(tables.BatchAction):
count
)
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum, 'tenant_id', None)
return {"project_id": project_id}
def allowed(self, request, instance=None):
"""Allow terminate action if instance not currently being deleted."""
return not is_deleting(instance)
@ -113,7 +108,7 @@ class TerminateInstance(tables.BatchAction):
api.nova.server_delete(request, obj_id)
class RebootInstance(tables.BatchAction):
class RebootInstance(policy.PolicyTargetMixin, tables.BatchAction):
name = "reboot"
classes = ('btn-danger', 'btn-reboot')
policy_rules = (("compute", "compute:reboot"),)
@ -134,12 +129,6 @@ class RebootInstance(tables.BatchAction):
count
)
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum, 'tenant_id', None)
return {"project_id": project_id}
def allowed(self, request, instance=None):
if instance is not None:
return ((instance.status in ACTIVE_STATES
@ -353,7 +342,7 @@ class LaunchLink(tables.LinkAction):
return HttpResponse(self.render())
class EditInstance(tables.LinkAction):
class EditInstance(policy.PolicyTargetMixin, tables.LinkAction):
name = "edit"
verbose_name = _("Edit Instance")
url = "horizon:project:instances:update"
@ -361,12 +350,6 @@ class EditInstance(tables.LinkAction):
icon = "pencil"
policy_rules = (("compute", "compute:update"),)
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum, 'tenant_id', None)
return {"project_id": project_id}
def get_link_url(self, project):
return self._get_link_url(project, 'instance_info')
@ -395,7 +378,7 @@ class EditInstanceSecurityGroups(EditInstance):
request.user.tenant_id == instance.tenant_id)
class CreateSnapshot(tables.LinkAction):
class CreateSnapshot(policy.PolicyTargetMixin, tables.LinkAction):
name = "snapshot"
verbose_name = _("Create Snapshot")
url = "horizon:project:images:snapshots:create"
@ -403,30 +386,18 @@ class CreateSnapshot(tables.LinkAction):
icon = "camera"
policy_rules = (("compute", "compute:snapshot"),)
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum, 'tenant_id', None)
return {"project_id": project_id}
def allowed(self, request, instance=None):
return instance.status in SNAPSHOT_READY_STATES \
and not is_deleting(instance)
class ConsoleLink(tables.LinkAction):
class ConsoleLink(policy.PolicyTargetMixin, tables.LinkAction):
name = "console"
verbose_name = _("Console")
url = "horizon:project:instances:detail"
classes = ("btn-console",)
policy_rules = (("compute", "compute_extension:consoles"),)
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum, 'tenant_id', None)
return {"project_id": project_id}
def allowed(self, request, instance=None):
# We check if ConsoleLink is allowed only if settings.CONSOLE_TYPE is
# not set at all, or if it's set to any value other than None or False.
@ -440,19 +411,13 @@ class ConsoleLink(tables.LinkAction):
return "?".join([base_url, tab_query_string])
class LogLink(tables.LinkAction):
class LogLink(policy.PolicyTargetMixin, tables.LinkAction):
name = "log"
verbose_name = _("View Log")
url = "horizon:project:instances:detail"
classes = ("btn-log",)
policy_rules = (("compute", "compute_extension:console_output"),)
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum, 'tenant_id', None)
return {"project_id": project_id}
def allowed(self, request, instance=None):
return instance.status in ACTIVE_STATES and not is_deleting(instance)
@ -463,19 +428,13 @@ class LogLink(tables.LinkAction):
return "?".join([base_url, tab_query_string])
class ResizeLink(tables.LinkAction):
class ResizeLink(policy.PolicyTargetMixin, tables.LinkAction):
name = "resize"
verbose_name = _("Resize Instance")
url = "horizon:project:instances:resize"
classes = ("ajax-modal", "btn-resize")
policy_rules = (("compute", "compute:resize"),)
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum, 'tenant_id', None)
return {"project_id": project_id}
def get_link_url(self, project):
return self._get_link_url(project, 'flavor_choice')
@ -493,18 +452,12 @@ class ResizeLink(tables.LinkAction):
and not is_deleting(instance))
class ConfirmResize(tables.Action):
class ConfirmResize(policy.PolicyTargetMixin, tables.Action):
name = "confirm"
verbose_name = _("Confirm Resize/Migrate")
classes = ("btn-confirm", "btn-action-required")
policy_rules = (("compute", "compute:confirm_resize"),)
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum, 'tenant_id', None)
return {"project_id": project_id}
def allowed(self, request, instance):
return instance.status == 'VERIFY_RESIZE'
@ -512,18 +465,12 @@ class ConfirmResize(tables.Action):
api.nova.server_confirm_resize(request, instance)
class RevertResize(tables.Action):
class RevertResize(policy.PolicyTargetMixin, tables.Action):
name = "revert"
verbose_name = _("Revert Resize/Migrate")
classes = ("btn-revert", "btn-action-required")
policy_rules = (("compute", "compute:revert_resize"),)
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum, 'tenant_id', None)
return {"project_id": project_id}
def allowed(self, request, instance):
return instance.status == 'VERIFY_RESIZE'
@ -531,19 +478,13 @@ class RevertResize(tables.Action):
api.nova.server_revert_resize(request, instance)
class RebuildInstance(tables.LinkAction):
class RebuildInstance(policy.PolicyTargetMixin, tables.LinkAction):
name = "rebuild"
verbose_name = _("Rebuild Instance")
classes = ("btn-rebuild", "ajax-modal")
url = "horizon:project:instances:rebuild"
policy_rules = (("compute", "compute:rebuild"),)
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum, 'tenant_id', None)
return {"project_id": project_id}
def allowed(self, request, instance):
return ((instance.status in ACTIVE_STATES
or instance.status == 'SHUTOFF')
@ -577,7 +518,7 @@ class DecryptInstancePassword(tables.LinkAction):
keypair_name])
class AssociateIP(tables.LinkAction):
class AssociateIP(policy.PolicyTargetMixin, tables.LinkAction):
name = "associate"
verbose_name = _("Associate Floating IP")
url = "horizon:project:access_and_security:floating_ips:associate"
@ -585,12 +526,6 @@ class AssociateIP(tables.LinkAction):
icon = "link"
policy_rules = (("compute", "network:associate_floating_ip"),)
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum, 'tenant_id', None)
return {"project_id": project_id}
def allowed(self, request, instance):
if not api.network.floating_ip_supported(request):
return False
@ -607,18 +542,12 @@ class AssociateIP(tables.LinkAction):
return "?".join([base_url, params])
class SimpleAssociateIP(tables.Action):
class SimpleAssociateIP(policy.PolicyTargetMixin, tables.Action):
name = "associate-simple"
verbose_name = _("Associate Floating IP")
icon = "link"
policy_rules = (("compute", "network:associate_floating_ip"),)
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum, 'tenant_id', None)
return {"project_id": project_id}
def allowed(self, request, instance):
if not api.network.floating_ip_simple_associate_supported(request):
return False
@ -642,18 +571,12 @@ class SimpleAssociateIP(tables.Action):
return shortcuts.redirect("horizon:project:instances:index")
class SimpleDisassociateIP(tables.Action):
class SimpleDisassociateIP(policy.PolicyTargetMixin, tables.Action):
name = "disassociate"
verbose_name = _("Disassociate Floating IP")
classes = ("btn-danger", "btn-disassociate",)
policy_rules = (("compute", "network:disassociate_floating_ip"),)
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum, 'tenant_id', None)
return {"project_id": project_id}
def allowed(self, request, instance):
if not api.network.floating_ip_supported(request):
return False
@ -725,7 +648,7 @@ class UpdateRow(tables.Row):
return instance
class StartInstance(tables.BatchAction):
class StartInstance(policy.PolicyTargetMixin, tables.BatchAction):
name = "start"
policy_rules = (("compute", "compute:start"),)
@ -745,12 +668,6 @@ class StartInstance(tables.BatchAction):
count
)
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum, 'tenant_id', None)
return {"project_id": project_id}
def allowed(self, request, instance):
return instance.status in ("SHUTDOWN", "SHUTOFF", "CRASHED")
@ -758,7 +675,7 @@ class StartInstance(tables.BatchAction):
api.nova.server_start(request, obj_id)
class StopInstance(tables.BatchAction):
class StopInstance(policy.PolicyTargetMixin, tables.BatchAction):
name = "stop"
classes = ('btn-danger',)
policy_rules = (("compute", "compute:stop"),)
@ -781,12 +698,6 @@ class StopInstance(tables.BatchAction):
count
)
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum, 'tenant_id', None)
return {"project_id": project_id}
def allowed(self, request, instance):
return ((get_power_state(instance)
in ("RUNNING", "PAUSED", "SUSPENDED"))

View File

@ -22,6 +22,7 @@ from horizon import exceptions
from horizon import tables
from openstack_dashboard import api
from openstack_dashboard import policy
class AddPoolLink(tables.LinkAction):
@ -69,7 +70,7 @@ class AddMonitorLink(tables.LinkAction):
policy_rules = (("network", "create_health_monitor"),)
class DeleteVipLink(tables.DeleteAction):
class DeleteVipLink(policy.PolicyTargetMixin, tables.DeleteAction):
name = "deletevip"
action_present = _("Delete")
action_past = _("Scheduled deletion of %(data_type)s")
@ -77,19 +78,13 @@ class DeleteVipLink(tables.DeleteAction):
data_type_plural = _("VIPs")
policy_rules = (("network", "delete_vip"),)
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum, 'tenant_id', None)
return {"project_id": project_id}
def allowed(self, request, datum=None):
if datum and not datum.vip_id:
return False
return True
class DeletePoolLink(tables.DeleteAction):
class DeletePoolLink(policy.PolicyTargetMixin, tables.DeleteAction):
name = "deletepool"
action_present = _("Delete")
action_past = _("Scheduled deletion of %(data_type)s")
@ -97,19 +92,14 @@ class DeletePoolLink(tables.DeleteAction):
data_type_plural = _("Pools")
policy_rules = (("network", "delete_pool"),)
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum, 'tenant_id', None)
return {"project_id": project_id}
def allowed(self, request, datum=None):
if datum and datum.vip_id:
return False
return True
class DeleteMonitorLink(tables.DeleteAction):
class DeleteMonitorLink(policy.PolicyTargetMixin,
tables.DeleteAction):
name = "deletemonitor"
action_present = _("Delete")
action_past = _("Scheduled deletion of %(data_type)s")
@ -117,14 +107,8 @@ class DeleteMonitorLink(tables.DeleteAction):
data_type_plural = _("Monitors")
policy_rules = (("network", "delete_health_monitor"),)
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum, 'tenant_id', None)
return {"project_id": project_id}
class DeleteMemberLink(tables.DeleteAction):
class DeleteMemberLink(policy.PolicyTargetMixin, tables.DeleteAction):
name = "deletemember"
action_present = _("Delete")
action_past = _("Scheduled deletion of %(data_type)s")
@ -132,43 +116,25 @@ class DeleteMemberLink(tables.DeleteAction):
data_type_plural = _("Members")
policy_rules = (("network", "delete_member"),)
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum, 'tenant_id', None)
return {"project_id": project_id}
class UpdatePoolLink(tables.LinkAction):
class UpdatePoolLink(policy.PolicyTargetMixin, tables.LinkAction):
name = "updatepool"
verbose_name = _("Edit Pool")
classes = ("ajax-modal", "btn-update",)
policy_rules = (("network", "update_pool"),)
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum, 'tenant_id', None)
return {"project_id": project_id}
def get_link_url(self, pool):
base_url = reverse("horizon:project:loadbalancers:updatepool",
kwargs={'pool_id': pool.id})
return base_url
class UpdateVipLink(tables.LinkAction):
class UpdateVipLink(policy.PolicyTargetMixin, tables.LinkAction):
name = "updatevip"
verbose_name = _("Edit VIP")
classes = ("ajax-modal", "btn-update",)
policy_rules = (("network", "update_vip"),)
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum, 'tenant_id', None)
return {"project_id": project_id}
def get_link_url(self, pool):
base_url = reverse("horizon:project:loadbalancers:updatevip",
kwargs={'vip_id': pool.vip_id})
@ -180,36 +146,24 @@ class UpdateVipLink(tables.LinkAction):
return True
class UpdateMemberLink(tables.LinkAction):
class UpdateMemberLink(policy.PolicyTargetMixin, tables.LinkAction):
name = "updatemember"
verbose_name = _("Edit Member")
classes = ("ajax-modal", "btn-update",)
policy_rules = (("network", "update_member"),)
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum, 'tenant_id', None)
return {"project_id": project_id}
def get_link_url(self, member):
base_url = reverse("horizon:project:loadbalancers:updatemember",
kwargs={'member_id': member.id})
return base_url
class UpdateMonitorLink(tables.LinkAction):
class UpdateMonitorLink(policy.PolicyTargetMixin, tables.LinkAction):
name = "updatemonitor"
verbose_name = _("Edit Monitor")
classes = ("ajax-modal", "btn-update",)
policy_rules = (("network", "update_health_monitor"),)
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum, 'tenant_id', None)
return {"project_id": project_id}
def get_link_url(self, monitor):
base_url = reverse("horizon:project:loadbalancers:updatemonitor",
kwargs={'monitor_id': monitor.id})
@ -224,7 +178,8 @@ def get_vip_link(pool):
return None
class AddPMAssociationLink(tables.LinkAction):
class AddPMAssociationLink(policy.PolicyTargetMixin,
tables.LinkAction):
name = "addassociation"
verbose_name = _("Associate Monitor")
url = "horizon:project:loadbalancers:addassociation"
@ -232,12 +187,6 @@ class AddPMAssociationLink(tables.LinkAction):
icon = "plus"
policy_rules = (("network", "create_pool_health_monitor"),)
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum, 'tenant_id', None)
return {"project_id": project_id}
def allowed(self, request, datum=None):
try:
tenant_id = request.user.tenant_id
@ -252,7 +201,8 @@ class AddPMAssociationLink(tables.LinkAction):
return False
class DeletePMAssociationLink(tables.LinkAction):
class DeletePMAssociationLink(policy.PolicyTargetMixin,
tables.LinkAction):
name = "deleteassociation"
verbose_name = _("Disassociate Monitor")
url = "horizon:project:loadbalancers:deleteassociation"
@ -260,12 +210,6 @@ class DeletePMAssociationLink(tables.LinkAction):
icon = "remove"
policy_rules = (("network", "delete_pool_health_monitor"),)
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum, 'tenant_id', None)
return {"project_id": project_id}
def allowed(self, request, datum=None):
if datum and not datum['health_monitors']:
return False

View File

@ -19,6 +19,7 @@ from django.utils.translation import ugettext_lazy as _
from horizon import tables
from openstack_dashboard import api
from openstack_dashboard import policy
def get_fixed_ips(port):
@ -36,7 +37,7 @@ def get_attached(port):
return _('Detached')
class UpdatePort(tables.LinkAction):
class UpdatePort(policy.PolicyTargetMixin, tables.LinkAction):
name = "update"
verbose_name = _("Edit Port")
url = "horizon:project:networks:editport"
@ -44,12 +45,6 @@ class UpdatePort(tables.LinkAction):
icon = "pencil"
policy_rules = (("network", "update_port"),)
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum, 'tenant_id', None)
return {"project_id": project_id}
def get_link_url(self, port):
network_id = self.table.kwargs['network_id']
return reverse(self.url, args=(network_id, port.id))

View File

@ -23,6 +23,7 @@ from horizon import tables
from horizon.utils import memoized
from openstack_dashboard import api
from openstack_dashboard import policy
LOG = logging.getLogger(__name__)
@ -40,16 +41,12 @@ class CheckNetworkEditable(object):
return True
class DeleteSubnet(CheckNetworkEditable, tables.DeleteAction):
class DeleteSubnet(policy.PolicyTargetMixin, CheckNetworkEditable,
tables.DeleteAction):
data_type_singular = _("Subnet")
data_type_plural = _("Subnets")
policy_rules = (("network", "delete_subnet"),)
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum, 'tenant_id', None)
return {"network:project_id": project_id}
policy_target_attrs = (("network:project_id", "tenant_id"),)
def delete(self, request, obj_id):
try:
@ -63,39 +60,34 @@ class DeleteSubnet(CheckNetworkEditable, tables.DeleteAction):
exceptions.handle(request, msg, redirect=redirect)
class CreateSubnet(CheckNetworkEditable, tables.LinkAction):
class CreateSubnet(policy.PolicyTargetMixin, CheckNetworkEditable,
tables.LinkAction):
name = "create"
verbose_name = _("Create Subnet")
url = "horizon:project:networks:addsubnet"
classes = ("ajax-modal",)
icon = "plus"
policy_rules = (("network", "create_subnet"),)
policy_target_attrs = (("network:project_id", "tenant_id"),)
def get_policy_target(self, request, datum=None):
project_id = None
network = self.table._get_network()
if network:
project_id = getattr(network, 'tenant_id', None)
return {"network:project_id": project_id}
return super(CreateSubnet, self)\
.get_policy_target(request, self.table._get_network())
def get_link_url(self, datum=None):
network_id = self.table.kwargs['network_id']
return reverse(self.url, args=(network_id,))
class UpdateSubnet(CheckNetworkEditable, tables.LinkAction):
class UpdateSubnet(policy.PolicyTargetMixin, CheckNetworkEditable,
tables.LinkAction):
name = "update"
verbose_name = _("Edit Subnet")
url = "horizon:project:networks:editsubnet"
classes = ("ajax-modal",)
icon = "pencil"
policy_rules = (("network", "update_subnet"),)
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum, 'tenant_id', None)
return {"network:project_id": project_id}
policy_target_attrs = (("network:project_id", "tenant_id"),)
def get_link_url(self, subnet):
network_id = self.table.kwargs['network_id']

View File

@ -22,7 +22,7 @@ from horizon import exceptions
from horizon import tables
from openstack_dashboard import api
from openstack_dashboard import policy
LOG = logging.getLogger(__name__)
@ -37,17 +37,12 @@ class CheckNetworkEditable(object):
return True
class DeleteNetwork(CheckNetworkEditable, tables.DeleteAction):
class DeleteNetwork(policy.PolicyTargetMixin, CheckNetworkEditable,
tables.DeleteAction):
data_type_singular = _("Network")
data_type_plural = _("Networks")
policy_rules = (("network", "delete_network"),)
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum, 'tenant_id', None)
return {"project_id": project_id}
def delete(self, request, network_id):
try:
# Retrieve existing subnets belonging to the network.
@ -76,7 +71,8 @@ class CreateNetwork(tables.LinkAction):
policy_rules = (("network", "create_network"),)
class EditNetwork(CheckNetworkEditable, tables.LinkAction):
class EditNetwork(policy.PolicyTargetMixin, CheckNetworkEditable,
tables.LinkAction):
name = "update"
verbose_name = _("Edit Network")
url = "horizon:project:networks:update"
@ -84,26 +80,16 @@ class EditNetwork(CheckNetworkEditable, tables.LinkAction):
icon = "pencil"
policy_rules = (("network", "update_network"),)
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum, 'tenant_id', None)
return {"project_id": project_id}
class CreateSubnet(CheckNetworkEditable, tables.LinkAction):
class CreateSubnet(policy.PolicyTargetMixin, CheckNetworkEditable,
tables.LinkAction):
name = "subnet"
verbose_name = _("Add Subnet")
url = "horizon:project:networks:addsubnet"
classes = ("ajax-modal",)
icon = "plus"
policy_rules = (("network", "create_subnet"),)
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum, 'tenant_id', None)
return {"network:project_id": project_id}
policy_target_attrs = (("network:project_id", "tenant_id"),)
def get_subnets(network):

View File

@ -19,13 +19,14 @@ from django.utils.translation import ugettext_lazy as _
from openstack_dashboard.dashboards.project.routers.extensions.routerrules\
import rulemanager
from openstack_dashboard import policy
from horizon import tables
LOG = logging.getLogger(__name__)
class AddRouterRule(tables.LinkAction):
class AddRouterRule(policy.PolicyTargetMixin, tables.LinkAction):
name = "create"
verbose_name = _("Add Router Rule")
url = "horizon:project:routers:addrouterrule"
@ -33,29 +34,17 @@ class AddRouterRule(tables.LinkAction):
icon = "plus"
policy_rules = (("network", "update_router"),)
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum, 'tenant_id', None)
return {"project_id": project_id}
def get_link_url(self, datum=None):
router_id = self.table.kwargs['router_id']
return reverse(self.url, args=(router_id,))
class RemoveRouterRule(tables.DeleteAction):
class RemoveRouterRule(policy.PolicyTargetMixin, tables.DeleteAction):
data_type_singular = _("Router Rule")
data_type_plural = _("Router Rules")
failure_url = 'horizon:project:routers:detail'
policy_rules = (("network", "update_router"),)
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum, 'tenant_id', None)
return {"project_id": project_id}
def delete(self, request, obj_id):
router_id = self.table.kwargs['router_id']
rulemanager.remove_rules(request, [obj_id],

View File

@ -23,6 +23,7 @@ from horizon import tables
from openstack_dashboard import api
from openstack_dashboard.dashboards.project.networks.ports \
import tables as project_tables
from openstack_dashboard import policy
LOG = logging.getLogger(__name__)
@ -36,7 +37,7 @@ def get_device_owner(port):
return ' '
class AddInterface(tables.LinkAction):
class AddInterface(policy.PolicyTargetMixin, tables.LinkAction):
name = "create"
verbose_name = _("Add Interface")
url = "horizon:project:routers:addinterface"
@ -44,18 +45,12 @@ class AddInterface(tables.LinkAction):
icon = "plus"
policy_rules = (("network", "add_router_interface"),)
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum, 'tenant_id', None)
return {"project_id": project_id}
def get_link_url(self, datum=None):
router_id = self.table.kwargs['router_id']
return reverse(self.url, args=(router_id,))
class RemoveInterface(tables.DeleteAction):
class RemoveInterface(policy.PolicyTargetMixin, tables.DeleteAction):
@staticmethod
def action_present(count):
return ungettext_lazy(
@ -75,12 +70,6 @@ class RemoveInterface(tables.DeleteAction):
failure_url = 'horizon:project:routers:detail'
policy_rules = (("network", "remove_router_interface"),)
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum, 'tenant_id', None)
return {"project_id": project_id}
def delete(self, request, obj_id):
try:
router_id = self.table.kwargs['router_id']

View File

@ -24,12 +24,12 @@ from horizon import exceptions
from horizon import messages
from horizon import tables
from openstack_dashboard import api
from openstack_dashboard import policy
LOG = logging.getLogger(__name__)
class DeleteRouter(tables.DeleteAction):
class DeleteRouter(policy.PolicyTargetMixin, tables.DeleteAction):
@staticmethod
def action_present(count):
return ungettext_lazy(
@ -49,12 +49,6 @@ class DeleteRouter(tables.DeleteAction):
redirect_url = "horizon:project:routers:index"
policy_rules = (("network", "delete_router"),)
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum, 'tenant_id', None)
return {"project_id": project_id}
def delete(self, request, obj_id):
obj = self.table.get_object_by_id(obj_id)
name = self.table.get_object_display(obj)
@ -84,7 +78,7 @@ class CreateRouter(tables.LinkAction):
policy_rules = (("network", "create_router"),)
class EditRouter(tables.LinkAction):
class EditRouter(policy.PolicyTargetMixin, tables.LinkAction):
name = "update"
verbose_name = _("Edit Router")
url = "horizon:project:routers:update"
@ -92,14 +86,8 @@ class EditRouter(tables.LinkAction):
icon = "pencil"
policy_rules = (("network", "update_router"),)
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum, 'tenant_id', None)
return {"project_id": project_id}
class SetGateway(tables.LinkAction):
class SetGateway(policy.PolicyTargetMixin, tables.LinkAction):
name = "setgateway"
verbose_name = _("Set Gateway")
url = "horizon:project:routers:setgateway"
@ -107,19 +95,13 @@ class SetGateway(tables.LinkAction):
icon = "camera"
policy_rules = (("network", "update_router"),)
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum, 'tenant_id', None)
return {"project_id": project_id}
def allowed(self, request, datum=None):
if datum.external_gateway_info:
return False
return True
class ClearGateway(tables.BatchAction):
class ClearGateway(policy.PolicyTargetMixin, tables.BatchAction):
name = "cleargateway"
action_present = _("Clear")
action_past = _("Cleared")
@ -129,12 +111,6 @@ class ClearGateway(tables.BatchAction):
redirect_url = "horizon:project:routers:index"
policy_rules = (("network", "update_router"),)
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum, 'tenant_id', None)
return {"project_id": project_id}
def action(self, request, obj_id):
obj = self.table.get_object_by_id(obj_id)
name = self.table.get_object_display(obj)

View File

@ -23,6 +23,7 @@ from horizon import tables
from openstack_dashboard import api
from openstack_dashboard.api import base
from openstack_dashboard.api import cinder
from openstack_dashboard import policy
from openstack_dashboard.dashboards.project.volumes \
.volumes import tables as volume_tables
@ -40,39 +41,27 @@ class LaunchSnapshot(volume_tables.LaunchVolume):
return "?".join([base_url, params])
class DeleteVolumeSnapshot(tables.DeleteAction):
class DeleteVolumeSnapshot(policy.PolicyTargetMixin, tables.DeleteAction):
data_type_singular = _("Volume Snapshot")
data_type_plural = _("Volume Snapshots")
action_past = _("Scheduled deletion of %(data_type)s")
policy_rules = (("volume", "volume:delete_snapshot"),)
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum,
"os-extended-snapshot-attributes:project_id",
None)
return {"project_id": project_id}
policy_target_attrs = (("project_id",
'os-extended-snapshot-attributes:project_id'),)
def delete(self, request, obj_id):
api.cinder.volume_snapshot_delete(request, obj_id)
class EditVolumeSnapshot(tables.LinkAction):
class EditVolumeSnapshot(policy.PolicyTargetMixin, tables.LinkAction):
name = "edit"
verbose_name = _("Edit Snapshot")
url = "horizon:project:volumes:snapshots:update"
classes = ("ajax-modal",)
icon = "pencil"
policy_rules = (("volume", "volume:update_snapshot"),)
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum,
"os-extended-snapshot-attributes:project_id",
None)
return {"project_id": project_id}
policy_target_attrs = (("project_id",
'os-extended-snapshot-attributes:project_id'),)
def allowed(self, request, snapshot=None):
return snapshot.status == "available"

View File

@ -33,6 +33,10 @@ from openstack_dashboard import policy
DELETABLE_STATES = ("available", "error", "error_extending")
class VolumePolicyTargetMixin(policy.PolicyTargetMixin):
policy_target_attrs = (("project_id", 'os-vol-tenant-attr:tenant_id'),)
class LaunchVolume(tables.LinkAction):
name = "launch_volume"
verbose_name = _("Launch as Instance")
@ -55,18 +59,12 @@ class LaunchVolume(tables.LinkAction):
return False
class DeleteVolume(tables.DeleteAction):
class DeleteVolume(VolumePolicyTargetMixin, tables.DeleteAction):
data_type_singular = _("Volume")
data_type_plural = _("Volumes")
action_past = _("Scheduled deletion of %(data_type)s")
policy_rules = (("volume", "volume:delete"),)
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum, "os-vol-tenant-attr:tenant_id", None)
return {"project_id": project_id}
def delete(self, request, obj_id):
obj = self.table.get_object_by_id(obj_id)
name = self.table.get_object_display(obj)
@ -121,19 +119,13 @@ class CreateVolume(tables.LinkAction):
return HttpResponse(self.render())
class ExtendVolume(tables.LinkAction):
class ExtendVolume(VolumePolicyTargetMixin, tables.LinkAction):
name = "extend"
verbose_name = _("Extend Volume")
url = "horizon:project:volumes:volumes:extend"
classes = ("ajax-modal", "btn-extend")
policy_rules = (("volume", "volume:extend"),)
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum, "os-vol-tenant-attr:tenant_id", None)
return {"project_id": project_id}
def allowed(self, request, volume=None):
return volume.status == "available"
@ -162,7 +154,7 @@ class EditAttachments(tables.LinkAction):
return False
class CreateSnapshot(tables.LinkAction):
class CreateSnapshot(VolumePolicyTargetMixin, tables.LinkAction):
name = "snapshots"
verbose_name = _("Create Snapshot")
url = "horizon:project:volumes:volumes:create_snapshot"
@ -170,12 +162,6 @@ class CreateSnapshot(tables.LinkAction):
icon = "camera"
policy_rules = (("volume", "volume:create_snapshot"),)
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum, "os-vol-tenant-attr:tenant_id", None)
return {"project_id": project_id}
def allowed(self, request, volume=None):
try:
limits = api.cinder.tenant_absolute_limits(request)
@ -193,25 +179,19 @@ class CreateSnapshot(tables.LinkAction):
return volume.status in ("available", "in-use")
class CreateBackup(tables.LinkAction):
class CreateBackup(VolumePolicyTargetMixin, tables.LinkAction):
name = "backups"
verbose_name = _("Create Backup")
url = "horizon:project:volumes:volumes:create_backup"
classes = ("ajax-modal",)
policy_rules = (("volume", "backup:create"),)
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum, "os-vol-tenant-attr:tenant_id", None)
return {"project_id": project_id}
def allowed(self, request, volume=None):
return (cinder.volume_backup_supported(request) and
volume.status == "available")
class UploadToImage(tables.LinkAction):
class UploadToImage(VolumePolicyTargetMixin, tables.LinkAction):
name = "upload_to_image"
verbose_name = _("Upload to Image")
url = "horizon:project:volumes:volumes:upload_to_image"
@ -219,13 +199,6 @@ class UploadToImage(tables.LinkAction):
icon = "cloud-upload"
policy_rules = (("volume", "volume:upload_to_image"),)
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum, "os-vol-tenant-attr:tenant_id", None)
return {"project_id": project_id}
def allowed(self, request, volume=None):
has_image_service_perm = \
request.user.has_perm('openstack.services.image')
@ -234,7 +207,7 @@ class UploadToImage(tables.LinkAction):
has_image_service_perm
class EditVolume(tables.LinkAction):
class EditVolume(VolumePolicyTargetMixin, tables.LinkAction):
name = "edit"
verbose_name = _("Edit Volume")
url = "horizon:project:volumes:volumes:update"
@ -242,17 +215,11 @@ class EditVolume(tables.LinkAction):
icon = "pencil"
policy_rules = (("volume", "volume:update"),)
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum, "os-vol-tenant-attr:tenant_id", None)
return {"project_id": project_id}
def allowed(self, request, volume=None):
return volume.status in ("available", "in-use")
class RetypeVolume(tables.LinkAction):
class RetypeVolume(VolumePolicyTargetMixin, tables.LinkAction):
name = "retype"
verbose_name = _("Change Volume Type")
url = "horizon:project:volumes:volumes:retype"
@ -260,13 +227,6 @@ class RetypeVolume(tables.LinkAction):
icon = "pencil"
policy_rules = (("volume", "volume:retype"),)
def get_policy_target(self, request, datum=None):
project_id = None
if datum:
project_id = getattr(datum, "os-vol-tenant-attr:tenant_id", None)
return {"project_id": project_id}
def allowed(self, request, volume=None):
retype_supported = cinder.retype_supported()

View File

@ -152,3 +152,29 @@ def _user_to_credentials(request, user):
'is_admin': user.is_superuser,
'roles': roles}
return user._credentials
class PolicyTargetMixin(object):
"""Mixin that adds the get_policy_target function
policy_target_attrs - a tuple of tuples which defines
the relationship between attributes in the policy
target dict and attributes in the passed datum object.
policy_target_attrs can be overwritten by sub-classes
which do not use the default, so they can neatly define
their policy target information, without overriding the
entire get_policy_target function.
"""
policy_target_attrs = (("project_id", "tenant_id"),
("user_id", "user_id"),
("domain_id", "domain_id"))
def get_policy_target(self, request, datum=None):
policy_target = {}
for policy_attr, datum_attr in self.policy_target_attrs:
if datum:
policy_target[policy_attr] = getattr(datum, datum_attr, None)
else:
policy_target[policy_attr] = None
return policy_target