mirror of
https://github.com/ansible/awx.git
synced 2026-04-10 12:39:22 -02:30
create lock for perform_update
* perform_update can be called from either awx-manage or the RunInventoryUpdate task * need to make sure that the inventory updates that happen with perform_update are atomic
This commit is contained in:
@@ -863,68 +863,69 @@ class Command(BaseCommand):
|
|||||||
self.inventory_update.save(update_fields=['org_host_limit_error'])
|
self.inventory_update.save(update_fields=['org_host_limit_error'])
|
||||||
|
|
||||||
def handle(self, *args, **options):
|
def handle(self, *args, **options):
|
||||||
# Load inventory and related objects from database.
|
with advisory_lock('inventory_{}_import'.format(self.inventory.id)):
|
||||||
inventory_name = options.get('inventory_name', None)
|
# Load inventory and related objects from database.
|
||||||
inventory_id = options.get('inventory_id', None)
|
inventory_name = options.get('inventory_name', None)
|
||||||
if inventory_name and inventory_id:
|
inventory_id = options.get('inventory_id', None)
|
||||||
raise CommandError('--inventory-name and --inventory-id are mutually exclusive')
|
if inventory_name and inventory_id:
|
||||||
elif not inventory_name and not inventory_id:
|
raise CommandError('--inventory-name and --inventory-id are mutually exclusive')
|
||||||
raise CommandError('--inventory-name or --inventory-id is required')
|
elif not inventory_name and not inventory_id:
|
||||||
|
raise CommandError('--inventory-name or --inventory-id is required')
|
||||||
|
|
||||||
# Obtain rest of the options needed to run update
|
# Obtain rest of the options needed to run update
|
||||||
raw_source = options.get('source', None)
|
raw_source = options.get('source', None)
|
||||||
if not raw_source:
|
if not raw_source:
|
||||||
raise CommandError('--source is required')
|
raise CommandError('--source is required')
|
||||||
verbosity = int(options.get('verbosity', 1))
|
verbosity = int(options.get('verbosity', 1))
|
||||||
self.set_logging_level(verbosity)
|
self.set_logging_level(verbosity)
|
||||||
venv_path = options.get('venv', None)
|
venv_path = options.get('venv', None)
|
||||||
|
|
||||||
# Load inventory object based on name or ID.
|
# Load inventory object based on name or ID.
|
||||||
if inventory_id:
|
if inventory_id:
|
||||||
q = dict(id=inventory_id)
|
q = dict(id=inventory_id)
|
||||||
else:
|
else:
|
||||||
q = dict(name=inventory_name)
|
q = dict(name=inventory_name)
|
||||||
try:
|
try:
|
||||||
inventory = Inventory.objects.get(**q)
|
inventory = Inventory.objects.get(**q)
|
||||||
except Inventory.DoesNotExist:
|
except Inventory.DoesNotExist:
|
||||||
raise CommandError('Inventory with %s = %s cannot be found' % list(q.items())[0])
|
raise CommandError('Inventory with %s = %s cannot be found' % list(q.items())[0])
|
||||||
except Inventory.MultipleObjectsReturned:
|
except Inventory.MultipleObjectsReturned:
|
||||||
raise CommandError('Inventory with %s = %s returned multiple results' % list(q.items())[0])
|
raise CommandError('Inventory with %s = %s returned multiple results' % list(q.items())[0])
|
||||||
logger.info('Updating inventory %d: %s' % (inventory.pk, inventory.name))
|
logger.info('Updating inventory %d: %s' % (inventory.pk, inventory.name))
|
||||||
|
|
||||||
|
|
||||||
# Create ad-hoc inventory source and inventory update objects
|
# Create ad-hoc inventory source and inventory update objects
|
||||||
with ignore_inventory_computed_fields():
|
with ignore_inventory_computed_fields():
|
||||||
source = Command.get_source_absolute_path(raw_source)
|
source = Command.get_source_absolute_path(raw_source)
|
||||||
|
|
||||||
inventory_source, created = InventorySource.objects.get_or_create(
|
inventory_source, created = InventorySource.objects.get_or_create(
|
||||||
inventory=inventory,
|
inventory=inventory,
|
||||||
source='file',
|
source='file',
|
||||||
source_path=os.path.abspath(source),
|
source_path=os.path.abspath(source),
|
||||||
overwrite=bool(options.get('overwrite', False)),
|
overwrite=bool(options.get('overwrite', False)),
|
||||||
overwrite_vars=bool(options.get('overwrite_vars', False)),
|
overwrite_vars=bool(options.get('overwrite_vars', False)),
|
||||||
)
|
)
|
||||||
inventory_update = inventory_source.create_inventory_update(
|
inventory_update = inventory_source.create_inventory_update(
|
||||||
_eager_fields=dict(
|
_eager_fields=dict(
|
||||||
job_args=json.dumps(sys.argv),
|
job_args=json.dumps(sys.argv),
|
||||||
job_env=dict(os.environ.items()),
|
job_env=dict(os.environ.items()),
|
||||||
job_cwd=os.getcwd())
|
job_cwd=os.getcwd())
|
||||||
)
|
)
|
||||||
|
|
||||||
data = AnsibleInventoryLoader(
|
data = AnsibleInventoryLoader(
|
||||||
source=source, venv_path=venv_path, verbosity=verbosity
|
source=source, venv_path=venv_path, verbosity=verbosity
|
||||||
).load()
|
).load()
|
||||||
|
|
||||||
logger.debug('Finished loading from source: %s', source)
|
logger.debug('Finished loading from source: %s', source)
|
||||||
status, tb, exc = self.perform_update(options, data, inventory_update)
|
status, tb, exc = self.perform_update(options, data, inventory_update)
|
||||||
|
|
||||||
with ignore_inventory_computed_fields():
|
with ignore_inventory_computed_fields():
|
||||||
inventory_update = InventoryUpdate.objects.get(pk=inventory_update.pk)
|
inventory_update = InventoryUpdate.objects.get(pk=inventory_update.pk)
|
||||||
inventory_update.result_traceback = tb
|
inventory_update.result_traceback = tb
|
||||||
inventory_update.status = status
|
inventory_update.status = status
|
||||||
inventory_update.save(update_fields=['status', 'result_traceback'])
|
inventory_update.save(update_fields=['status', 'result_traceback'])
|
||||||
inventory_source.status = status
|
inventory_source.status = status
|
||||||
inventory_source.save(update_fields=['status'])
|
inventory_source.save(update_fields=['status'])
|
||||||
|
|
||||||
if exc:
|
if exc:
|
||||||
logger.error(str(exc))
|
logger.error(str(exc))
|
||||||
@@ -966,7 +967,12 @@ class Command(BaseCommand):
|
|||||||
raise CommandError('invalid regular expression for --host-filter')
|
raise CommandError('invalid regular expression for --host-filter')
|
||||||
|
|
||||||
begin = time.time()
|
begin = time.time()
|
||||||
with advisory_lock('inventory_{}_update'.format(self.inventory.id)):
|
|
||||||
|
# Since perform_update can be invoked either through the awx-manage CLI
|
||||||
|
# or from the task system, we need to create a new lock at this level
|
||||||
|
# (even though inventory_import.Command.handle -- which calls
|
||||||
|
# perform_update -- has its own lock, inventory_ID_import)
|
||||||
|
with advisory_lock('inventory_{}_perform_update'.format(self.inventory.id)):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.check_license()
|
self.check_license()
|
||||||
|
|||||||
Reference in New Issue
Block a user