Use ClientPlugin.ignore_not_found as a context manager
These are all trivial uses with no flow control implications, where using a context manager is clearly simpler. Change-Id: I908c34738f8881787ea697c7378dcf2f17f6e7fc
This commit is contained in:
parent
55f30cc976
commit
c9140ff1df
@ -150,15 +150,11 @@ class ElasticIp(resource.Resource):
|
||||
|
||||
# deallocate the eip
|
||||
if self.properties[self.DOMAIN]:
|
||||
try:
|
||||
with self.client_plugin('neutron').ignore_not_found:
|
||||
self.neutron().delete_floatingip(self.resource_id)
|
||||
except Exception as ex:
|
||||
self.client_plugin('neutron').ignore_not_found(ex)
|
||||
else:
|
||||
try:
|
||||
with self.client_plugin('nova').ignore_not_found:
|
||||
self.client().floating_ips.delete(self.resource_id)
|
||||
except Exception as e:
|
||||
self.client_plugin('nova').ignore_not_found(e)
|
||||
|
||||
def handle_update(self, json_snippet, tmpl_diff, prop_diff):
|
||||
if prop_diff:
|
||||
|
@ -404,10 +404,8 @@ class Instance(resource.Resource, sh.SchedulerHintsMixin):
|
||||
# delete the port data which implicit-created
|
||||
port_id = self.data().get('port_id')
|
||||
if port_id:
|
||||
try:
|
||||
with self.client_plugin('neutron').ignore_not_found:
|
||||
self.neutron().delete_port(port_id)
|
||||
except Exception as ex:
|
||||
self.client_plugin('neutron').ignore_not_found(ex)
|
||||
self.data_delete('port_id')
|
||||
|
||||
def _build_nics(self, network_interfaces,
|
||||
|
@ -126,10 +126,8 @@ class VPCGatewayAttachment(resource.Resource):
|
||||
|
||||
def handle_delete(self):
|
||||
for router in self._vpc_route_tables():
|
||||
try:
|
||||
with self.client_plugin().ignore_not_found:
|
||||
self.client().remove_gateway_router(router.resource_id)
|
||||
except Exception as ex:
|
||||
self.client_plugin().ignore_not_found(ex)
|
||||
|
||||
|
||||
def resource_mapping():
|
||||
|
@ -134,10 +134,8 @@ class NetworkInterface(resource.Resource):
|
||||
if self.resource_id is None:
|
||||
return
|
||||
|
||||
try:
|
||||
with self.client_plugin().ignore_not_found:
|
||||
self.client().delete_port(self.resource_id)
|
||||
except Exception as ex:
|
||||
self.client_plugin().ignore_not_found(ex)
|
||||
|
||||
def handle_update(self, json_snippet, tmpl_diff, prop_diff):
|
||||
if prop_diff:
|
||||
|
@ -92,16 +92,12 @@ class RouteTable(resource.Resource):
|
||||
client = self.client()
|
||||
|
||||
router_id = self.resource_id
|
||||
try:
|
||||
with self.client_plugin().ignore_not_found:
|
||||
client.delete_router(router_id)
|
||||
except Exception as ex:
|
||||
self.client_plugin().ignore_not_found(ex)
|
||||
|
||||
# just in case this router has been added to a gateway, remove it
|
||||
try:
|
||||
with self.client_plugin().ignore_not_found:
|
||||
client.remove_gateway_router(router_id)
|
||||
except Exception as ex:
|
||||
self.client_plugin().ignore_not_found(ex)
|
||||
|
||||
|
||||
class SubnetRouteTableAssociation(resource.Resource):
|
||||
@ -137,14 +133,12 @@ class SubnetRouteTableAssociation(resource.Resource):
|
||||
router_id = self.properties.get(self.ROUTE_TABLE_ID)
|
||||
|
||||
# remove the default router association for this subnet.
|
||||
try:
|
||||
with self.client_plugin().ignore_not_found:
|
||||
previous_router = self._router_for_subnet(subnet_id)
|
||||
if previous_router:
|
||||
client.remove_interface_router(
|
||||
previous_router['id'],
|
||||
{'subnet_id': subnet_id})
|
||||
except Exception as ex:
|
||||
self.client_plugin().ignore_not_found(ex)
|
||||
|
||||
client.add_interface_router(
|
||||
router_id, {'subnet_id': subnet_id})
|
||||
@ -162,20 +156,16 @@ class SubnetRouteTableAssociation(resource.Resource):
|
||||
|
||||
router_id = self.properties.get(self.ROUTE_TABLE_ID)
|
||||
|
||||
try:
|
||||
with self.client_plugin().ignore_not_found:
|
||||
client.remove_interface_router(router_id, {
|
||||
'subnet_id': subnet_id})
|
||||
except Exception as ex:
|
||||
self.client_plugin().ignore_not_found(ex)
|
||||
|
||||
# add back the default router
|
||||
try:
|
||||
with self.client_plugin().ignore_not_found:
|
||||
default_router = self._router_for_subnet(subnet_id)
|
||||
if default_router:
|
||||
client.add_interface_router(
|
||||
default_router['id'], {'subnet_id': subnet_id})
|
||||
except Exception as ex:
|
||||
self.client_plugin().ignore_not_found(ex)
|
||||
|
||||
|
||||
def resource_mapping():
|
||||
|
@ -151,10 +151,8 @@ class NovaSecurityGroup(BaseSecurityGroup):
|
||||
self.client.security_groups.delete(self.sg.resource_id)
|
||||
|
||||
def delete_rule(self, rule_id):
|
||||
try:
|
||||
with self.plugin.ignore_not_found:
|
||||
self.client.security_group_rules.delete(rule_id)
|
||||
except Exception as e:
|
||||
self.plugin.ignore_not_found(e)
|
||||
|
||||
def update(self, props):
|
||||
sec = self.client.security_groups.get(self.sg.resource_id)
|
||||
@ -277,16 +275,13 @@ class NeutronSecurityGroup(BaseSecurityGroup):
|
||||
else:
|
||||
for rule in sec['security_group_rules']:
|
||||
self.delete_rule(rule['id'])
|
||||
try:
|
||||
|
||||
with self.plugin.ignore_not_found:
|
||||
self.client.delete_security_group(self.sg.resource_id)
|
||||
except Exception as ex:
|
||||
self.plugin.ignore_not_found(ex)
|
||||
|
||||
def delete_rule(self, rule_id):
|
||||
try:
|
||||
with self.plugin.ignore_not_found:
|
||||
self.client.delete_security_group_rule(rule_id)
|
||||
except Exception as ex:
|
||||
self.plugin.ignore_not_found(ex)
|
||||
|
||||
def delete_default_egress_rules(self, sec):
|
||||
"""Delete the default rules which allow all egress traffic."""
|
||||
|
@ -107,19 +107,15 @@ class Subnet(resource.Resource):
|
||||
network_id = self.properties.get(self.VPC_ID)
|
||||
subnet_id = self.resource_id
|
||||
|
||||
try:
|
||||
with self.client_plugin().ignore_not_found:
|
||||
router = vpc.VPC.router_for_vpc(self.client(), network_id)
|
||||
if router:
|
||||
self.client().remove_interface_router(
|
||||
router['id'],
|
||||
{'subnet_id': subnet_id})
|
||||
except Exception as ex:
|
||||
self.client_plugin().ignore_not_found(ex)
|
||||
|
||||
try:
|
||||
with self.client_plugin().ignore_not_found:
|
||||
self.client().delete_subnet(subnet_id)
|
||||
except Exception as ex:
|
||||
self.client_plugin().ignore_not_found(ex)
|
||||
|
||||
def _resolve_attribute(self, name):
|
||||
if name == self.AVAILABILITY_ZONE:
|
||||
|
@ -111,17 +111,13 @@ class VPC(resource.Resource):
|
||||
if self.resource_id is None:
|
||||
return
|
||||
|
||||
try:
|
||||
with self.client_plugin().ignore_not_found:
|
||||
router = self.router_for_vpc(self.client(), self.resource_id)
|
||||
if router:
|
||||
self.client().delete_router(router['id'])
|
||||
except Exception as ex:
|
||||
self.client_plugin().ignore_not_found(ex)
|
||||
|
||||
try:
|
||||
with self.client_plugin().ignore_not_found:
|
||||
self.client().delete_network(self.resource_id)
|
||||
except Exception as ex:
|
||||
self.client_plugin().ignore_not_found(ex)
|
||||
|
||||
|
||||
def resource_mapping():
|
||||
|
@ -147,13 +147,11 @@ class DesignateRecord(resource.Resource):
|
||||
|
||||
def handle_delete(self):
|
||||
if self.resource_id is not None:
|
||||
try:
|
||||
with self.client_plugin().ignore_not_found:
|
||||
self.client_plugin().record_delete(
|
||||
id=self.resource_id,
|
||||
domain=self.properties[self.DOMAIN]
|
||||
)
|
||||
except Exception as ex:
|
||||
self.client_plugin().ignore_not_found(ex)
|
||||
|
||||
# FIXME(kanagaraj-manickam) Remove this method once designate defect
|
||||
# 1485552 is fixed.
|
||||
|
@ -173,10 +173,8 @@ class RemoteStack(resource.Resource):
|
||||
|
||||
def handle_delete(self):
|
||||
if self.resource_id is not None:
|
||||
try:
|
||||
with self.client_plugin().ignore_not_found:
|
||||
self.heat().stacks.delete(stack_id=self.resource_id)
|
||||
except Exception as e:
|
||||
self.client_plugin().ignore_not_found(e)
|
||||
|
||||
def handle_resume(self):
|
||||
if self.resource_id is None:
|
||||
|
@ -103,12 +103,10 @@ class KeystoneGroup(resource.Resource,
|
||||
|
||||
def handle_delete(self):
|
||||
if self.resource_id is not None:
|
||||
try:
|
||||
with self.client_plugin.ignore_not_found:
|
||||
self.delete_assignment(group_id=self.resource_id)
|
||||
|
||||
self.client().groups.delete(self.resource_id)
|
||||
except Exception as ex:
|
||||
self.client_plugin().ignore_not_found(ex)
|
||||
|
||||
|
||||
def resource_mapping():
|
||||
|
@ -232,7 +232,7 @@ class KeystoneUser(resource.Resource,
|
||||
|
||||
def handle_delete(self):
|
||||
if self.resource_id is not None:
|
||||
try:
|
||||
with self.client_plugin().ignore_not_found:
|
||||
self.delete_assignment(user_id=self.resource_id)
|
||||
|
||||
if self._stored_properties_data.get(self.GROUPS) is not None:
|
||||
@ -243,8 +243,6 @@ class KeystoneUser(resource.Resource,
|
||||
self._stored_properties_data.get(self.GROUPS)])
|
||||
|
||||
self.client().users.delete(self.resource_id)
|
||||
except Exception as ex:
|
||||
self.client_plugin().ignore_not_found(ex)
|
||||
|
||||
|
||||
def resource_mapping():
|
||||
|
@ -525,10 +525,8 @@ class Workflow(signal_responder.SignalResponder,
|
||||
def _delete_executions(self):
|
||||
if self.data().get(self.EXECUTIONS):
|
||||
for id in self.data().get(self.EXECUTIONS).split(','):
|
||||
try:
|
||||
with self.client_plugin().ignore_not_found:
|
||||
self.client().executions.delete(id)
|
||||
except Exception as ex:
|
||||
self.client_plugin().ignore_not_found(ex)
|
||||
|
||||
self.data_delete('executions')
|
||||
|
||||
|
@ -182,11 +182,9 @@ class MonascaAlarmDefinition(resource.Resource):
|
||||
|
||||
def handle_delete(self):
|
||||
if self.resource_id is not None:
|
||||
try:
|
||||
with self.client_plugin().ignore_not_found:
|
||||
self.client().alarm_definitions.delete(
|
||||
alarm_id=self.resource_id)
|
||||
except Exception as ex:
|
||||
self.client_plugin().ignore_not_found(ex)
|
||||
|
||||
# FIXME(kanagaraj-manickam) Remove this method once monasca defect 1484900
|
||||
# is fixed.
|
||||
|
@ -101,11 +101,9 @@ class MonascaNotification(resource.Resource):
|
||||
|
||||
def handle_delete(self):
|
||||
if self.resource_id is not None:
|
||||
try:
|
||||
with self.client_plugin().ignore_not_found:
|
||||
self.client().notifications.delete(
|
||||
notification_id=self.resource_id)
|
||||
except Exception as ex:
|
||||
self.client_plugin().ignore_not_found(ex)
|
||||
|
||||
# FIXME(kanagaraj-manickam) Remove this method once monasca defect 1484900
|
||||
# is fixed.
|
||||
|
@ -96,7 +96,7 @@ class ExtraRoute(neutron.NeutronResource):
|
||||
if not self.resource_id:
|
||||
return
|
||||
(router_id, destination, nexthop) = self.resource_id.split(':')
|
||||
try:
|
||||
with self.client_plugin().ignore_not_found:
|
||||
routes = self.client().show_router(
|
||||
router_id).get('router').get('routes', [])
|
||||
try:
|
||||
@ -106,8 +106,6 @@ class ExtraRoute(neutron.NeutronResource):
|
||||
return
|
||||
self.client().update_router(router_id,
|
||||
{'router': {'routes': routes}})
|
||||
except Exception as ex:
|
||||
self.client_plugin().ignore_not_found(ex)
|
||||
|
||||
|
||||
def resource_mapping():
|
||||
|
@ -229,10 +229,8 @@ class FloatingIP(neutron.NeutronResource):
|
||||
return self.client().show_floatingip(self.resource_id)['floatingip']
|
||||
|
||||
def handle_delete(self):
|
||||
try:
|
||||
with self.client_plugin().ignore_not_found:
|
||||
self.client().delete_floatingip(self.resource_id)
|
||||
except Exception as ex:
|
||||
self.client_plugin().ignore_not_found(ex)
|
||||
|
||||
def handle_update(self, json_snippet, tmpl_diff, prop_diff):
|
||||
if prop_diff:
|
||||
@ -324,12 +322,10 @@ class FloatingIPAssociation(neutron.NeutronResource):
|
||||
if not self.resource_id:
|
||||
return
|
||||
|
||||
try:
|
||||
with self.client_plugin().ignore_not_found:
|
||||
self.client().update_floatingip(
|
||||
self.properties[self.FLOATINGIP_ID],
|
||||
{'floatingip': {'port_id': None}})
|
||||
except Exception as ex:
|
||||
self.client_plugin().ignore_not_found(ex)
|
||||
|
||||
def handle_update(self, json_snippet, tmpl_diff, prop_diff):
|
||||
if prop_diff:
|
||||
@ -338,12 +334,10 @@ class FloatingIPAssociation(neutron.NeutronResource):
|
||||
# if the floatingip_id is changed, disassociate the port which
|
||||
# associated with the old floatingip_id
|
||||
if self.FLOATINGIP_ID in prop_diff:
|
||||
try:
|
||||
with self.client_plugin().ignore_not_found:
|
||||
self.client().update_floatingip(
|
||||
floatingip_id,
|
||||
{'floatingip': {'port_id': None}})
|
||||
except Exception as ex:
|
||||
self.client_plugin().ignore_not_found(ex)
|
||||
|
||||
# associate the floatingip with the new port
|
||||
floatingip_id = (prop_diff.get(self.FLOATINGIP_ID) or
|
||||
|
@ -740,10 +740,8 @@ class LoadBalancer(resource.Resource):
|
||||
old_members = set(six.iterkeys(rd_members))
|
||||
for member in old_members - members:
|
||||
member_id = rd_members[member]
|
||||
try:
|
||||
with self.client_plugin().ignore_not_found:
|
||||
self.client().delete_member(member_id)
|
||||
except Exception as ex:
|
||||
self.client_plugin().ignore_not_found(ex)
|
||||
self.data_delete(member)
|
||||
pool = self.properties[self.POOL_ID]
|
||||
protocol_port = self.properties[self.PROTOCOL_PORT]
|
||||
@ -761,10 +759,8 @@ class LoadBalancer(resource.Resource):
|
||||
# FIXME(pshchelo): this deletes members in a tight loop,
|
||||
# so is prone to OverLimit bug similar to LP 1265937
|
||||
for member, member_id in self.data().items():
|
||||
try:
|
||||
with self.client_plugin().ignore_not_found:
|
||||
self.client().delete_member(member_id)
|
||||
except Exception as ex:
|
||||
self.client_plugin().ignore_not_found(ex)
|
||||
self.data_delete(member)
|
||||
|
||||
|
||||
|
@ -207,7 +207,7 @@ class NetworkGateway(neutron.NeutronResource):
|
||||
|
||||
connections = self.properties[self.CONNECTIONS]
|
||||
for connection in connections:
|
||||
try:
|
||||
with self.client_plugin().ignore_not_found:
|
||||
self.client_plugin().resolve_network(
|
||||
connection, self.NETWORK, 'network_id')
|
||||
if self.NETWORK in six.iterkeys(connection):
|
||||
@ -215,8 +215,6 @@ class NetworkGateway(neutron.NeutronResource):
|
||||
self.client().disconnect_network_gateway(
|
||||
self.resource_id, connection
|
||||
)
|
||||
except Exception as ex:
|
||||
self.client_plugin().ignore_not_found(ex)
|
||||
|
||||
try:
|
||||
self.client().delete_network_gateway(self.resource_id)
|
||||
@ -243,7 +241,7 @@ class NetworkGateway(neutron.NeutronResource):
|
||||
|
||||
if self.CONNECTIONS in prop_diff:
|
||||
for connection in self.properties[self.CONNECTIONS]:
|
||||
try:
|
||||
with self.client_plugin().ignore_not_found:
|
||||
self.client_plugin().resolve_network(
|
||||
connection, self.NETWORK, 'network_id')
|
||||
if self.NETWORK in six.iterkeys(connection):
|
||||
@ -251,8 +249,6 @@ class NetworkGateway(neutron.NeutronResource):
|
||||
self.client().disconnect_network_gateway(
|
||||
self.resource_id, connection
|
||||
)
|
||||
except Exception as ex:
|
||||
self.client_plugin().ignore_not_found(ex)
|
||||
for connection in connections:
|
||||
self.client_plugin().resolve_network(
|
||||
connection, self.NETWORK, 'network_id')
|
||||
|
@ -442,12 +442,10 @@ class RouterInterface(neutron.NeutronResource):
|
||||
if len(tokens) == 2: # compatible with old data
|
||||
tokens.insert(1, 'subnet_id')
|
||||
(router_id, key, value) = tokens
|
||||
try:
|
||||
with self.client_plugin().ignore_not_found:
|
||||
self.client().remove_interface_router(
|
||||
router_id,
|
||||
{key: value})
|
||||
except Exception as ex:
|
||||
self.client_plugin().ignore_not_found(ex)
|
||||
|
||||
|
||||
class RouterGateway(neutron.NeutronResource):
|
||||
@ -545,10 +543,8 @@ class RouterGateway(neutron.NeutronResource):
|
||||
return
|
||||
|
||||
(router_id, network_id) = self.resource_id.split(':')
|
||||
try:
|
||||
with self.client_plugin().ignore_not_found:
|
||||
self.client().remove_gateway_router(router_id)
|
||||
except Exception as ex:
|
||||
self.client_plugin().ignore_not_found(ex)
|
||||
|
||||
|
||||
def resource_mapping():
|
||||
|
@ -226,10 +226,8 @@ class SecurityGroup(neutron.NeutronResource):
|
||||
return
|
||||
|
||||
self._delete_rules()
|
||||
try:
|
||||
with self.client_plugin().ignore_not_found:
|
||||
self.client().delete_security_group(self.resource_id)
|
||||
except Exception as ex:
|
||||
self.client_plugin().ignore_not_found(ex)
|
||||
|
||||
def handle_update(self, json_snippet, tmpl_diff, prop_diff):
|
||||
props = self.prepare_update_properties(json_snippet)
|
||||
|
@ -1249,15 +1249,13 @@ class Server(stack_user.StackUser, sh.SchedulerHintsMixin,
|
||||
object_name = self.data().get('metadata_object_name')
|
||||
if not object_name:
|
||||
return
|
||||
try:
|
||||
with self.client_plugin('swift').ignore_not_found:
|
||||
container = self.physical_resource_name()
|
||||
swift = self.client('swift')
|
||||
swift.delete_object(container, object_name)
|
||||
headers = swift.head_container(container)
|
||||
if int(headers['x-container-object-count']) == 0:
|
||||
swift.delete_container(container)
|
||||
except Exception as ex:
|
||||
self.client_plugin('swift').ignore_not_found(ex)
|
||||
|
||||
def _delete_queue(self):
|
||||
queue_id = self.data().get('metadata_queue_id')
|
||||
@ -1266,10 +1264,8 @@ class Server(stack_user.StackUser, sh.SchedulerHintsMixin,
|
||||
client_plugin = self.client_plugin('zaqar')
|
||||
zaqar = client_plugin.create_for_tenant(
|
||||
self.stack.stack_user_project_id)
|
||||
try:
|
||||
with client_plugin.ignore_not_found:
|
||||
zaqar.queue(queue_id).delete()
|
||||
except Exception as ex:
|
||||
client_plugin.ignore_not_found(ex)
|
||||
self.data_delete('metadata_queue_id')
|
||||
|
||||
def handle_snapshot_delete(self, state):
|
||||
@ -1407,10 +1403,8 @@ class Server(stack_user.StackUser, sh.SchedulerHintsMixin,
|
||||
|
||||
def handle_delete_snapshot(self, snapshot):
|
||||
image_id = snapshot['resource_data'].get('snapshot_image_id')
|
||||
try:
|
||||
with self.client_plugin().ignore_not_found:
|
||||
self.client().images.delete(image_id)
|
||||
except Exception as e:
|
||||
self.client_plugin().ignore_not_found(e)
|
||||
|
||||
def handle_restore(self, defn, restore_data):
|
||||
image_id = restore_data['resource_data']['snapshot_image_id']
|
||||
|
@ -143,10 +143,8 @@ class ServerNetworkMixin(object):
|
||||
|
||||
def _delete_internal_port(self, port_id):
|
||||
"""Delete physical port by id."""
|
||||
try:
|
||||
with self.client_plugin('neutron').ignore_not_found:
|
||||
self.client('neutron').delete_port(port_id)
|
||||
except Exception as ex:
|
||||
self.client_plugin('neutron').ignore_not_found(ex)
|
||||
|
||||
self._data_update_ports(port_id, 'delete')
|
||||
|
||||
|
@ -177,10 +177,9 @@ class SwiftContainer(resource.Resource):
|
||||
args.append(obj['name'])
|
||||
else:
|
||||
deleter = self.client().delete_container
|
||||
try:
|
||||
|
||||
with self.client_plugin().ignore_not_found:
|
||||
deleter(*args)
|
||||
except Exception as ex:
|
||||
self.client_plugin().ignore_not_found(ex)
|
||||
|
||||
def handle_delete(self):
|
||||
if self.resource_id is None:
|
||||
|
@ -110,10 +110,8 @@ class ZaqarQueue(resource.Resource):
|
||||
"""Delete a zaqar message queue."""
|
||||
if not self.resource_id:
|
||||
return
|
||||
try:
|
||||
with self.client_plugin().ignore_not_found:
|
||||
self.client().queue(self.resource_id, auto_create=False).delete()
|
||||
except Exception as exc:
|
||||
self.client_plugin().ignore_not_found(exc)
|
||||
|
||||
def href(self):
|
||||
api_endpoint = self.client().api_url
|
||||
|
@ -251,7 +251,7 @@ class SignalResponder(stack_user.StackUser):
|
||||
object_name = self.data().get('swift_signal_object_name')
|
||||
if not object_name:
|
||||
return
|
||||
try:
|
||||
with self.client_plugin('swift').ignore_not_found:
|
||||
container_name = self.stack.id
|
||||
swift = self.client('swift')
|
||||
|
||||
@ -268,8 +268,6 @@ class SignalResponder(stack_user.StackUser):
|
||||
headers = swift.head_container(container_name)
|
||||
if int(headers['x-container-object-count']) == 0:
|
||||
swift.delete_container(container_name)
|
||||
except Exception as ex:
|
||||
self.client_plugin('swift').ignore_not_found(ex)
|
||||
self.data_delete('swift_signal_object_name')
|
||||
self.data_delete('swift_signal_url')
|
||||
|
||||
@ -302,10 +300,8 @@ class SignalResponder(stack_user.StackUser):
|
||||
if not queue_id:
|
||||
return
|
||||
zaqar = self.client('zaqar')
|
||||
try:
|
||||
with self.client_plugin('zaqar').ignore_not_found:
|
||||
zaqar.queue(queue_id).delete()
|
||||
except Exception as ex:
|
||||
self.client_plugin('zaqar').ignore_not_found(ex)
|
||||
self.data_delete('zaqar_signal_queue_id')
|
||||
|
||||
def _get_signal(self, signal_type=SIGNAL, multiple_signals=False):
|
||||
|
Loading…
Reference in New Issue
Block a user