diff --git a/awx/main/managers.py b/awx/main/managers.py index b91bda42bd..7b9164ef32 100644 --- a/awx/main/managers.py +++ b/awx/main/managers.py @@ -12,9 +12,10 @@ from awx.main.utils.pglock import advisory_lock from awx.main.utils.common import get_capacity_type from awx.main.constants import RECEPTOR_PENDING -___all__ = ['HostManager', 'InstanceManager', 'InstanceGroupManager', 'DeferJobCreatedManager'] +___all__ = ['HostManager', 'InstanceManager', 'InstanceGroupManager', 'DeferJobCreatedManager', 'UUID_DEFAULT'] logger = logging.getLogger('awx.main.managers') +UUID_DEFAULT = '00000000-0000-0000-0000-000000000000' class DeferJobCreatedManager(models.Manager): @@ -105,7 +106,7 @@ class InstanceManager(models.Manager): """Return the currently active instance.""" # If we are running unit tests, return a stub record. if settings.IS_TESTING(sys.argv) or hasattr(sys, '_called_from_test'): - return self.model(id=1, hostname=settings.CLUSTER_HOST_ID, uuid='00000000-0000-0000-0000-000000000000') + return self.model(id=1, hostname=settings.CLUSTER_HOST_ID, uuid=UUID_DEFAULT) node = self.filter(hostname=settings.CLUSTER_HOST_ID) if node.exists(): @@ -115,6 +116,7 @@ class InstanceManager(models.Manager): def register(self, uuid=None, hostname=None, ip_address=None, node_type='hybrid', defaults=None): if not hostname: hostname = settings.CLUSTER_HOST_ID + with advisory_lock('instance_registration_%s' % hostname): if settings.AWX_AUTO_DEPROVISION_INSTANCES: # detect any instances with the same IP address. @@ -127,14 +129,25 @@ class InstanceManager(models.Manager): other_inst.save(update_fields=['ip_address']) logger.warning("IP address {0} conflict detected, ip address unset for host {1}.".format(ip_address, other_hostname)) - # Return existing instance that matches hostname - instance = self.filter(hostname=hostname) + # Return existing instance that matches hostname or UUID (default to UUID) + if uuid is not None and uuid != UUID_DEFAULT and self.filter(uuid=uuid).exists(): + instance = self.filter(uuid=uuid) + else: + # if instance was not retrieved by uuid and hostname was, use the hostname + instance = self.filter(hostname=hostname) + + # Return existing instance if instance.exists(): - instance = instance.get() + instance = instance.first() # in the unusual occasion that there is more than one, only get one update_fields = [] + # if instance was retrieved by uuid and hostname has changed, update hostname + if instance.hostname != hostname: + logger.warning("passed in hostname {0} is different from the original hostname {1}, updating to {0}".format(hostname, instance.hostname)) + instance.hostname = hostname + update_fields.append('hostname') + # if any other fields are to be updated if instance.ip_address != ip_address: instance.ip_address = ip_address - update_fields.append('ip_address') if instance.node_type != node_type: instance.node_type = node_type update_fields.append('node_type') diff --git a/awx/main/models/ha.py b/awx/main/models/ha.py index 0b75e4a964..d2686708e5 100644 --- a/awx/main/models/ha.py +++ b/awx/main/models/ha.py @@ -18,7 +18,7 @@ from solo.models import SingletonModel from awx import __version__ as awx_application_version from awx.api.versioning import reverse -from awx.main.managers import InstanceManager, InstanceGroupManager +from awx.main.managers import InstanceManager, InstanceGroupManager, UUID_DEFAULT from awx.main.fields import JSONField from awx.main.models.base import BaseModel, HasEditsMixin, prevent_search from awx.main.models.unified_jobs import UnifiedJob @@ -59,7 +59,7 @@ class Instance(HasPolicyEditsMixin, BaseModel): objects = InstanceManager() # Fields set in instance registration - uuid = models.CharField(max_length=40, default='00000000-0000-0000-0000-000000000000') + uuid = models.CharField(max_length=40, default=UUID_DEFAULT) hostname = models.CharField(max_length=250, unique=True) ip_address = models.CharField( blank=True,