1
0
mirror of https://github.com/ansible/awx.git synced 2024-10-27 17:55:10 +03:00

Add smart_inventories endpoint to Host

This commit is contained in:
Wayne Witzel III 2017-05-26 10:10:31 -04:00
parent 5232b70897
commit e28cd97ffb
8 changed files with 92 additions and 7 deletions

View File

@ -1204,6 +1204,7 @@ class HostSerializer(BaseSerializerWithVariables):
job_host_summaries = self.reverse('api:host_job_host_summaries_list', kwargs={'pk': obj.pk}),
activity_stream = self.reverse('api:host_activity_stream_list', kwargs={'pk': obj.pk}),
inventory_sources = self.reverse('api:host_inventory_sources_list', kwargs={'pk': obj.pk}),
smart_inventories = self.reverse('api:host_smart_inventories_list', kwargs={'pk': obj.pk}),
ad_hoc_commands = self.reverse('api:host_ad_hoc_commands_list', kwargs={'pk': obj.pk}),
ad_hoc_command_events = self.reverse('api:host_ad_hoc_command_events_list', kwargs={'pk': obj.pk}),
fact_versions = self.reverse('api:host_fact_versions_list', kwargs={'pk': obj.pk}),

View File

@ -115,6 +115,7 @@ host_urls = patterns('awx.api.views',
url(r'^(?P<pk>[0-9]+)/job_host_summaries/$', 'host_job_host_summaries_list'),
url(r'^(?P<pk>[0-9]+)/activity_stream/$', 'host_activity_stream_list'),
url(r'^(?P<pk>[0-9]+)/inventory_sources/$', 'host_inventory_sources_list'),
url(r'^(?P<pk>[0-9]+)/smart_inventories/$', 'host_smart_inventories_list'),
url(r'^(?P<pk>[0-9]+)/ad_hoc_commands/$', 'host_ad_hoc_commands_list'),
url(r'^(?P<pk>[0-9]+)/ad_hoc_command_events/$', 'host_ad_hoc_command_events_list'),
#url(r'^(?P<pk>[0-9]+)/single_fact/$', 'host_single_fact_view'),

View File

@ -58,7 +58,7 @@ import ansiconv
from social.backends.utils import load_backends
# AWX
from awx.main.tasks import send_notifications
from awx.main.tasks import send_notifications, update_host_smart_inventory_memberships
from awx.main.access import get_user_queryset
from awx.main.ha import is_ha_environment
from awx.api.authentication import TaskAuthentication, TokenGetAuthentication
@ -2006,6 +2006,22 @@ class HostInventorySourcesList(SubListAPIView):
new_in_148 = True
class HostSmartInventoriesList(SubListAPIView):
model = Inventory
serializer_class = InventorySerializer
parent_model = Host
relationship = 'smart_inventories'
new_in_320 = True
def list(self, *args, **kwargs):
try:
if settings.AWX_REBUILD_SMART_MEMBERSHIP:
update_host_smart_inventory_memberships.delay()
return super(HostSmartInventoriesList, self).list(*args, **kwargs)
except Exception as e:
return Response(dict(error=_(unicode(e))), status=status.HTTP_400_BAD_REQUEST)
class HostActivityStreamList(ActivityStreamEnforcementMixin, SubListAPIView):
model = ActivityStream

View File

@ -36,6 +36,8 @@ class Migration(migrations.Migration):
name='inventory',
field=models.ForeignKey(related_name='inventory_sources', default=None, to='main.Inventory', null=True),
),
# Smart Inventory
migrations.AddField(
model_name='inventory',
name='host_filter',
@ -44,7 +46,28 @@ class Migration(migrations.Migration):
migrations.AddField(
model_name='inventory',
name='kind',
field=models.CharField(default=b'', help_text='Kind of inventory being represented.', max_length=32, choices=[(b'', 'Hosts have a direct link to this inventory.'), (b'smart', 'Hosts for inventory generated using the host_filter property.')]),
field=models.CharField(default=b'', help_text='Kind of inventory being represented.', max_length=32, blank=True, choices=[(b'', 'Hosts have a direct link to this inventory.'), (b'smart', 'Hosts for inventory generated using the host_filter property.')]),
),
migrations.CreateModel(
name='SmartInventoryMembership',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('host', models.ForeignKey(related_name='+', to='main.Host')),
],
),
migrations.AddField(
model_name='smartinventorymembership',
name='inventory',
field=models.ForeignKey(related_name='+', to='main.Inventory'),
),
migrations.AddField(
model_name='host',
name='smart_inventories',
field=models.ManyToManyField(related_name='_host_smart_inventories_+', through='main.SmartInventoryMembership', to='main.Inventory'),
),
migrations.AlterUniqueTogether(
name='smartinventorymembership',
unique_together=set([('host', 'inventory')]),
),
# Facts

View File

