diff --git a/awx/api/urls/host_metric.py b/awx/api/urls/host_metric.py index d464fb82c5..a5e43fefbc 100644 --- a/awx/api/urls/host_metric.py +++ b/awx/api/urls/host_metric.py @@ -5,6 +5,6 @@ from django.urls import re_path from awx.api.views import HostMetricList, HostMetricDetail -urls = [re_path(r'$^', HostMetricList.as_view(), name='host_metric_list'), re_path(r'^(?P[0-9]+)/$', HostMetricDetail.as_view(), name='host_metric_detail')] +urls = [re_path(r'^$', HostMetricList.as_view(), name='host_metric_list'), re_path(r'^(?P[0-9]+)/$', HostMetricDetail.as_view(), name='host_metric_detail')] __all__ = ['urls'] diff --git a/awx/api/views/__init__.py b/awx/api/views/__init__.py index 0dd0f306cd..d05806afb1 100644 --- a/awx/api/views/__init__.py +++ b/awx/api/views/__init__.py @@ -1556,6 +1556,9 @@ class HostMetricList(ListAPIView): permission_classes = (IsSystemAdminOrAuditor,) search_fields = ('hostname', 'deleted') + def get_queryset(self): + return self.model.objects.all() + class HostMetricDetail(RetrieveDestroyAPIView): name = _("Host Metric Detail") @@ -1572,13 +1575,13 @@ class HostMetricDetail(RetrieveDestroyAPIView): class HostMetricSummaryMonthlyList(ListAPIView): name = _("Host Metrics Summary Monthly") model = models.HostMetricSummaryMonthly - permission_classes = (IsSystemAdminOrAuditor,) serializer_class = serializers.HostMetricSummaryMonthlySerializer + permission_classes = (IsSystemAdminOrAuditor,) search_fields = ('date',) filter_backends = [HostMetricSummaryMonthlyFieldLookupBackend] def get_queryset(self): - queryset = super().get_queryset() + queryset = self.model.objects.all() past_months = self.request.query_params.get('past_months', None) date_from = self._get_date_from(past_months) diff --git a/awx/api/views/root.py b/awx/api/views/root.py index 7b4eb8191e..f343d8169d 100644 --- a/awx/api/views/root.py +++ b/awx/api/views/root.py @@ -102,6 +102,8 @@ class ApiVersionRootView(APIView): data['inventory_updates'] = reverse('api:inventory_update_list', request=request) data['groups'] = reverse('api:group_list', request=request) data['hosts'] = reverse('api:host_list', request=request) + data['host_metrics'] = reverse('api:host_metric_list', request=request) + data['host_metric_summary_monthly'] = reverse('api:host_metric_summary_monthly_list', request=request) data['job_templates'] = reverse('api:job_template_list', request=request) data['jobs'] = reverse('api:job_list', request=request) data['ad_hoc_commands'] = reverse('api:ad_hoc_command_list', request=request) diff --git a/awx/main/access.py b/awx/main/access.py index 5cca1ff133..5d51ab3b91 100644 --- a/awx/main/access.py +++ b/awx/main/access.py @@ -37,8 +37,6 @@ from awx.main.models import ( ExecutionEnvironment, Group, Host, - HostMetric, - HostMetricSummaryMonthly, Instance, InstanceGroup, Inventory, @@ -885,61 +883,6 @@ class OrganizationAccess(NotificationAttachMixin, BaseAccess): return super(OrganizationAccess, self).can_attach(obj, sub_obj, relationship, *args, **kwargs) -class HostMetricAccess(BaseAccess): - """ - - I can see host metrics when I'm a super user or system auditor. - - I can delete host metrics when I'm a super user. - """ - - model = HostMetric - - def get_queryset(self): - if self.user.is_superuser or self.user.is_system_auditor: - qs = self.model.objects.all() - else: - qs = self.filtered_queryset() - return qs - - def can_read(self, obj): - return bool(self.user.is_superuser or self.user.is_system_auditor or (obj and obj.user == self.user)) - - def can_add(self, data): - return False # There is no API endpoint to POST new settings. - - def can_change(self, obj, data): - return False - - def can_delete(self, obj): - return bool(self.user.is_superuser or (obj and obj.user == self.user)) - - -class HostMetricSummaryMonthlyAccess(BaseAccess): - """ - - I can see host metrics when I'm a super user or system auditor. - """ - - model = HostMetricSummaryMonthly - - def get_queryset(self): - if self.user.is_superuser or self.user.is_system_auditor: - qs = self.model.objects.all() - else: - qs = self.filtered_queryset() - return qs - - def can_read(self, obj): - return bool(self.user.is_superuser or self.user.is_system_auditor or (obj and obj.user == self.user)) - - def can_add(self, data): - return False # There is no API endpoint to POST new settings. - - def can_change(self, obj, data): - return False - - def can_delete(self, obj): - return False - - class InventoryAccess(BaseAccess): """ I can see inventory when: diff --git a/awx/main/migrations/0175_add_hostmetric_fields.py b/awx/main/migrations/0175_add_hostmetric_fields.py index d273a6b6ea..ee91b01fbb 100644 --- a/awx/main/migrations/0175_add_hostmetric_fields.py +++ b/awx/main/migrations/0175_add_hostmetric_fields.py @@ -18,12 +18,12 @@ class Migration(migrations.Migration): migrations.AddField( model_name='hostmetric', name='automated_counter', - field=models.BigIntegerField(default=0, help_text='How many times was the host automated'), + field=models.IntegerField(default=0, help_text='How many times was the host automated'), ), migrations.AddField( model_name='hostmetric', name='deleted_counter', - field=models.BigIntegerField(default=0, help_text='How many times was the host deleted'), + field=models.IntegerField(default=0, help_text='How many times was the host deleted'), ), migrations.AddField( model_name='hostmetric', @@ -35,7 +35,7 @@ class Migration(migrations.Migration): migrations.AddField( model_name='hostmetric', name='used_in_inventories', - field=models.BigIntegerField(null=True, help_text='How many inventories contain this host'), + field=models.IntegerField(null=True, help_text='How many inventories contain this host'), ), migrations.AddField( model_name='hostmetric', name='id', field=models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID') diff --git a/awx/main/migrations/0176_hostmetricsummarymonthly.py b/awx/main/migrations/0176_hostmetricsummarymonthly.py index 735f46f0d6..7631363a4c 100644 --- a/awx/main/migrations/0176_hostmetricsummarymonthly.py +++ b/awx/main/migrations/0176_hostmetricsummarymonthly.py @@ -18,15 +18,15 @@ class Migration(migrations.Migration): ('license_capacity', models.BigIntegerField(default=0, help_text="'License capacity as max. number of unique hosts")), ( 'hosts_added', - models.BigIntegerField(default=0, help_text='How many hosts were added in the associated month, consuming more license capacity'), + models.IntegerField(default=0, help_text='How many hosts were added in the associated month, consuming more license capacity'), ), ( 'hosts_deleted', - models.BigIntegerField(default=0, help_text='How many hosts were deleted in the associated month, freeing the license capacity'), + models.IntegerField(default=0, help_text='How many hosts were deleted in the associated month, freeing the license capacity'), ), ( 'indirectly_managed_hosts', - models.BigIntegerField(default=0, help_text='Manually entered number indirectly managed hosts for a certain month'), + models.IntegerField(default=0, help_text='Manually entered number indirectly managed hosts for a certain month'), ), ], ), diff --git a/awx/main/models/events.py b/awx/main/models/events.py index 0ba07185f4..2d6dee6f61 100644 --- a/awx/main/models/events.py +++ b/awx/main/models/events.py @@ -6,7 +6,7 @@ from collections import defaultdict from django.conf import settings from django.core.exceptions import ObjectDoesNotExist -from django.db import connection, models, DatabaseError +from django.db import models, DatabaseError from django.utils.dateparse import parse_datetime from django.utils.text import Truncator from django.utils.timezone import utc, now @@ -585,7 +585,7 @@ class JobEvent(BasePlaybookEvent): # bulk-create current_time = now() HostMetric.objects.bulk_create( - [HostMetric(hostname=hostname, last_automation=current_time) for hostname in updated_hosts_list], ignore_conflicts=True, batch_size=1000 + [HostMetric(hostname=hostname, last_automation=current_time) for hostname in updated_hosts_list], ignore_conflicts=True, batch_size=100 ) # bulk-update batch_start, batch_size = 0, 1000 diff --git a/awx/main/models/inventory.py b/awx/main/models/inventory.py index c937c4342d..56dea84d96 100644 --- a/awx/main/models/inventory.py +++ b/awx/main/models/inventory.py @@ -824,12 +824,12 @@ class HostMetric(models.Model): first_automation = models.DateTimeField(auto_now_add=True, null=False, db_index=True, help_text=_('When the host was first automated against')) last_automation = models.DateTimeField(db_index=True, help_text=_('When the host was last automated against')) last_deleted = models.DateTimeField(null=True, db_index=True, help_text=_('When the host was last deleted')) - automated_counter = models.BigIntegerField(default=0, help_text=_('How many times was the host automated')) - deleted_counter = models.BigIntegerField(default=0, help_text=_('How many times was the host deleted')) + automated_counter = models.IntegerField(default=0, help_text=_('How many times was the host automated')) + deleted_counter = models.IntegerField(default=0, help_text=_('How many times was the host deleted')) deleted = models.BooleanField( default=False, help_text=_('Boolean flag saying whether the host is deleted and therefore not counted into the subscription consumption') ) - used_in_inventories = models.BigIntegerField(null=True, help_text=_('How many inventories contain this host')) + used_in_inventories = models.IntegerField(null=True, help_text=_('How many inventories contain this host')) objects = models.Manager() active_objects = HostMetricActiveManager() @@ -842,12 +842,12 @@ class HostMetric(models.Model): self.deleted_counter = (self.deleted_counter or 0) + 1 self.last_deleted = now() self.deleted = True - self.save() + self.save(update_fields=['deleted', 'deleted_counter', 'last_deleted']) def soft_restore(self): if self.deleted: self.deleted = False - self.save() + self.save(update_fields=['deleted']) class HostMetricSummaryMonthly(models.Model): @@ -858,9 +858,9 @@ class HostMetricSummaryMonthly(models.Model): date = models.DateField(unique=True) license_consumed = models.BigIntegerField(default=0, help_text=_("How much unique hosts are consumed from the license")) license_capacity = models.BigIntegerField(default=0, help_text=_("'License capacity as max. number of unique hosts")) - hosts_added = models.BigIntegerField(default=0, help_text=_("How many hosts were added in the associated month, consuming more license capacity")) - hosts_deleted = models.BigIntegerField(default=0, help_text=_("How many hosts were deleted in the associated month, freeing the license capacity")) - indirectly_managed_hosts = models.BigIntegerField(default=0, help_text=("Manually entered number indirectly managed hosts for a certain month")) + hosts_added = models.IntegerField(default=0, help_text=_("How many hosts were added in the associated month, consuming more license capacity")) + hosts_deleted = models.IntegerField(default=0, help_text=_("How many hosts were deleted in the associated month, freeing the license capacity")) + indirectly_managed_hosts = models.IntegerField(default=0, help_text=("Manually entered number indirectly managed hosts for a certain month")) class InventorySourceOptions(BaseModel):