mirror of
https://github.com/ansible/awx.git
synced 2026-04-14 06:29:25 -02:30
delete inventories in the background via a celery task
see: #4382 see: #6279
This commit is contained in:
@@ -1130,7 +1130,7 @@ class InventorySerializer(BaseSerializerWithVariables):
|
|||||||
'total_hosts', 'hosts_with_active_failures', 'total_groups',
|
'total_hosts', 'hosts_with_active_failures', 'total_groups',
|
||||||
'groups_with_active_failures', 'has_inventory_sources',
|
'groups_with_active_failures', 'has_inventory_sources',
|
||||||
'total_inventory_sources', 'inventory_sources_with_failures',
|
'total_inventory_sources', 'inventory_sources_with_failures',
|
||||||
'insights_credential',)
|
'insights_credential', 'pending_deletion',)
|
||||||
|
|
||||||
def get_related(self, obj):
|
def get_related(self, obj):
|
||||||
res = super(InventorySerializer, self).get_related(obj)
|
res = super(InventorySerializer, self).get_related(obj)
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ import ansiconv
|
|||||||
from social.backends.utils import load_backends
|
from social.backends.utils import load_backends
|
||||||
|
|
||||||
# AWX
|
# AWX
|
||||||
from awx.main.tasks import send_notifications, update_host_smart_inventory_memberships
|
from awx.main.tasks import send_notifications, update_host_smart_inventory_memberships, delete_inventory
|
||||||
from awx.main.access import get_user_queryset
|
from awx.main.access import get_user_queryset
|
||||||
from awx.main.ha import is_ha_environment
|
from awx.main.ha import is_ha_environment
|
||||||
from awx.api.authentication import TaskAuthentication, TokenGetAuthentication
|
from awx.api.authentication import TaskAuthentication, TokenGetAuthentication
|
||||||
@@ -1838,9 +1838,16 @@ class InventoryDetail(ControlledByScmMixin, RetrieveUpdateDestroyAPIView):
|
|||||||
return super(InventoryDetail, self).update(request, *args, **kwargs)
|
return super(InventoryDetail, self).update(request, *args, **kwargs)
|
||||||
|
|
||||||
def destroy(self, request, *args, **kwargs):
|
def destroy(self, request, *args, **kwargs):
|
||||||
with ignore_inventory_computed_fields():
|
obj = self.get_object()
|
||||||
with ignore_inventory_group_removal():
|
if obj.pending_deletion is True:
|
||||||
return super(InventoryDetail, self).destroy(request, *args, **kwargs)
|
return Response(dict(error=_("Inventory is already being deleted.")), status=status.HTTP_400_BAD_REQUEST)
|
||||||
|
if not request.user.can_access(self.model, 'delete', obj):
|
||||||
|
raise PermissionDenied()
|
||||||
|
obj.websocket_emit_status('pending_deletion')
|
||||||
|
delete_inventory.delay(obj.id)
|
||||||
|
obj.pending_deletion = True
|
||||||
|
obj.save(update_fields=['pending_deletion'])
|
||||||
|
return Response(status=status.HTTP_202_ACCEPTED)
|
||||||
|
|
||||||
|
|
||||||
class InventoryActivityStreamList(ActivityStreamEnforcementMixin, SubListAPIView):
|
class InventoryActivityStreamList(ActivityStreamEnforcementMixin, SubListAPIView):
|
||||||
|
|||||||
@@ -70,6 +70,13 @@ class Migration(migrations.Migration):
|
|||||||
unique_together=set([('host', 'inventory')]),
|
unique_together=set([('host', 'inventory')]),
|
||||||
),
|
),
|
||||||
|
|
||||||
|
# Background Inventory deletion
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='inventory',
|
||||||
|
name='pending_deletion',
|
||||||
|
field=models.BooleanField(default=False, help_text='Flag indicating the inventory is being deleted.', editable=False),
|
||||||
|
),
|
||||||
|
|
||||||
# Facts
|
# Facts
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name='fact',
|
model_name='fact',
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import os.path
|
|||||||
|
|
||||||
# Django
|
# Django
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.db import models
|
from django.db import models, connection
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
from django.db import transaction
|
from django.db import transaction
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
@@ -20,6 +20,7 @@ from django.utils.timezone import now
|
|||||||
# AWX
|
# AWX
|
||||||
from awx.api.versioning import reverse
|
from awx.api.versioning import reverse
|
||||||
from awx.main.constants import CLOUD_PROVIDERS
|
from awx.main.constants import CLOUD_PROVIDERS
|
||||||
|
from awx.main.consumers import emit_channel_notification
|
||||||
from awx.main.fields import (
|
from awx.main.fields import (
|
||||||
ImplicitRoleField,
|
ImplicitRoleField,
|
||||||
JSONBField,
|
JSONBField,
|
||||||
@@ -153,6 +154,11 @@ class Inventory(CommonModelNameNotUnique, ResourceMixin):
|
|||||||
null=True,
|
null=True,
|
||||||
default=None,
|
default=None,
|
||||||
)
|
)
|
||||||
|
pending_deletion = models.BooleanField(
|
||||||
|
default=False,
|
||||||
|
editable=False,
|
||||||
|
help_text=_('Flag indicating the inventory is being deleted.'),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def get_absolute_url(self, request=None):
|
def get_absolute_url(self, request=None):
|
||||||
@@ -351,6 +357,12 @@ class Inventory(CommonModelNameNotUnique, ResourceMixin):
|
|||||||
iobj.save(update_fields=computed_fields.keys())
|
iobj.save(update_fields=computed_fields.keys())
|
||||||
logger.debug("Finished updating inventory computed fields")
|
logger.debug("Finished updating inventory computed fields")
|
||||||
|
|
||||||
|
def websocket_emit_status(self, status):
|
||||||
|
connection.on_commit(lambda: emit_channel_notification(
|
||||||
|
'inventories-status_changed',
|
||||||
|
{'group_name': 'inventories', 'inventory_id': self.id, 'status': status}
|
||||||
|
))
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def root_groups(self):
|
def root_groups(self):
|
||||||
group_pks = self.groups.values_list('pk', flat=True)
|
group_pks = self.groups.values_list('pk', flat=True)
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ from awx.main.isolated import run, isolated_manager
|
|||||||
from awx.main.utils import (get_ansible_version, get_ssh_version, decrypt_field, update_scm_url,
|
from awx.main.utils import (get_ansible_version, get_ssh_version, decrypt_field, update_scm_url,
|
||||||
check_proot_installed, build_proot_temp_dir,
|
check_proot_installed, build_proot_temp_dir,
|
||||||
wrap_args_with_proot, get_system_task_capacity, OutputEventFilter,
|
wrap_args_with_proot, get_system_task_capacity, OutputEventFilter,
|
||||||
parse_yaml_or_json)
|
parse_yaml_or_json, ignore_inventory_computed_fields, ignore_inventory_group_removal)
|
||||||
from awx.main.utils.reload import restart_local_services, stop_local_services
|
from awx.main.utils.reload import restart_local_services, stop_local_services
|
||||||
from awx.main.utils.handlers import configure_external_logger
|
from awx.main.utils.handlers import configure_external_logger
|
||||||
from awx.main.consumers import emit_channel_notification
|
from awx.main.consumers import emit_channel_notification
|
||||||
@@ -356,6 +356,23 @@ def update_host_smart_inventory_memberships():
|
|||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
|
@task(queue='tower')
|
||||||
|
def delete_inventory(inventory_id):
|
||||||
|
i = Inventory.objects.filter(id=inventory_id)
|
||||||
|
if not i.exists():
|
||||||
|
logger.error("Delete Inventory failed due to missing inventory: " + str(inventory_id))
|
||||||
|
return
|
||||||
|
i = i[0]
|
||||||
|
with ignore_inventory_computed_fields(), \
|
||||||
|
ignore_inventory_group_removal():
|
||||||
|
i.delete()
|
||||||
|
emit_channel_notification(
|
||||||
|
'inventories-status_changed',
|
||||||
|
{'group_name': 'inventories', 'inventory_id': inventory_id, 'status': 'deleted'}
|
||||||
|
)
|
||||||
|
logger.debug('Deleted inventory: %s' % inventory_id)
|
||||||
|
|
||||||
|
|
||||||
class BaseTask(Task):
|
class BaseTask(Task):
|
||||||
name = None
|
name = None
|
||||||
model = None
|
model = None
|
||||||
|
|||||||
Reference in New Issue
Block a user