@ -36,7 +36,8 @@ from awx.main.models.notifications import (
)
from awx.main.utils import _inventory_updates
__all__ = ['Inventory', 'Host', 'Group', 'InventorySource', 'InventoryUpdate', 'CustomInventoryScript']
__all__ = ['Inventory', 'Host', 'Group', 'InventorySource', 'InventoryUpdate',
'CustomInventoryScript', 'SmartInventoryMembership']
logger = logging.getLogger('awx.main.models.inventory')
@ -346,6 +347,19 @@ class Inventory(CommonModelNameNotUnique, ResourceMixin):
return self.groups.exclude(parents__pk__in=group_pks).distinct()
class SmartInventoryMembership(BaseModel):
'''
A lookup table for Host membership in Smart Inventory
'''
class Meta:
app_label = 'main'
unique_together = (('host', 'inventory'),)
inventory = models.ForeignKey('Inventory', related_name='+', on_delete=models.CASCADE)
host = models.ForeignKey('Host', related_name='+', on_delete=models.CASCADE)
class Host(CommonModelNameNotUnique):
'''
A managed node
@ -361,6 +375,11 @@ class Host(CommonModelNameNotUnique):
related_name='hosts',
on_delete=models.CASCADE,
)
smart_inventories = models.ManyToManyField(
'Inventory',
related_name='+',
through='SmartInventoryMembership',
)
enabled = models.BooleanField(
default=True,
help_text=_('Is this host online and available for running jobs?'),

View File

@ -38,7 +38,7 @@ from celery.signals import celeryd_init, worker_process_init
# Django
from django.conf import settings
from django.db import transaction, DatabaseError
from django.db import transaction, DatabaseError, IntegrityError
from django.utils.timezone import now
from django.utils.encoding import smart_str
from django.core.mail import send_mail
@ -62,8 +62,8 @@ from awx.main.utils.handlers import configure_external_logger
from awx.main.consumers import emit_channel_notification
__all__ = ['RunJob', 'RunSystemJob', 'RunProjectUpdate', 'RunInventoryUpdate',
'RunAdHocCommand', 'handle_work_error',
'handle_work_success', 'update_inventory_computed_fields',
'RunAdHocCommand', 'handle_work_error', 'handle_work_success',
'update_inventory_computed_fields', 'update_host_smart_inventory_memberships',
'send_notifications', 'run_administrative_checks', 'purge_old_stdout_files']
HIDDEN_PASSWORD = '**********'
@ -321,6 +321,22 @@ def update_inventory_computed_fields(inventory_id, should_update_hosts=True):
i.update_computed_fields(update_hosts=should_update_hosts)
@task(queue='tower')
def update_host_smart_inventory_memberships():
try:
with transaction.atomic():
smart_inventories = Inventory.objects.filter(kind='smart', host_filter__isnull=False)
SmartInventoryMembership.objects.all().delete()
memberships = []
for smart_inventory in smart_inventories:
memberships.extend([SmartInventoryMembership(inventory_id=smart_inventory.id, host_id=host_id[0])
for host_id in smart_inventory.hosts.values_list('id')])
SmartInventoryMembership.objects.bulk_create(memberships)
except IntegrityError as e:
logger.error("Update Host Smart Inventory Memberships failed due to an exception: " + str(e))
return
class BaseTask(Task):
name = None
model = None

View File

@ -568,6 +568,9 @@ AWX_TASK_ENV = {}
# Flag to enable/disable updating hosts M2M when saving job events.
CAPTURE_JOB_EVENT_HOSTS = False
# Rebuild Host Smart Inventory memberships.
AWX_REBUILD_SMART_MEMBERSHIP = False
# Enable bubblewrap support for running jobs (playbook runs only).
# Note: This setting may be overridden by database settings.
AWX_PROOT_ENABLED = True

View File

@ -23,10 +23,16 @@ in our _Smart Search_.
* The `Inventory` model has a new field called `kind`. The default of this field will be blank
for normal inventories and set to `smart` for smart inventories.
* `Inventory` model as a new field called `host_filter`. The default of this field will be blank
* `Inventory` model has a new field called `host_filter`. The default of this field will be blank
for normal inventories. When `host_filter` is set AND the inventory `kind` is set to `smart`
is the combination that makes a _Smart Inventory_.
* `Host` model has a new field called `smart_inventories`. This field uses the `SmartInventoryMemberships`
lookup table to provide a set of all of the _Smart Inventory_ a host is a part of. The memberships
or generated by the `update_host_smart_inventory_memberships` task. This task is called when the view for
`/api/v2/hosts/:id/smart_inventories` is materialized. NOTE: This task is only run if the
`AWX_REBUILD_SMART_MEMBERSHIP` is set to True. It defaults to False.
### Smart Filter (host_filter)
The `SmartFilter` class handles our translation of the smart search string. We store the
filter value in the `host_filter` field for an inventory. This value should be expressed