diff --git a/openstack_dashboard/dashboards/admin/networks/subnets/tables.py b/openstack_dashboard/dashboards/admin/networks/subnets/tables.py index 5c72803540..9e9dadd8cb 100644 --- a/openstack_dashboard/dashboards/admin/networks/subnets/tables.py +++ b/openstack_dashboard/dashboards/admin/networks/subnets/tables.py @@ -17,7 +17,6 @@ import logging from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse_lazy from django.utils.translation import ugettext_lazy as _ -from django.utils.translation import ungettext_lazy from horizon import exceptions from horizon import tables @@ -33,38 +32,6 @@ from openstack_dashboard.usage import quotas LOG = logging.getLogger(__name__) -class DeleteSubnet(proj_tables.SubnetPolicyTargetMixin, tables.DeleteAction): - @staticmethod - def action_present(count): - return ungettext_lazy( - u"Delete Subnet", - u"Delete Subnets", - count - ) - - @staticmethod - def action_past(count): - return ungettext_lazy( - u"Deleted Subnet", - u"Deleted Subnets", - count - ) - - policy_rules = (("network", "delete_subnet"),) - - def delete(self, request, obj_id): - try: - api.neutron.subnet_delete(request, obj_id) - except Exception as e: - LOG.info('Failed to delete subnet %(id)s: %(exc)s', - {'id': obj_id, 'exc': e}) - msg = _('Failed to delete subnet %s') % obj_id - network_id = self.table.kwargs['network_id'] - redirect = reverse('horizon:admin:networks:detail', - args=[network_id]) - exceptions.handle(request, msg, redirect=redirect) - - class CreateSubnet(proj_tables.SubnetPolicyTargetMixin, tables.LinkAction): name = "create" verbose_name = _("Create Subnet") @@ -149,8 +116,9 @@ class SubnetsTable(tables.DataTable): class Meta(object): name = "subnets" verbose_name = _("Subnets") - table_actions = (CreateSubnet, DeleteSubnet, tables.FilterAction,) - row_actions = (UpdateSubnet, DeleteSubnet,) + table_actions = (CreateSubnet, proj_tables.DeleteSubnet, + tables.FilterAction,) + row_actions = (UpdateSubnet, proj_tables.DeleteSubnet,) hidden_title = False def __init__(self, request, data=None, needs_form_wrapper=None, **kwargs): diff --git a/openstack_dashboard/dashboards/admin/networks/tables.py b/openstack_dashboard/dashboards/admin/networks/tables.py index c359e8d33d..d035aa1653 100644 --- a/openstack_dashboard/dashboards/admin/networks/tables.py +++ b/openstack_dashboard/dashboards/admin/networks/tables.py @@ -14,11 +14,9 @@ import logging -from django.core.urlresolvers import reverse from django.template import defaultfilters as filters from django.utils.translation import pgettext_lazy from django.utils.translation import ugettext_lazy as _ -from django.utils.translation import ungettext_lazy from horizon import exceptions from horizon import tables @@ -32,36 +30,6 @@ from openstack_dashboard.usage import quotas LOG = logging.getLogger(__name__) -class DeleteNetwork(policy.PolicyTargetMixin, tables.DeleteAction): - @staticmethod - def action_present(count): - return ungettext_lazy( - u"Delete Network", - u"Delete Networks", - count - ) - - @staticmethod - def action_past(count): - return ungettext_lazy( - u"Deleted Network", - u"Deleted Networks", - count - ) - - policy_rules = (("network", "delete_network"),) - - def delete(self, request, obj_id): - try: - api.neutron.network_delete(request, obj_id) - except Exception as e: - LOG.info('Failed to delete network %(id)s: %(exc)s', - {'id': obj_id, 'exc': e}) - msg = _('Failed to delete network %s') % obj_id - redirect = reverse('horizon:admin:networks:index') - exceptions.handle(request, msg, redirect=redirect) - - class CreateNetwork(tables.LinkAction): name = "create" verbose_name = _("Create Network") @@ -147,9 +115,9 @@ class NetworksTable(tables.DataTable): class Meta(object): name = "networks" verbose_name = _("Networks") - table_actions = (CreateNetwork, DeleteNetwork, + table_actions = (CreateNetwork, project_tables.DeleteNetwork, AdminNetworksFilterAction) - row_actions = (EditNetwork, CreateSubnet, DeleteNetwork) + row_actions = (EditNetwork, CreateSubnet, project_tables.DeleteNetwork) def __init__(self, request, data=None, needs_form_wrapper=None, **kwargs): super(NetworksTable, self).__init__( diff --git a/openstack_dashboard/dashboards/project/networks/subnets/tables.py b/openstack_dashboard/dashboards/project/networks/subnets/tables.py index 71f3440c0f..219709021e 100644 --- a/openstack_dashboard/dashboards/project/networks/subnets/tables.py +++ b/openstack_dashboard/dashboards/project/networks/subnets/tables.py @@ -14,6 +14,8 @@ import logging +from neutronclient.common import exceptions as neutron_exceptions + from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse_lazy from django.utils.translation import ugettext_lazy as _ @@ -21,6 +23,7 @@ from django.utils.translation import ungettext_lazy from horizon import exceptions from horizon import tables +from horizon.tables import actions from horizon.utils import memoized from openstack_dashboard import api @@ -73,17 +76,20 @@ class DeleteSubnet(SubnetPolicyTargetMixin, tables.DeleteAction): policy_rules = (("network", "delete_subnet"),) + @actions.handle_exception_with_detail_message( + # normal_log_message + 'Failed to delete subnet %(id)s: %(exc)s', + # target_exception + neutron_exceptions.Conflict, + # target_log_message + 'Unable to delete subnet %(id)s with 409 Conflict: %(exc)s', + # target_user_message + _('Unable to delete subnet %(name)s. Most possible reason is because ' + 'one or more ports have an IP allocation from this subnet.'), + # logger_name + __name__) def delete(self, request, obj_id): - try: - api.neutron.subnet_delete(request, obj_id) - except Exception as e: - LOG.info('Failed to delete subnet %(id)s: %(exc)s', - {'id': obj_id, 'exc': e}) - msg = _('Failed to delete subnet %s') % obj_id - network_id = self.table.kwargs['network_id'] - redirect = reverse('horizon:project:networks:detail', - args=[network_id]) - exceptions.handle(request, msg, redirect=redirect) + api.neutron.subnet_delete(request, obj_id) class CreateSubnet(SubnetPolicyTargetMixin, tables.LinkAction): diff --git a/openstack_dashboard/dashboards/project/networks/tables.py b/openstack_dashboard/dashboards/project/networks/tables.py index d995b233ba..1776e2c7a5 100644 --- a/openstack_dashboard/dashboards/project/networks/tables.py +++ b/openstack_dashboard/dashboards/project/networks/tables.py @@ -13,7 +13,6 @@ # under the License. import logging -from django.core.urlresolvers import reverse_lazy from django import template from django.template import defaultfilters as filters from django.utils.translation import pgettext_lazy @@ -23,6 +22,7 @@ from neutronclient.common import exceptions as neutron_exceptions from horizon import exceptions from horizon import tables +from horizon.tables import actions from openstack_dashboard import api from openstack_dashboard.dashboards.project.networks.subnets import tables \ @@ -53,34 +53,24 @@ class DeleteNetwork(policy.PolicyTargetMixin, tables.DeleteAction): policy_rules = (("network", "delete_network"),) + @actions.handle_exception_with_detail_message( + # normal_log_message + 'Failed to delete network %(id)s: %(exc)s', + # target_exception + neutron_exceptions.Conflict, + # target_log_message + 'Unable to delete network %(id)s with 409 Conflict: %(exc)s', + # target_user_message + _('Unable to delete network %(name)s. Most possible reason is because ' + 'one or more ports still exist on the requested network.'), + # logger_name + __name__) def delete(self, request, network_id): - network_name = network_id - redirect_url = reverse_lazy("horizon:project:networks:index") - try: - # Retrieve the network list. - network = api.neutron.network_get(request, network_id, - expand_subnet=False) - network_name = network.name - LOG.debug('Network %(network_id)s has subnets: %(subnets)s', - {'network_id': network_id, 'subnets': network.subnets}) - for subnet_id in network.subnets: - api.neutron.subnet_delete(request, subnet_id) - LOG.debug('Deleted subnet %s', subnet_id) - api.neutron.network_delete(request, network_id) - LOG.debug('Deleted network %s successfully', network_id) - except neutron_exceptions.Conflict as e: - LOG.info('Failed to delete network %(id)s with 409 Conflict: ' - '%(exc)s', {'id': network_id, 'exc': e}) - msg = (_('Failed to delete network %(network_name)s. ' - 'Most possible case is that one or more ports still ' - 'exist on the requested network.') % - {"network_name": network_name, "subnet_id": subnet_id}) - exceptions.handle(request, msg, redirect=redirect_url) - except Exception as e: - LOG.info('Failed to delete network %(id)s: %(exc)s', - {'id': network_id, 'exc': e}) - msg = _('Failed to delete network %s') % network_name - exceptions.handle(request, msg, redirect=redirect_url) + network = self.table.get_object_by_id(network_id) + LOG.debug('Network %(network_id)s has subnets: %(subnets)s', + {'network_id': network_id, 'subnets': network.subnets}) + api.neutron.network_delete(request, network_id) + LOG.debug('Deleted network %s successfully', network_id) class CreateNetwork(tables.LinkAction): diff --git a/openstack_dashboard/dashboards/project/networks/tests.py b/openstack_dashboard/dashboards/project/networks/tests.py index fa70bfe20b..d2835fb5c4 100644 --- a/openstack_dashboard/dashboards/project/networks/tests.py +++ b/openstack_dashboard/dashboards/project/networks/tests.py @@ -1011,10 +1011,6 @@ class NetworkTests(test.TestCase, NetworkStubMixin): def test_delete_network_no_subnet(self): network = self.networks.first() network.subnets = [] - api.neutron.network_get(IsA(http.HttpRequest), - network.id, - expand_subnet=False)\ - .AndReturn(network) api.neutron.is_extension_supported( IsA(http.HttpRequest), 'network_availability_zone')\ .MultipleTimes().AndReturn(True) @@ -1030,23 +1026,13 @@ class NetworkTests(test.TestCase, NetworkStubMixin): @test.create_stubs({api.neutron: ('network_get', 'network_list', 'network_delete', - 'subnet_delete', 'is_extension_supported')}) def test_delete_network_with_subnet(self): network = self.networks.first() - network.subnets = [subnet.id for subnet in network.subnets] - subnet_id = network.subnets[0] - subnetv6_id = network.subnets[1] - api.neutron.network_get(IsA(http.HttpRequest), - network.id, - expand_subnet=False)\ - .AndReturn(network) api.neutron.is_extension_supported( IsA(http.HttpRequest), 'network_availability_zone')\ .MultipleTimes().AndReturn(True) self._stub_net_list() - api.neutron.subnet_delete(IsA(http.HttpRequest), subnet_id) - api.neutron.subnet_delete(IsA(http.HttpRequest), subnetv6_id) api.neutron.network_delete(IsA(http.HttpRequest), network.id) self.mox.ReplayAll() @@ -1059,23 +1045,13 @@ class NetworkTests(test.TestCase, NetworkStubMixin): @test.create_stubs({api.neutron: ('network_get', 'network_list', 'network_delete', - 'subnet_delete', 'is_extension_supported')}) def test_delete_network_exception(self): network = self.networks.first() - network.subnets = [subnet.id for subnet in network.subnets] - subnet_id = network.subnets[0] - subnetv6_id = network.subnets[1] - api.neutron.network_get(IsA(http.HttpRequest), - network.id, - expand_subnet=False)\ - .AndReturn(network) api.neutron.is_extension_supported( IsA(http.HttpRequest), 'network_availability_zone')\ .MultipleTimes().AndReturn(True) self._stub_net_list() - api.neutron.subnet_delete(IsA(http.HttpRequest), subnet_id) - api.neutron.subnet_delete(IsA(http.HttpRequest), subnetv6_id) api.neutron.network_delete(IsA(http.HttpRequest), network.id)\ .AndRaise(self.exceptions.neutron) diff --git a/openstack_dashboard/dashboards/project/routers/tables.py b/openstack_dashboard/dashboards/project/routers/tables.py index b0cd5cbf0d..7266c08b51 100644 --- a/openstack_dashboard/dashboards/project/routers/tables.py +++ b/openstack_dashboard/dashboards/project/routers/tables.py @@ -19,11 +19,11 @@ from django.template import defaultfilters as filters from django.utils.translation import pgettext_lazy from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ungettext_lazy -from neutronclient.common import exceptions as q_ext +from neutronclient.common import exceptions as neutron_exceptions from horizon import exceptions -from horizon import messages from horizon import tables +from horizon.tables import actions from openstack_dashboard import api from openstack_dashboard import policy @@ -53,38 +53,26 @@ class DeleteRouter(policy.PolicyTargetMixin, tables.DeleteAction): redirect_url = "horizon:project:routers:index" policy_rules = (("network", "delete_router"),) + @actions.handle_exception_with_detail_message( + # normal_log_message + 'Failed to delete router %(id)s: %(exc)s', + # target_exception + neutron_exceptions.NeutronClientException, + # target_log_message + 'Unable to delete router %(id)s: %(exc)s', + # target_user_message + _('Unable to delete router %(name)s: %(exc)s'), + # logger_name + __name__) def delete(self, request, obj_id): - try: - # detach all interfaces before attempting to delete the router - search_opts = {'device_owner': 'network:router_interface', - 'device_id': obj_id} - ports = api.neutron.port_list(request, **search_opts) - for port in ports: - api.neutron.router_remove_interface(request, obj_id, - port_id=port.id) - api.neutron.router_delete(request, obj_id) - except q_ext.NeutronClientException as e: - # TODO(amotoki): Revisit why Http302 needs to be raised. - # We have this pattern ONLY HERE. - # Can't we merge two except clauses? - LOG.info('Unable to delete router %(id)s: %(exc)s', - {'id': obj_id, 'exc': e}) - obj = self.table.get_object_by_id(obj_id) - name = self.table.get_object_display(obj) - msg = _('Unable to delete router "%s"') % name - messages.error(request, msg) - redirect = reverse(self.redirect_url) - raise exceptions.Http302(redirect, message=msg) - except Exception as e: - LOG.info('Unable to delete router %(id)s: %(exc)s', - {'id': obj_id, 'exc': e}) - obj = self.table.get_object_by_id(obj_id) - name = self.table.get_object_display(obj) - msg = _('Unable to delete router "%s"') % name - exceptions.handle(request, msg) - - def allowed(self, request, router=None): - return True + # detach all interfaces before attempting to delete the router + search_opts = {'device_owner': 'network:router_interface', + 'device_id': obj_id} + ports = api.neutron.port_list(request, **search_opts) + for port in ports: + api.neutron.router_remove_interface(request, obj_id, + port_id=port.id) + api.neutron.router_delete(request, obj_id) class CreateRouter(tables.LinkAction): @@ -159,19 +147,21 @@ class ClearGateway(policy.PolicyTargetMixin, tables.BatchAction): policy_rules = (("network", "update_router"),) action_type = "danger" + @actions.handle_exception_with_detail_message( + # normal_log_message + 'Unable to clear gateway for router %(id)s: %(exc)s', + # target_exception + neutron_exceptions.Conflict, + # target_log_message + 'Unable to clear gateway for router %(id)s: %(exc)s', + # target_user_message + _('Unable to clear gateway for router %(name)s. ' + 'Most possible reason is because the gateway is required ' + 'by one or more floating IPs'), + # logger_name + __name__) def action(self, request, obj_id): - obj = self.table.get_object_by_id(obj_id) - name = self.table.get_object_display(obj) - try: - api.neutron.router_remove_gateway(request, obj_id) - except Exception as e: - LOG.info('Unable to clear gateway for router %(id)s: %(exc)s', - {'id': obj_id, 'exc': e}) - msg = (_('Unable to clear gateway for router ' - '"%(name)s": "%(msg)s"') - % {"name": name, "msg": e}) - redirect = reverse(self.redirect_url) - exceptions.handle(request, msg, redirect=redirect) + api.neutron.router_remove_gateway(request, obj_id) def get_success_url(self, request): return reverse(self.redirect_url)