mirror of
https://github.com/ansible/awx.git
synced 2026-03-19 18:07:33 -02:30
Prevent duplicating instance links
In receptor address post-save method: - Fixed detecting if address was missing a link from control nodes - Use InstanceLink create_or_update to prevent adding duplicate InstanceLink source and target peers In instance serializer create_or_update, delete receptor addresses first before doing instance create or update. This ensures that we don't trigger unnecessary post-save methods that might attempt to manipulate receptor addresses that will just be removed later. Signed-off-by: Seth Foster <fosterbseth@gmail.com>
This commit is contained in:
@@ -5598,27 +5598,32 @@ class InstanceSerializer(BaseSerializer):
|
|||||||
|
|
||||||
def create_or_update(self, validated_data, obj=None, create=True):
|
def create_or_update(self, validated_data, obj=None, create=True):
|
||||||
# create a managed receptor address if listener port is defined
|
# create a managed receptor address if listener port is defined
|
||||||
kwargs = dict()
|
port = validated_data.pop('listener_port', -1)
|
||||||
if 'listener_port' in validated_data:
|
peers_from_control_nodes = validated_data.pop('peers_from_control_nodes', -1)
|
||||||
kwargs['port'] = validated_data.pop('listener_port')
|
|
||||||
if 'peers_from_control_nodes' in validated_data:
|
# delete the receptor address if the port is explicitly set to None
|
||||||
kwargs['peers_from_control_nodes'] = validated_data.pop('peers_from_control_nodes')
|
if obj and port == None:
|
||||||
|
obj.receptor_addresses.filter(address=obj.hostname).delete()
|
||||||
|
|
||||||
if create:
|
if create:
|
||||||
instance = super(InstanceSerializer, self).create(validated_data)
|
instance = super(InstanceSerializer, self).create(validated_data)
|
||||||
else:
|
else:
|
||||||
instance = super(InstanceSerializer, self).update(obj, validated_data)
|
instance = super(InstanceSerializer, self).update(obj, validated_data)
|
||||||
|
instance.refresh_from_db() # instance canonical address lookup is deferred, so needs to be reloaded
|
||||||
|
|
||||||
# delete the receptor address if the port is expolisitly set to None
|
|
||||||
if 'port' in kwargs and not kwargs['port']:
|
|
||||||
instance.receptor_addresses.filter(address=instance.hostname).delete()
|
|
||||||
# only create or update if port is defined in validated_data or already exists in the
|
# only create or update if port is defined in validated_data or already exists in the
|
||||||
# canonical address
|
# canonical address
|
||||||
# this prevents creating a receptor address if peers_from_control_nodes is in
|
# this prevents creating a receptor address if peers_from_control_nodes is in
|
||||||
# validated_data but a port is not set
|
# validated_data but a port is not set
|
||||||
elif kwargs and ('port' in kwargs or instance.canonical_address_port):
|
if (port != None and port != -1) or instance.canonical_address_port:
|
||||||
kwargs['canonical'] = True
|
kwargs = {}
|
||||||
instance.receptor_addresses.update_or_create(address=instance.hostname, defaults=kwargs)
|
if port != -1:
|
||||||
|
kwargs['port'] = port
|
||||||
|
if peers_from_control_nodes != -1:
|
||||||
|
kwargs['peers_from_control_nodes'] = peers_from_control_nodes
|
||||||
|
if kwargs:
|
||||||
|
kwargs['canonical'] = True
|
||||||
|
instance.receptor_addresses.update_or_create(address=instance.hostname, defaults=kwargs)
|
||||||
|
|
||||||
return instance
|
return instance
|
||||||
|
|
||||||
|
|||||||
@@ -522,13 +522,14 @@ def receptor_address_saved(sender, instance, **kwargs):
|
|||||||
|
|
||||||
control_instances = set(Instance.objects.filter(node_type__in=[Instance.Types.CONTROL, Instance.Types.HYBRID]))
|
control_instances = set(Instance.objects.filter(node_type__in=[Instance.Types.CONTROL, Instance.Types.HYBRID]))
|
||||||
if address.peers_from_control_nodes:
|
if address.peers_from_control_nodes:
|
||||||
# FIXME: you ought to be able to have more connections than just the control instances
|
# if control_instances is not a subset of current peers of address, then
|
||||||
if set(address.peers_from.all()) != control_instances:
|
# that means we need to add some InstanceLinks
|
||||||
|
if not control_instances <= set(address.peers_from.all()):
|
||||||
with disable_activity_stream():
|
with disable_activity_stream():
|
||||||
address.peers_from.add(*control_instances)
|
for control_instance in control_instances:
|
||||||
|
InstanceLink.objects.update_or_create(source=control_instance, target=address)
|
||||||
schedule_write_receptor_config()
|
schedule_write_receptor_config()
|
||||||
else:
|
else:
|
||||||
# FIXME: you shouldn't unconditionally remove every peer when disabling peers_from_control_nodes
|
|
||||||
if address.peers_from.exists():
|
if address.peers_from.exists():
|
||||||
with disable_activity_stream():
|
with disable_activity_stream():
|
||||||
address.peers_from.remove(*control_instances)
|
address.peers_from.remove(*control_instances)
|
||||||
|
|||||||
Reference in New Issue
Block a user