From f5b7d500a57aaf922818b8fe1760e222bfe62df4 Mon Sep 17 00:00:00 2001 From: Luke Sneeringer Date: Mon, 22 Sep 2014 14:57:42 -0500 Subject: [PATCH 01/33] Addition of a /ping/ endpoint to give basic HA info. --- awx/api/urls.py | 1 + awx/api/views.py | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/awx/api/urls.py b/awx/api/urls.py index 131072bc14..8baa0e17e7 100644 --- a/awx/api/urls.py +++ b/awx/api/urls.py @@ -194,6 +194,7 @@ activity_stream_urls = patterns('awx.api.views', v1_urls = patterns('awx.api.views', url(r'^$', 'api_v1_root_view'), + url(r'^ping/$', 'api_v1_ping_view'), url(r'^config/$', 'api_v1_config_view'), url(r'^authtoken/$', 'auth_token_view'), url(r'^me/$', 'user_me_list'), diff --git a/awx/api/views.py b/awx/api/views.py index 75bb53eb25..91e55ce88d 100644 --- a/awx/api/views.py +++ b/awx/api/views.py @@ -114,6 +114,27 @@ class ApiV1RootView(APIView): data['activity_stream'] = reverse('api:activity_stream_list') return Response(data) + +class ApiV1PingView(APIView): + """A simple view that reports very basic information about this Tower + instance, which is acceptable to be public information. + """ + permission_classes = (AllowAny,) + authentication_classes = () + view_name = 'Ping' + + def get(self, request, format=None): + """Return some basic information about this Tower instance. + + Everything returned here should be considered public / insecure, as + this requires no auth and is intended for use by the installer process. + """ + return Response({ + 'role': 'standalone', # FIXME: Make this dynamic. + 'version': get_awx_version(), + }) + + class ApiV1ConfigView(APIView): permission_classes = (IsAuthenticated,) From b740faeccd7ab4037a7b6698b9a3fabeda964583 Mon Sep 17 00:00:00 2001 From: Luke Sneeringer Date: Wed, 24 Sep 2014 16:29:56 -0500 Subject: [PATCH 02/33] Setup wizard adjustments. --- .gitignore | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index 2120b78f23..801b7e1110 100644 --- a/.gitignore +++ b/.gitignore @@ -49,6 +49,10 @@ pep8.txt tools/vagrant/local.yml .vagrant* +# Setup +setup/tower_setup_conf.yml +setup/setup.log + # Other .tower_cycle env/* From 072ab2118fc86b7652bbc2d4dc0409103b7d9d50 Mon Sep 17 00:00:00 2001 From: Luke Sneeringer Date: Fri, 26 Sep 2014 14:08:19 -0500 Subject: [PATCH 03/33] Instance model (for HA) --- awx/main/migrations/0055_v210_changes.py | 2 +- awx/main/models/__init__.py | 1 + awx/main/models/ha.py | 18 ++++++++++++++++++ 3 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 awx/main/models/ha.py diff --git a/awx/main/migrations/0055_v210_changes.py b/awx/main/migrations/0055_v210_changes.py index a383a1b875..c72ea2986e 100644 --- a/awx/main/migrations/0055_v210_changes.py +++ b/awx/main/migrations/0055_v210_changes.py @@ -476,4 +476,4 @@ class Migration(SchemaMigration): } } - complete_apps = ['main'] \ No newline at end of file + complete_apps = ['main'] diff --git a/awx/main/models/__init__.py b/awx/main/models/__init__.py index 2f9d583a24..2d0e8cac4e 100644 --- a/awx/main/models/__init__.py +++ b/awx/main/models/__init__.py @@ -14,6 +14,7 @@ from awx.main.models.inventory import * from awx.main.models.jobs import * from awx.main.models.schedules import * from awx.main.models.activity_stream import * +from awx.main.models.ha import * # Monkeypatch Django serializer to ignore django-taggit fields (which break # the dumpdata command; see https://github.com/alex/django-taggit/issues/155). diff --git a/awx/main/models/ha.py b/awx/main/models/ha.py new file mode 100644 index 0000000000..40a7aed12c --- /dev/null +++ b/awx/main/models/ha.py @@ -0,0 +1,18 @@ +# Copyright (c) 2014 Ansible, Inc. +# All Rights Reserved. + +from django.db import models + + +class Instance(models.Model): + """A model representing an Ansible Tower instance, primary or secondary, + running against this database. + """ + uuid = models.CharField(max_length=40) + primary = models.BooleanField(default=False) + created = models.DateTimeField(auto_now_add=True) + modified = models.DateTimeField(auto_now=True) + + class Meta: + app_label = 'main' + From 35c6c72f2ebcddd71e613ade1ead7f32143f28cc Mon Sep 17 00:00:00 2001 From: Luke Sneeringer Date: Mon, 29 Sep 2014 14:11:10 -0500 Subject: [PATCH 04/33] Add Instance.role property. --- awx/main/models/ha.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/awx/main/models/ha.py b/awx/main/models/ha.py index 40a7aed12c..a277124cd4 100644 --- a/awx/main/models/ha.py +++ b/awx/main/models/ha.py @@ -16,3 +16,9 @@ class Instance(models.Model): class Meta: app_label = 'main' + @property + def role(self): + """Return the role of this instance, as a string.""" + if self.primary: + return 'primary' + return 'secondary' From 3e2cf3acb31b8d097fdd70823245b90cca10626d Mon Sep 17 00:00:00 2001 From: Luke Sneeringer Date: Mon, 29 Sep 2014 14:44:35 -0500 Subject: [PATCH 05/33] Beginning work on instance registration, sanity checks. --- .../management/commands/register_instance.py | 71 +++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 awx/main/management/commands/register_instance.py diff --git a/awx/main/management/commands/register_instance.py b/awx/main/management/commands/register_instance.py new file mode 100644 index 0000000000..560b8c2f14 --- /dev/null +++ b/awx/main/management/commands/register_instance.py @@ -0,0 +1,71 @@ +# Copyright (c) 2014 Ansible, Inc. +# All Rights Reserved + +from optparse import make_option + +from django.conf import settings +from django.core.management.base import BaseCommand, CommandError + +from awx.main.models import Instance + + +class Command(BaseCommand): + """Regsiter this instance with the database for HA tracking. + + This command is idempotent. It will register the machine if it is not + yet present and do nothing if the machine is already registered. + + If a second primary machine is registered, the first primary machine will + become a secondary machine, and the newly registered primary machine + will be primary (unless `--timid` is provided, in which case the command + will simply error out). + + This command will also error out under the following circumstances: + + * Attempting to register a secondary machine with no primary machines. + * Attempting to register this machine with a different state than its + existing registration plus `--timid`. + """ + option_list = BaseCommand.option_list + ( + make_option('--timid', action='store_true', dest='timid'), + make_option('--primary', action='store_true', dest='primary'), + make_option('--secondary', action='store_false', dest='primary'), + ) + + def handle(self, **options): + uuid = settings.SYSTEM_UUID + + # Is there an existing record for this machine? + # If so, retrieve that record and look for issues. + try: + instance = Instance.objects.get(uuid=uuid) + existing = True + except Instance.DoesNotExist: + instance = Instance(uuid=uuid) + existing = False + + # Get a status on primary machines (excluding this one, regardless + # of its status). + other_instances = Instance.objects.exclude(uuid=uuid) + primaries = other_instances.filter(primary=True).count() + + # Sanity check: If we're supposed to be being timid, then ensure + # that there's no crazy mosh pits happening here. + # + # If the primacy setting doesn't match what is already on + # the instance, error out. + if existing and timid and instance.primary != options['primary']: + raise CommandError('This instance is already registered as a ' + '%s instance.' % instance.role) + + # If this instance is being set to primary and a *different* primary + # machine already exists, then error out if we're supposed to be timid. + if timid and instance.primary and primaries: + raise CommandError('Another instance is already registered as ' + 'primary.') + + # Lastly, if there are no primary machines at all, then don't allow + # this to be registered as a secondary machine. + if not instance.primary and not primaries: + raise CommandError('Unable to register a secondary machine until ' + 'a primary machine has been registered') From 4915ba291e1b48259a3677e5cb2983d6586ddcc6 Mon Sep 17 00:00:00 2001 From: Luke Sneeringer Date: Mon, 29 Sep 2014 15:05:53 -0500 Subject: [PATCH 06/33] Working instance registration. --- .../management/commands/register_instance.py | 23 +++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/awx/main/management/commands/register_instance.py b/awx/main/management/commands/register_instance.py index 560b8c2f14..f8894f6458 100644 --- a/awx/main/management/commands/register_instance.py +++ b/awx/main/management/commands/register_instance.py @@ -59,13 +59,28 @@ class Command(BaseCommand): '%s instance.' % instance.role) # If this instance is being set to primary and a *different* primary - # machine already exists, then error out if we're supposed to be timid. - if timid and instance.primary and primaries: + # machine alreadyexists, error out if we're supposed to be timid. + if timid and options['primary'] and primaries: raise CommandError('Another instance is already registered as ' 'primary.') # Lastly, if there are no primary machines at all, then don't allow # this to be registered as a secondary machine. - if not instance.primary and not primaries: + if not options['primary'] and not primaries: raise CommandError('Unable to register a secondary machine until ' - 'a primary machine has been registered') + 'another primary machine has been registered.') + + # If this is a primary machine and there is another primary machine, + # it must be de-primary-ified. + if options['primary'] and primaries: + for old_primary in other_instances.filter(primary=True): + old_primary.primary = False + old_primary.save() + + # Okay, we've checked for appropriate errata; perform the registration. + dirty = instance.primary is not options['primary'] + instance.primary = options['primary'] + instance.save() + + # Done! + print('Instance %s registered (changed: %r).' % (uuid, dirty)) From f77ae6f1bccfa29586f0dd4b51042f10272a63e3 Mon Sep 17 00:00:00 2001 From: Luke Sneeringer Date: Mon, 29 Sep 2014 15:20:40 -0500 Subject: [PATCH 07/33] Fixing a variable error. --- awx/main/management/commands/register_instance.py | 1 + 1 file changed, 1 insertion(+) diff --git a/awx/main/management/commands/register_instance.py b/awx/main/management/commands/register_instance.py index f8894f6458..c10d607146 100644 --- a/awx/main/management/commands/register_instance.py +++ b/awx/main/management/commands/register_instance.py @@ -34,6 +34,7 @@ class Command(BaseCommand): def handle(self, **options): uuid = settings.SYSTEM_UUID + timid = options['timid'] # Is there an existing record for this machine? # If so, retrieve that record and look for issues. From a9260db790cf6070cc54ee619c464bf18e06868a Mon Sep 17 00:00:00 2001 From: Luke Sneeringer Date: Tue, 30 Sep 2014 10:38:37 -0500 Subject: [PATCH 08/33] Adding an instance manager. --- awx/main/managers.py | 27 +++++++++++++++++++++++++++ awx/main/models/ha.py | 5 ++++- 2 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 awx/main/managers.py diff --git a/awx/main/managers.py b/awx/main/managers.py new file mode 100644 index 0000000000..a96e3b5571 --- /dev/null +++ b/awx/main/managers.py @@ -0,0 +1,27 @@ +# Copyright (c) 2014 Ansible, Inc. +# All Rights Reserved. + +from django.conf import settings +from django.db import models +from django.utils.functional import cached_property + + +class InstanceManager(models.Manager): + """A custom manager class for the Instance model. + + Provides "table-level" methods including getting the currently active + instance or role. + """ + @cached_property + def me(self): + """Return the currently active instance.""" + return self.get(uuid=settings.SYSTEM_UUID) + + @cached_property + def my_role(self): + """Return the role of the currently active instance, as a string + ('primary' or 'secondary'). + """ + if self.me.primary: + return 'primary' + return 'secondary' diff --git a/awx/main/models/ha.py b/awx/main/models/ha.py index a277124cd4..24aa4774af 100644 --- a/awx/main/models/ha.py +++ b/awx/main/models/ha.py @@ -2,13 +2,16 @@ # All Rights Reserved. from django.db import models +from awx.main.managers import InstanceManager class Instance(models.Model): """A model representing an Ansible Tower instance, primary or secondary, running against this database. """ - uuid = models.CharField(max_length=40) + objects = InstanceManager() + + uuid = models.CharField(max_length=40, unique=True) primary = models.BooleanField(default=False) created = models.DateTimeField(auto_now_add=True) modified = models.DateTimeField(auto_now=True) From 1c11f43ea21b8127fa3be510f93903913f776cc8 Mon Sep 17 00:00:00 2001 From: Luke Sneeringer Date: Tue, 30 Sep 2014 10:44:13 -0500 Subject: [PATCH 09/33] Thinking better of making the manager methods properties. --- awx/main/managers.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/awx/main/managers.py b/awx/main/managers.py index a96e3b5571..bb14078dc9 100644 --- a/awx/main/managers.py +++ b/awx/main/managers.py @@ -12,16 +12,14 @@ class InstanceManager(models.Manager): Provides "table-level" methods including getting the currently active instance or role. """ - @cached_property def me(self): """Return the currently active instance.""" return self.get(uuid=settings.SYSTEM_UUID) - @cached_property def my_role(self): """Return the role of the currently active instance, as a string ('primary' or 'secondary'). """ - if self.me.primary: + if self.me().primary: return 'primary' return 'secondary' From e43488467e45dcdd6b5c1e2fdce008b0014f3c12 Mon Sep 17 00:00:00 2001 From: Luke Sneeringer Date: Tue, 30 Sep 2014 13:05:27 -0500 Subject: [PATCH 10/33] Add dynamic role in /api/v1/ping/ --- awx/api/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/awx/api/views.py b/awx/api/views.py index 91e55ce88d..61abc5a509 100644 --- a/awx/api/views.py +++ b/awx/api/views.py @@ -130,7 +130,7 @@ class ApiV1PingView(APIView): this requires no auth and is intended for use by the installer process. """ return Response({ - 'role': 'standalone', # FIXME: Make this dynamic. + 'role': Instance.objects.my_role(), 'version': get_awx_version(), }) From 66dc2df8c3b1ed1c94466581168976b42233f031 Mon Sep 17 00:00:00 2001 From: Luke Sneeringer Date: Tue, 30 Sep 2014 13:05:38 -0500 Subject: [PATCH 11/33] Make development settings honor conf.d --- awx/settings/development.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/awx/settings/development.py b/awx/settings/development.py index 5b88d30778..3e6c4f984f 100644 --- a/awx/settings/development.py +++ b/awx/settings/development.py @@ -46,7 +46,10 @@ if 'django_jenkins' in INSTALLED_APPS: os.path.join(BASE_DIR, 'ui/static/lib/ansible'),] # If there is an `/etc/tower/settings.py`, include it. +# If there is a `/etc/tower/conf.d/*.py`, include them. include(optional('/etc/tower/settings.py'), scope=locals()) +include(optional('/etc/tower/conf.d/*.py'), scope=locals()) + # If any local_*.py files are present in awx/settings/, use them to override # default settings for development. If not present, we can still run using From 60dae748dccc63bdc74cf19fcc6f4d6f6ac004e2 Mon Sep 17 00:00:00 2001 From: Luke Sneeringer Date: Wed, 1 Oct 2014 10:55:14 -0500 Subject: [PATCH 12/33] Adding IP Address to the instance. Needed for redirecting. --- awx/main/models/ha.py | 1 + 1 file changed, 1 insertion(+) diff --git a/awx/main/models/ha.py b/awx/main/models/ha.py index 24aa4774af..a0f42c1d5f 100644 --- a/awx/main/models/ha.py +++ b/awx/main/models/ha.py @@ -12,6 +12,7 @@ class Instance(models.Model): objects = InstanceManager() uuid = models.CharField(max_length=40, unique=True) + ip_address = models.GenericIPAddressField(protocol='both', unpack_ipv4=True) primary = models.BooleanField(default=False) created = models.DateTimeField(auto_now_add=True) modified = models.DateTimeField(auto_now=True) From 57194c9a8971b2b0d93a24d3eb6cf96e4b01e6f1 Mon Sep 17 00:00:00 2001 From: Luke Sneeringer Date: Wed, 1 Oct 2014 14:43:52 -0500 Subject: [PATCH 13/33] Addition of IP address to instance records. --- awx/main/management/commands/register_instance.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/awx/main/management/commands/register_instance.py b/awx/main/management/commands/register_instance.py index c10d607146..495cd88caf 100644 --- a/awx/main/management/commands/register_instance.py +++ b/awx/main/management/commands/register_instance.py @@ -28,6 +28,7 @@ class Command(BaseCommand): """ option_list = BaseCommand.option_list + ( make_option('--timid', action='store_true', dest='timid'), + make_option('--ip-address', dest='ip_address', default=''), make_option('--primary', action='store_true', dest='primary'), make_option('--secondary', action='store_false', dest='primary'), ) @@ -71,6 +72,12 @@ class Command(BaseCommand): raise CommandError('Unable to register a secondary machine until ' 'another primary machine has been registered.') + # Sanity check: An IP address is required if this is an initial + # registration. + if not existing and not options['ip_address']: + raise CommandError('An explicit IP address is required at initial ' + 'registration.') + # If this is a primary machine and there is another primary machine, # it must be de-primary-ified. if options['primary'] and primaries: @@ -79,8 +86,14 @@ class Command(BaseCommand): old_primary.save() # Okay, we've checked for appropriate errata; perform the registration. - dirty = instance.primary is not options['primary'] + dirty = any([ + instance.primary is not options['primary'], + options['ip_address'] and + instance.ip_address != options['ip_address'], + ]) instance.primary = options['primary'] + if options['ip_address']: + instance.ip_address = options['ip_address'] instance.save() # Done! From 0e623f2337361206656f202c590bcbf42c4338d7 Mon Sep 17 00:00:00 2001 From: Luke Sneeringer Date: Wed, 1 Oct 2014 16:36:34 -0500 Subject: [PATCH 14/33] Start of HA middleware. --- awx/main/managers.py | 4 ++++ awx/main/middleware.py | 11 +++++++++++ awx/settings/defaults.py | 1 + 3 files changed, 16 insertions(+) diff --git a/awx/main/managers.py b/awx/main/managers.py index bb14078dc9..fe0fc6b1e7 100644 --- a/awx/main/managers.py +++ b/awx/main/managers.py @@ -23,3 +23,7 @@ class InstanceManager(models.Manager): if self.me().primary: return 'primary' return 'secondary' + + def primary(self): + """Return the primary instance.""" + return self.get(primary=True) diff --git a/awx/main/middleware.py b/awx/main/middleware.py index a9d111249e..b553ffed87 100644 --- a/awx/main/middleware.py +++ b/awx/main/middleware.py @@ -61,3 +61,14 @@ class ActivityStreamMiddleware(threading.local): else: if instance.id not in self.instance_ids: self.instance_ids.append(instance.id) + + +class HAMiddlware(object): + """A middleware class that checks to see whether the request is being + served on a secondary instance, and redirects the request back to the + primary instance if so. + """ + def process_request(self, request): + """Process the request, and redirect if this is a request on a + secondary node. + """ diff --git a/awx/settings/defaults.py b/awx/settings/defaults.py index ea34f44161..e71f62b562 100644 --- a/awx/settings/defaults.py +++ b/awx/settings/defaults.py @@ -116,6 +116,7 @@ TEMPLATE_CONTEXT_PROCESSORS += ( ) MIDDLEWARE_CLASSES += ( + 'awx.main.middleware.HAMiddleware', 'awx.main.middleware.ActivityStreamMiddleware', 'crum.CurrentRequestUserMiddleware', ) From 1ae333ca1d9443c4d8f94c12344a942aad6253c5 Mon Sep 17 00:00:00 2001 From: Luke Sneeringer Date: Thu, 2 Oct 2014 14:03:09 -0500 Subject: [PATCH 15/33] HA redirection. --- awx/main/middleware.py | 41 ++++++++++++++++++++++++++++------ awx/templates/ha/redirect.html | 13 +++++++++++ 2 files changed, 47 insertions(+), 7 deletions(-) create mode 100644 awx/templates/ha/redirect.html diff --git a/awx/main/middleware.py b/awx/main/middleware.py index b553ffed87..b09d5405f5 100644 --- a/awx/main/middleware.py +++ b/awx/main/middleware.py @@ -1,20 +1,27 @@ # Copyright (c) 2014 AnsibleWorks, Inc. # All Rights Reserved. +import json +import logging +import threading +import uuid +import urllib2 + from django.conf import settings from django.contrib.auth.models import User, AnonymousUser from django.db.models.signals import pre_save, post_save from django.db import IntegrityError +from django.http import HttpResponseRedirect +from django.template.response import TemplateResponse from django.utils.functional import curry -from awx.main.models import ActivityStream, AuthToken -import json -import threading -import uuid -import urllib2 -import logging +from awx import __version__ as version +from awx.main.models import ActivityStream, AuthToken, Instance + + logger = logging.getLogger('awx.main.middleware') + class ActivityStreamMiddleware(threading.local): def __init__(self): @@ -63,7 +70,7 @@ class ActivityStreamMiddleware(threading.local): self.instance_ids.append(instance.id) -class HAMiddlware(object): +class HAMiddleware(object): """A middleware class that checks to see whether the request is being served on a secondary instance, and redirects the request back to the primary instance if so. @@ -72,3 +79,23 @@ class HAMiddlware(object): """Process the request, and redirect if this is a request on a secondary node. """ + # Is this the primary node? If so, we can just return None and be done; + # we just want normal behavior in this case. + if Instance.objects.my_role() == 'primary': + return None + + # Get the primary instance. + primary = Instance.objects.primary() + + # If this is a request to /, then we return a special landing page that + # informs the user that they are on the secondary instance and will + # be redirected. + if request.path == '/': + return TemplateResponse(request, 'ha/redirect.html', { + 'primary': primary, + 'redirect_seconds': 30, + 'version': version, + }) + + # Redirect to the base page of the primary instance. + return HttpResponseRedirect('http://%s/' % primary.ip_address) diff --git a/awx/templates/ha/redirect.html b/awx/templates/ha/redirect.html new file mode 100644 index 0000000000..244575756f --- /dev/null +++ b/awx/templates/ha/redirect.html @@ -0,0 +1,13 @@ + + + Ansible Tower: Secondary + + + +

Ansible Tower

+

This Ansible Tower server (version {{ version }}) is in secondary + mode. The current master is {{ primary.ip_address }}. +

+

This page will redirect in {{ redirect_seconds }} seconds.

+ + From ec7aa1867fc116bb14b76275b21a7b7a70cba3e8 Mon Sep 17 00:00:00 2001 From: Luke Sneeringer Date: Mon, 6 Oct 2014 11:43:53 -0500 Subject: [PATCH 16/33] Adding JobOrigin model and migration. --- awx/main/migrations/0056_v210_changes.py | 2 +- awx/main/models/ha.py | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/awx/main/migrations/0056_v210_changes.py b/awx/main/migrations/0056_v210_changes.py index b5d9ced76a..0291afc6e0 100644 --- a/awx/main/migrations/0056_v210_changes.py +++ b/awx/main/migrations/0056_v210_changes.py @@ -475,4 +475,4 @@ class Migration(SchemaMigration): } } - complete_apps = ['main'] \ No newline at end of file + complete_apps = ['main'] diff --git a/awx/main/models/ha.py b/awx/main/models/ha.py index a0f42c1d5f..34659bb7ef 100644 --- a/awx/main/models/ha.py +++ b/awx/main/models/ha.py @@ -2,7 +2,9 @@ # All Rights Reserved. from django.db import models + from awx.main.managers import InstanceManager +from awx.main.models import UnifiedJob class Instance(models.Model): @@ -26,3 +28,21 @@ class Instance(models.Model): if self.primary: return 'primary' return 'secondary' + + +class JobOrigin(models.Model): + """A model representing the relationship between a unified job and + the instance that was responsible for starting that job. + + It may be possible that a job has no origin (the common reason for this + being that the job was started on Tower < 2.1 before origins were a thing). + This is fine, and code should be able to handle it. A job with no origin + is always assumed to *not* have the current instance as its origin. + """ + unified_job = models.ForeignKey(UnifiedJob) + instance = models.ForeignKey(Instance) + created = models.DateTimeField(auto_now_add=True) + modified = models.DateTimeField(auto_now=True) + + class Meta: + app_label = 'main' From a72e72f20fce4c176f28b896f896db196f936996 Mon Sep 17 00:00:00 2001 From: Luke Sneeringer Date: Mon, 6 Oct 2014 12:38:12 -0500 Subject: [PATCH 17/33] Adding a post_save receiver. --- awx/main/models/ha.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/awx/main/models/ha.py b/awx/main/models/ha.py index 34659bb7ef..b28fe1231e 100644 --- a/awx/main/models/ha.py +++ b/awx/main/models/ha.py @@ -2,6 +2,8 @@ # All Rights Reserved. from django.db import models +from django.db.models.signals import post_save +from django.dispatch import receiver from awx.main.managers import InstanceManager from awx.main.models import UnifiedJob @@ -46,3 +48,24 @@ class JobOrigin(models.Model): class Meta: app_label = 'main' + + + +@receiver(post_save, sender=UnifiedJob) +def on_create(sender, instance, created=False, raw=False, **kwargs): + """When a new job is created, save a record of its origin (the machine + that started the job). + """ + # Sanity check: We only want to create a JobOrigin record in cases where + # we are making a new record, and in normal situations. + # + # In other situations, we simply do nothing. + if raw or not created: + return + + # Create the JobOrigin record, which attaches to the current instance + # (which started the job). + job_origin, new = JobOrigin.objects.get_or_create( + instance=Instance.objects.me(), + unified_job=instance, + ) From f6a501bb28b09a5a08a2673e9fc1ac7ef280970e Mon Sep 17 00:00:00 2001 From: Luke Sneeringer Date: Mon, 6 Oct 2014 12:57:57 -0500 Subject: [PATCH 18/33] Register signal against subclasses separately. --- awx/main/models/ha.py | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/awx/main/models/ha.py b/awx/main/models/ha.py index b28fe1231e..cf460c7aaf 100644 --- a/awx/main/models/ha.py +++ b/awx/main/models/ha.py @@ -6,7 +6,12 @@ from django.db.models.signals import post_save from django.dispatch import receiver from awx.main.managers import InstanceManager -from awx.main.models import UnifiedJob +from awx.main.models.inventory import InventoryUpdate +from awx.main.models.jobs import Job +from awx.main.models.projects import ProjectUpdate +from awx.main.models.unified_jobs import UnifiedJob + +__all__ = ('Instance', 'JobOrigin') class Instance(models.Model): @@ -50,8 +55,12 @@ class JobOrigin(models.Model): app_label = 'main' - -@receiver(post_save, sender=UnifiedJob) +# Unfortunately, the signal can't just be connected against UnifiedJob; it +# turns out that creating a model's subclass doesn't fire the signal for the +# superclass model. +@receiver(post_save, sender=InventoryUpdate) +@receiver(post_save, sender=Job) +@receiver(post_save, sender=ProjectUpdate) def on_create(sender, instance, created=False, raw=False, **kwargs): """When a new job is created, save a record of its origin (the machine that started the job). From e23801313e61377d73ac6289bca1555a3b23f041 Mon Sep 17 00:00:00 2001 From: Luke Sneeringer Date: Tue, 7 Oct 2014 09:54:06 -0500 Subject: [PATCH 19/33] Do a OneToOne with UnifiedJob. --- awx/main/models/ha.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/awx/main/models/ha.py b/awx/main/models/ha.py index cf460c7aaf..145b556d87 100644 --- a/awx/main/models/ha.py +++ b/awx/main/models/ha.py @@ -46,7 +46,7 @@ class JobOrigin(models.Model): This is fine, and code should be able to handle it. A job with no origin is always assumed to *not* have the current instance as its origin. """ - unified_job = models.ForeignKey(UnifiedJob) + unified_job = models.OneToOneField(UnifiedJob, related_name='job_origin') instance = models.ForeignKey(Instance) created = models.DateTimeField(auto_now_add=True) modified = models.DateTimeField(auto_now=True) From ec1c7700992966059696dbec542f3993f0025156 Mon Sep 17 00:00:00 2001 From: Luke Sneeringer Date: Tue, 7 Oct 2014 12:20:02 -0500 Subject: [PATCH 20/33] Added job cancelation when switching to secondary. --- awx/main/models/ha.py | 25 +++++++++++++++++++++++-- awx/main/models/unified_jobs.py | 4 +++- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/awx/main/models/ha.py b/awx/main/models/ha.py index 145b556d87..d59d77c868 100644 --- a/awx/main/models/ha.py +++ b/awx/main/models/ha.py @@ -1,6 +1,8 @@ # Copyright (c) 2014 Ansible, Inc. # All Rights Reserved. +import functools + from django.db import models from django.db.models.signals import post_save from django.dispatch import receiver @@ -9,7 +11,7 @@ from awx.main.managers import InstanceManager from awx.main.models.inventory import InventoryUpdate from awx.main.models.jobs import Job from awx.main.models.projects import ProjectUpdate -from awx.main.models.unified_jobs import UnifiedJob +from awx.main.models.unified_jobs import UnifiedJob, CAN_CANCEL __all__ = ('Instance', 'JobOrigin') @@ -36,6 +38,25 @@ class Instance(models.Model): return 'primary' return 'secondary' + @functools.wraps(models.Model.save) + def save(self, *args, **kwargs): + """Save the instance. If this is a secondary instance, then ensure + that any currently-running jobs that this instance started are + canceled. + """ + # Perform the normal save. + result = super(Instance, self).save(*args, **kwargs) + + # If this is not a primary instance, then kill any jobs that this + # instance was responsible for starting. + if not self.primary: + for job in UnifiedJob.objects.filter(job_origin__instance=self, + status__in=CAN_CANCEL): + job.cancel() + + # Return back the original result. + return result + class JobOrigin(models.Model): """A model representing the relationship between a unified job and @@ -61,7 +82,7 @@ class JobOrigin(models.Model): @receiver(post_save, sender=InventoryUpdate) @receiver(post_save, sender=Job) @receiver(post_save, sender=ProjectUpdate) -def on_create(sender, instance, created=False, raw=False, **kwargs): +def on_job_create(sender, instance, created=False, raw=False, **kwargs): """When a new job is created, save a record of its origin (the machine that started the job). """ diff --git a/awx/main/models/unified_jobs.py b/awx/main/models/unified_jobs.py index 2a6220b9fd..c8b86bcfcf 100644 --- a/awx/main/models/unified_jobs.py +++ b/awx/main/models/unified_jobs.py @@ -42,6 +42,8 @@ __all__ = ['UnifiedJobTemplate', 'UnifiedJob'] logger = logging.getLogger('awx.main.models.unified_jobs') +CAN_CANCEL = ('new', 'pending', 'waiting', 'running') + class UnifiedJobTemplate(PolymorphicModel, CommonModelNameNotUnique): ''' @@ -644,7 +646,7 @@ class UnifiedJob(PolymorphicModel, PasswordFieldsModel, CommonModelNameNotUnique @property def can_cancel(self): - return bool(self.status in ('new', 'pending', 'waiting', 'running')) + return bool(self.status in CAN_CANCEL) def _force_cancel(self): # Update the status to 'canceled' if we can detect that the job From 223a2168b8a558fd4d934e3d3e7acbaf69a3c80b Mon Sep 17 00:00:00 2001 From: Luke Sneeringer Date: Tue, 7 Oct 2014 12:54:13 -0500 Subject: [PATCH 21/33] Commenting up the UnifiedJob.save method. --- awx/main/models/unified_jobs.py | 40 ++++++++++++++++++++++++++++----- 1 file changed, 35 insertions(+), 5 deletions(-) diff --git a/awx/main/models/unified_jobs.py b/awx/main/models/unified_jobs.py index c8b86bcfcf..210d3d4b6b 100644 --- a/awx/main/models/unified_jobs.py +++ b/awx/main/models/unified_jobs.py @@ -469,28 +469,47 @@ class UnifiedJob(PolymorphicModel, PasswordFieldsModel, CommonModelNameNotUnique 'last_job_failed']) def save(self, *args, **kwargs): + """Save the job, with current status, to the database. + Ensure that all data is consistent before doing so. + """ # If update_fields has been specified, add our field names to it, # if it hasn't been specified, then we're just doing a normal save. update_fields = kwargs.get('update_fields', []) + # Get status before save... status_before = self.status or 'new' + + # If this job already exists in the database, retrieve a copy of + # the job in its prior state. if self.pk: self_before = self.__class__.objects.get(pk=self.pk) if self_before.status != self.status: status_before = self_before.status + + # Sanity check: Is this a failure? Ensure that the failure value + # matches the status. failed = bool(self.status in ('failed', 'error', 'canceled')) if self.failed != failed: self.failed = failed if 'failed' not in update_fields: update_fields.append('failed') + + # Sanity check: Has the job just started? If so, mark down its start + # time. if self.status == 'running' and not self.started: self.started = now() if 'started' not in update_fields: update_fields.append('started') + + # Sanity check: Has the job just completed? If so, mark down its + # completion time, and record its output to the database. if self.status in ('successful', 'failed', 'error', 'canceled') and not self.finished: self.finished = now() if 'finished' not in update_fields: update_fields.append('finished') + + # If we have a start and finished time, and haven't already calculated + # out the time that elapsed, do so. if self.started and self.finished and not self.elapsed: td = self.finished - self.started elapsed = (td.microseconds + (td.seconds + td.days * 24 * 3600) * 10**6) / (10**6 * 1.0) @@ -500,15 +519,23 @@ class UnifiedJob(PolymorphicModel, PasswordFieldsModel, CommonModelNameNotUnique self.elapsed = str(elapsed) if 'elapsed' not in update_fields: update_fields.append('elapsed') + + # Ensure that the job template information is current. if self.unified_job_template != self._get_parent_instance(): self.unified_job_template = self._get_parent_instance() if 'unified_job_template' not in update_fields: update_fields.append('unified_job_template') - super(UnifiedJob, self).save(*args, **kwargs) - # If status changed, update parent instance.... + + # Okay; we're done. Perform the actual save. + result = super(UnifiedJob, self).save(*args, **kwargs) + + # If status changed, update the parent instance. if self.status != status_before: self._update_parent_instance() + # Done. + return result + def delete(self): if self.result_stdout_file != "": try: @@ -518,12 +545,15 @@ class UnifiedJob(PolymorphicModel, PasswordFieldsModel, CommonModelNameNotUnique super(UnifiedJob, self).delete() def result_stdout_raw_handle(self): - if self.result_stdout_file != "": + """Return a file-like object containing the standard out of the + job's result. + """ + if self.result_stdout_text: + return StringIO(self.result_stdout_text) + else: if not os.path.exists(self.result_stdout_file): return StringIO("stdout capture is missing") return codecs.open(self.result_stdout_file, "r", encoding='utf-8') - else: - return StringIO(self.result_stdout_text) @property def result_stdout_raw(self): From dea41b6126cf56c4b34ed41b90754b654ae82d4a Mon Sep 17 00:00:00 2001 From: Luke Sneeringer Date: Tue, 7 Oct 2014 13:24:52 -0500 Subject: [PATCH 22/33] Record stdout in the database. --- awx/main/models/unified_jobs.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/awx/main/models/unified_jobs.py b/awx/main/models/unified_jobs.py index 210d3d4b6b..27fea7cd73 100644 --- a/awx/main/models/unified_jobs.py +++ b/awx/main/models/unified_jobs.py @@ -9,7 +9,7 @@ import re import shlex import os import os.path -from cStringIO import StringIO +from StringIO import StringIO # PyYAML import yaml @@ -504,10 +504,19 @@ class UnifiedJob(PolymorphicModel, PasswordFieldsModel, CommonModelNameNotUnique # Sanity check: Has the job just completed? If so, mark down its # completion time, and record its output to the database. if self.status in ('successful', 'failed', 'error', 'canceled') and not self.finished: + # Record the `finished` time. self.finished = now() if 'finished' not in update_fields: update_fields.append('finished') + # Take the output from the filesystem and record it in the + # database. + stdout = self.result_stdout_raw_handle() + if not isinstance(stdout, StringIO): + self.result_stdout_text = stdout.read() + if 'result_stdout_text' not in update_fields: + update_fields.append('result_stdout_text') + # If we have a start and finished time, and haven't already calculated # out the time that elapsed, do so. if self.started and self.finished and not self.elapsed: From d325cd4d098be0ee744d1f32eff587c8435e7687 Mon Sep 17 00:00:00 2001 From: Luke Sneeringer Date: Tue, 7 Oct 2014 15:10:59 -0500 Subject: [PATCH 23/33] Remove file when moving data to database. --- awx/main/models/unified_jobs.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/awx/main/models/unified_jobs.py b/awx/main/models/unified_jobs.py index 27fea7cd73..a9429636dc 100644 --- a/awx/main/models/unified_jobs.py +++ b/awx/main/models/unified_jobs.py @@ -517,6 +517,15 @@ class UnifiedJob(PolymorphicModel, PasswordFieldsModel, CommonModelNameNotUnique if 'result_stdout_text' not in update_fields: update_fields.append('result_stdout_text') + # Attempt to delete the job output from the filesystem if it + # was moved to the database. + if self.result_stdout_file: + try: + os.remove(self.result_stdout_file) + self.result_stdout_file = '' + except: + pass # Meh. We don't care that much. + # If we have a start and finished time, and haven't already calculated # out the time that elapsed, do so. if self.started and self.finished and not self.elapsed: From ac4bde69cc03fc65df486f310bbd1160ea35d212 Mon Sep 17 00:00:00 2001 From: Luke Sneeringer Date: Wed, 8 Oct 2014 10:48:01 -0500 Subject: [PATCH 24/33] Minor commit to make result_stdout_file become empty string. --- awx/main/models/unified_jobs.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/awx/main/models/unified_jobs.py b/awx/main/models/unified_jobs.py index a9429636dc..189bbc2f8a 100644 --- a/awx/main/models/unified_jobs.py +++ b/awx/main/models/unified_jobs.py @@ -523,6 +523,8 @@ class UnifiedJob(PolymorphicModel, PasswordFieldsModel, CommonModelNameNotUnique try: os.remove(self.result_stdout_file) self.result_stdout_file = '' + if 'result_stdout_file' not in update_fields: + update_fields.append('result_stdout_file') except: pass # Meh. We don't care that much. From bc763eab57de1e682980b58bac7b9b3b5b9b448d Mon Sep 17 00:00:00 2001 From: Luke Sneeringer Date: Wed, 8 Oct 2014 12:01:58 -0500 Subject: [PATCH 25/33] Know how to spot an HA environment. --- awx/main/ha.py | 23 +++++++++++++++++++++++ awx/main/middleware.py | 2 +- awx/main/utils.py | 24 ++++++++++++++++++++++-- 3 files changed, 46 insertions(+), 3 deletions(-) create mode 100644 awx/main/ha.py diff --git a/awx/main/ha.py b/awx/main/ha.py new file mode 100644 index 0000000000..1cd4540a87 --- /dev/null +++ b/awx/main/ha.py @@ -0,0 +1,23 @@ +# Copyright (c) 2014 Ansible, Inc. +# All Rights Reserved. + +from django.conf import settings + +from awx.main.models import Instance + + +def is_ha_environment(): + """Return True if this is an HA environment, and False + otherwise. + """ + # If there are two or more instances, then we are in an HA environment. + if Instance.objects.count() > 1: + return True + + # If the database is not local, then we are in an HA environment. + host = settings.DATABASES['default'].get('host', 'localhost') + if host and host.lower() not in ('127.0.0.1', 'localhost'): + return True + + # We are not in an HA environment. + return False diff --git a/awx/main/middleware.py b/awx/main/middleware.py index b09d5405f5..d0c05c89da 100644 --- a/awx/main/middleware.py +++ b/awx/main/middleware.py @@ -1,4 +1,4 @@ -# Copyright (c) 2014 AnsibleWorks, Inc. +# Copyright (c) 2014 Ansible, Inc. # All Rights Reserved. import json diff --git a/awx/main/utils.py b/awx/main/utils.py index 4e4482d4eb..87635d5968 100644 --- a/awx/main/utils.py +++ b/awx/main/utils.py @@ -21,10 +21,13 @@ from Crypto.Cipher import AES # ZeroMQ import zmq + __all__ = ['get_object_or_400', 'get_object_or_403', 'camelcase_to_underscore', 'get_ansible_version', 'get_awx_version', 'update_scm_url', - 'get_type_for_model', 'get_model_for_type', 'ignore_inventory_computed_fields', - 'ignore_inventory_group_removal', '_inventory_updates'] + 'get_type_for_model', 'get_model_for_type', + 'ignore_inventory_computed_fields', 'ignore_inventory_group_removal', + '_inventory_updates'] + def get_object_or_400(klass, *args, **kwargs): ''' @@ -40,6 +43,7 @@ def get_object_or_400(klass, *args, **kwargs): except queryset.model.MultipleObjectsReturned, e: raise ParseError(*e.args) + def get_object_or_403(klass, *args, **kwargs): ''' Return a single object from the given model or queryset based on the query @@ -54,6 +58,7 @@ def get_object_or_403(klass, *args, **kwargs): except queryset.model.MultipleObjectsReturned, e: raise PermissionDenied(*e.args) + def camelcase_to_underscore(s): ''' Convert CamelCase names to lowercase_with_underscore. @@ -61,6 +66,7 @@ def camelcase_to_underscore(s): s = re.sub(r'(((?<=[a-z])[A-Z])|([A-Z](?![A-Z]|$)))', '_\\1', s) return s.lower().strip('_') + class RequireDebugTrueOrTest(logging.Filter): ''' Logging filter to output when in DEBUG mode or running tests. @@ -70,6 +76,7 @@ class RequireDebugTrueOrTest(logging.Filter): from django.conf import settings return settings.DEBUG or 'test' in sys.argv + def get_ansible_version(): ''' Return Ansible version installed. @@ -83,6 +90,7 @@ def get_ansible_version(): except: return 'unknown' + def get_awx_version(): ''' Return Ansible Tower version as reported by setuptools. @@ -94,6 +102,7 @@ def get_awx_version(): except: return __version__ + def get_encryption_key(instance, field_name): ''' Generate key for encrypted password based on instance pk and field name. @@ -105,6 +114,7 @@ def get_encryption_key(instance, field_name): h.update(field_name) return h.digest()[:16] + def encrypt_field(instance, field_name, ask=False): ''' Return content of the given instance and field name encrypted. @@ -121,6 +131,7 @@ def encrypt_field(instance, field_name, ask=False): b64data = base64.b64encode(encrypted) return '$encrypted$%s$%s' % ('AES', b64data) + def decrypt_field(instance, field_name): ''' Return content of the given instance and field name decrypted. @@ -137,6 +148,7 @@ def decrypt_field(instance, field_name): value = cipher.decrypt(encrypted) return value.rstrip('\x00') + def update_scm_url(scm_type, url, username=True, password=True, check_special_cases=True): ''' @@ -233,6 +245,7 @@ def update_scm_url(scm_type, url, username=True, password=True, parts.query, parts.fragment]) return new_url + def model_instance_diff(old, new, serializer_mapping=None): """ Calculate the differences between two model instances. One of the instances may be None (i.e., a newly @@ -283,6 +296,7 @@ def model_instance_diff(old, new, serializer_mapping=None): return diff + def model_to_dict(obj, serializer_mapping=None): """ Serialize a model instance to a dictionary as best as possible @@ -309,6 +323,7 @@ def model_to_dict(obj, serializer_mapping=None): attr_d[field.name] = "hidden" return attr_d + def get_type_for_model(model): ''' Return type name for a given model class. @@ -317,6 +332,7 @@ def get_type_for_model(model): opts = get_concrete_model(model)._meta return camelcase_to_underscore(opts.object_name) + def get_model_for_type(type): ''' Return model class for a given type name. @@ -331,6 +347,7 @@ def get_model_for_type(type): if type == ct_type: return ct_model + def get_system_task_capacity(): ''' Measure system memory and use it as a baseline for determining the system's capacity @@ -345,6 +362,7 @@ def get_system_task_capacity(): return 50 return 50 + ((int(total_mem_value) / 1024) - 2) * 75 + def emit_websocket_notification(endpoint, event, payload): from django.conf import settings if getattr(settings, 'SOCKETIO_NOTIFICATION_PORT', None): @@ -357,6 +375,7 @@ def emit_websocket_notification(endpoint, event, payload): _inventory_updates = threading.local() + @contextlib.contextmanager def ignore_inventory_computed_fields(): ''' @@ -369,6 +388,7 @@ def ignore_inventory_computed_fields(): finally: _inventory_updates.is_updating = previous_value + @contextlib.contextmanager def ignore_inventory_group_removal(): ''' From 2166a3788cd7a4784a503da1420cb1933f0fd9f5 Mon Sep 17 00:00:00 2001 From: Luke Sneeringer Date: Wed, 8 Oct 2014 12:16:51 -0500 Subject: [PATCH 26/33] Adding HA status to ping view. --- awx/api/views.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/awx/api/views.py b/awx/api/views.py index 61abc5a509..176971e38e 100644 --- a/awx/api/views.py +++ b/awx/api/views.py @@ -45,6 +45,7 @@ from awx.main.task_engine import TaskSerializer, TASK_FILE from awx.main.models import * from awx.main.utils import * from awx.main.access import get_user_queryset +from awx.main.ha import is_ha_environment from awx.api.authentication import JobTaskAuthentication from awx.api.permissions import * from awx.api.renderers import * @@ -130,6 +131,7 @@ class ApiV1PingView(APIView): this requires no auth and is intended for use by the installer process. """ return Response({ + 'ha': is_ha_environment(), 'role': Instance.objects.my_role(), 'version': get_awx_version(), }) From 08570ef4e97ead0084c3357cde53a69da5f9a3c0 Mon Sep 17 00:00:00 2001 From: Luke Sneeringer Date: Wed, 15 Oct 2014 14:55:03 -0500 Subject: [PATCH 27/33] Add primary and secondary IP output to ping view. --- awx/api/views.py | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/awx/api/views.py b/awx/api/views.py index 176971e38e..66c8c22b8a 100644 --- a/awx/api/views.py +++ b/awx/api/views.py @@ -130,11 +130,32 @@ class ApiV1PingView(APIView): Everything returned here should be considered public / insecure, as this requires no auth and is intended for use by the installer process. """ - return Response({ + # Most of this response is canned; just build the dictionary. + response = { 'ha': is_ha_environment(), 'role': Instance.objects.my_role(), 'version': get_awx_version(), - }) + } + + # If this is an HA environment, we also include the IP address of + # all of the instances. + # + # Set up a default structure. + response['instances'] = { + 'primary': None, + 'secondaries': [], + } + + # Add all of the instances into the structure. + for instance in Instance.objects.all(): + if instance.primary: + response['instances']['primary'] = instance.ip_address + else: + response['instances']['secondaries'].append(instance.ip_address) + response['instances']['secondaries'].sort() + + # Done; return the response. + return Response(response) class ApiV1ConfigView(APIView): From b18303be20b71cb4005f3daffa79fe1d4a846253 Mon Sep 17 00:00:00 2001 From: Luke Sneeringer Date: Fri, 17 Oct 2014 11:18:04 -0500 Subject: [PATCH 28/33] Readd migration for instances and job origins. --- awx/main/migrations/0057_v210_changes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/awx/main/migrations/0057_v210_changes.py b/awx/main/migrations/0057_v210_changes.py index d4e60c6f78..1ff37aeb7c 100644 --- a/awx/main/migrations/0057_v210_changes.py +++ b/awx/main/migrations/0057_v210_changes.py @@ -472,4 +472,4 @@ class Migration(SchemaMigration): } } - complete_apps = ['main'] \ No newline at end of file + complete_apps = ['main'] From 53234eb1ab0bafe49b8e198336d7958fed3e3f61 Mon Sep 17 00:00:00 2001 From: Luke Sneeringer Date: Fri, 17 Oct 2014 13:26:21 -0500 Subject: [PATCH 29/33] Return stub records in testing. --- awx/main/managers.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/awx/main/managers.py b/awx/main/managers.py index fe0fc6b1e7..c2a0335f04 100644 --- a/awx/main/managers.py +++ b/awx/main/managers.py @@ -1,6 +1,8 @@ # Copyright (c) 2014 Ansible, Inc. # All Rights Reserved. +import sys + from django.conf import settings from django.db import models from django.utils.functional import cached_property @@ -14,16 +16,34 @@ class InstanceManager(models.Manager): """ def me(self): """Return the currently active instance.""" + # If we are running unit tests, return a stub record. + if len(sys.argv) >= 2 and sys.argv[1] == 'test': + return self.model(id=1, primary=True, + uuid='00000000-0000-0000-0000-000000000000') + + # Return the appropriate record from the database. return self.get(uuid=settings.SYSTEM_UUID) def my_role(self): """Return the role of the currently active instance, as a string ('primary' or 'secondary'). """ + # If we are running unit tests, we are primary, because reasons. + if len(sys.argv) >= 2 and sys.argv[1] == 'test': + return 'primary' + + # Check if this instance is primary; if so, return "primary", otherwise + # "secondary". if self.me().primary: return 'primary' return 'secondary' def primary(self): """Return the primary instance.""" + # If we are running unit tests, return a stub record. + if len(sys.argv) >= 2 and sys.argv[1] == 'test': + return self.model(id=1, primary=True, + uuid='00000000-0000-0000-0000-000000000000') + + # Return the appropriate record from the database. return self.get(primary=True) From 1bdd1f4c34b60791ec47a9b3053812b350a473a1 Mon Sep 17 00:00:00 2001 From: Luke Sneeringer Date: Fri, 17 Oct 2014 13:59:55 -0500 Subject: [PATCH 30/33] Remove migration...again. --- awx/main/migrations/0057_v210_changes.py | 475 ----------------------- 1 file changed, 475 deletions(-) delete mode 100644 awx/main/migrations/0057_v210_changes.py diff --git a/awx/main/migrations/0057_v210_changes.py b/awx/main/migrations/0057_v210_changes.py deleted file mode 100644 index 1ff37aeb7c..0000000000 --- a/awx/main/migrations/0057_v210_changes.py +++ /dev/null @@ -1,475 +0,0 @@ -# -*- coding: utf-8 -*- -from south.utils import datetime_utils as datetime -from south.db import db -from south.v2 import SchemaMigration -from django.db import models - - -class Migration(SchemaMigration): - - def forwards(self, orm): - # Adding field 'Schedule.extra_data' - db.add_column(u'main_schedule', 'extra_data', - self.gf('jsonfield.fields.JSONField')(default={}, blank=True), - keep_default=False) - - # Adding field 'SystemJob.extra_vars' - db.add_column(u'main_systemjob', 'extra_vars', - self.gf('django.db.models.fields.TextField')(default='', blank=True), - keep_default=False) - - - def backwards(self, orm): - # Deleting field 'Schedule.extra_data' - db.delete_column(u'main_schedule', 'extra_data') - - # Deleting field 'SystemJob.extra_vars' - db.delete_column(u'main_systemjob', 'extra_vars') - - - models = { - u'auth.group': { - 'Meta': {'object_name': 'Group'}, - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), - 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) - }, - u'auth.permission': { - 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'}, - 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) - }, - u'auth.user': { - 'Meta': {'object_name': 'User'}, - 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), - 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), - 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}), - 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) - }, - u'contenttypes.contenttype': { - 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, - 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) - }, - 'main.activitystream': { - 'Meta': {'object_name': 'ActivityStream'}, - 'actor': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'activity_stream'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), - 'changes': ('django.db.models.fields.TextField', [], {'blank': 'True'}), - 'credential': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.Credential']", 'symmetrical': 'False', 'blank': 'True'}), - 'group': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.Group']", 'symmetrical': 'False', 'blank': 'True'}), - 'host': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.Host']", 'symmetrical': 'False', 'blank': 'True'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'inventory': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.Inventory']", 'symmetrical': 'False', 'blank': 'True'}), - 'inventory_source': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.InventorySource']", 'symmetrical': 'False', 'blank': 'True'}), - 'inventory_update': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.InventoryUpdate']", 'symmetrical': 'False', 'blank': 'True'}), - 'job': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.Job']", 'symmetrical': 'False', 'blank': 'True'}), - 'job_template': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.JobTemplate']", 'symmetrical': 'False', 'blank': 'True'}), - 'object1': ('django.db.models.fields.TextField', [], {}), - 'object2': ('django.db.models.fields.TextField', [], {}), - 'object_relationship_type': ('django.db.models.fields.TextField', [], {'blank': 'True'}), - 'operation': ('django.db.models.fields.CharField', [], {'max_length': '13'}), - 'organization': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.Organization']", 'symmetrical': 'False', 'blank': 'True'}), - 'permission': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.Permission']", 'symmetrical': 'False', 'blank': 'True'}), - 'project': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.Project']", 'symmetrical': 'False', 'blank': 'True'}), - 'project_update': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.ProjectUpdate']", 'symmetrical': 'False', 'blank': 'True'}), - 'schedule': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.Schedule']", 'symmetrical': 'False', 'blank': 'True'}), - 'team': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.Team']", 'symmetrical': 'False', 'blank': 'True'}), - 'timestamp': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), - 'unified_job': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'activity_stream_as_unified_job+'", 'blank': 'True', 'to': "orm['main.UnifiedJob']"}), - 'unified_job_template': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'activity_stream_as_unified_job_template+'", 'blank': 'True', 'to': "orm['main.UnifiedJobTemplate']"}), - 'user': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.User']", 'symmetrical': 'False', 'blank': 'True'}) - }, - 'main.authtoken': { - 'Meta': {'object_name': 'AuthToken'}, - 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), - 'expires': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'key': ('django.db.models.fields.CharField', [], {'max_length': '40', 'primary_key': 'True'}), - 'modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), - 'request_hash': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '40', 'blank': 'True'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'auth_tokens'", 'to': u"orm['auth.User']"}) - }, - 'main.credential': { - 'Meta': {'ordering': "('kind', 'name')", 'unique_together': "[('user', 'team', 'kind', 'name')]", 'object_name': 'Credential'}, - 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'cloud': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'created': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), - 'created_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'credential\', \'app_label\': \'main\'}(class)s_created+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), - 'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), - 'host': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'kind': ('django.db.models.fields.CharField', [], {'default': "'ssh'", 'max_length': '32'}), - 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), - 'modified_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'credential\', \'app_label\': \'main\'}(class)s_modified+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}), - 'password': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), - 'project': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '100', 'blank': 'True'}), - 'ssh_key_data': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), - 'ssh_key_unlock': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), - 'su_password': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), - 'su_username': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), - 'sudo_password': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), - 'sudo_username': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), - 'team': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'credentials'", 'null': 'True', 'blank': 'True', 'to': "orm['main.Team']"}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'credentials'", 'null': 'True', 'blank': 'True', 'to': u"orm['auth.User']"}), - 'username': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), - 'vault_password': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}) - }, - 'main.custominventoryscript': { - 'Meta': {'ordering': "('name',)", 'object_name': 'CustomInventoryScript'}, - 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'created': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), - 'created_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'custominventoryscript\', \'app_label\': \'main\'}(class)s_created+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), - 'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), - 'modified_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'custominventoryscript\', \'app_label\': \'main\'}(class)s_modified+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), - 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '512'}), - 'script': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}) - }, - 'main.group': { - 'Meta': {'ordering': "('name',)", 'unique_together': "(('name', 'inventory'),)", 'object_name': 'Group'}, - 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'created': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), - 'created_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'group\', \'app_label\': \'main\'}(class)s_created+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), - 'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), - 'groups_with_active_failures': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), - 'has_active_failures': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'has_inventory_sources': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'hosts': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'groups'", 'blank': 'True', 'to': "orm['main.Host']"}), - 'hosts_with_active_failures': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'inventory': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'groups'", 'to': "orm['main.Inventory']"}), - 'inventory_sources': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'groups'", 'symmetrical': 'False', 'to': "orm['main.InventorySource']"}), - 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), - 'modified_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'group\', \'app_label\': \'main\'}(class)s_modified+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}), - 'parents': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'children'", 'blank': 'True', 'to': "orm['main.Group']"}), - 'total_groups': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), - 'total_hosts': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), - 'variables': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}) - }, - 'main.host': { - 'Meta': {'ordering': "('inventory', 'name')", 'unique_together': "(('name', 'inventory'),)", 'object_name': 'Host'}, - 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'created': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), - 'created_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'host\', \'app_label\': \'main\'}(class)s_created+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), - 'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), - 'enabled': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'has_active_failures': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'has_inventory_sources': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'instance_id': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '100', 'blank': 'True'}), - 'inventory': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'hosts'", 'to': "orm['main.Inventory']"}), - 'inventory_sources': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'hosts'", 'symmetrical': 'False', 'to': "orm['main.InventorySource']"}), - 'last_job': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'hosts_as_last_job+'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Job']"}), - 'last_job_host_summary': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'hosts_as_last_job_summary+'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.JobHostSummary']", 'blank': 'True', 'null': 'True'}), - 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), - 'modified_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'host\', \'app_label\': \'main\'}(class)s_modified+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}), - 'variables': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}) - }, - 'main.inventory': { - 'Meta': {'ordering': "('name',)", 'unique_together': "[('name', 'organization')]", 'object_name': 'Inventory'}, - 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'created': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), - 'created_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'inventory\', \'app_label\': \'main\'}(class)s_created+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), - 'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), - 'groups_with_active_failures': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), - 'has_active_failures': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'has_inventory_sources': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'hosts_with_active_failures': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'inventory_sources_with_failures': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), - 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), - 'modified_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'inventory\', \'app_label\': \'main\'}(class)s_modified+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), - 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '512'}), - 'organization': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'inventories'", 'to': "orm['main.Organization']"}), - 'total_groups': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), - 'total_hosts': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), - 'total_inventory_sources': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), - 'variables': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}) - }, - 'main.inventorysource': { - 'Meta': {'object_name': 'InventorySource', '_ormbases': ['main.UnifiedJobTemplate']}, - 'credential': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'inventorysources'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.Credential']", 'blank': 'True', 'null': 'True'}), - 'group': ('awx.main.fields.AutoOneToOneField', [], {'default': 'None', 'related_name': "'inventory_source'", 'unique': 'True', 'null': 'True', 'to': "orm['main.Group']"}), - 'inventory': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'inventory_sources'", 'null': 'True', 'to': "orm['main.Inventory']"}), - 'overwrite': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'overwrite_vars': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'source': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '32', 'blank': 'True'}), - 'source_path': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), - 'source_regions': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), - 'source_script': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': "orm['main.CustomInventoryScript']", 'null': 'True', 'on_delete': 'models.SET_NULL', 'blank': 'True'}), - 'source_vars': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), - u'unifiedjobtemplate_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['main.UnifiedJobTemplate']", 'unique': 'True', 'primary_key': 'True'}), - 'update_cache_timeout': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), - 'update_on_launch': ('django.db.models.fields.BooleanField', [], {'default': 'False'}) - }, - 'main.inventoryupdate': { - 'Meta': {'object_name': 'InventoryUpdate', '_ormbases': ['main.UnifiedJob']}, - 'credential': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'inventoryupdates'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.Credential']", 'blank': 'True', 'null': 'True'}), - 'inventory_source': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'inventory_updates'", 'to': "orm['main.InventorySource']"}), - 'license_error': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'overwrite': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'overwrite_vars': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'source': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '32', 'blank': 'True'}), - 'source_path': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), - 'source_regions': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), - 'source_script': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': "orm['main.CustomInventoryScript']", 'null': 'True', 'on_delete': 'models.SET_NULL', 'blank': 'True'}), - 'source_vars': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), - u'unifiedjob_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['main.UnifiedJob']", 'unique': 'True', 'primary_key': 'True'}) - }, - 'main.job': { - 'Meta': {'ordering': "('id',)", 'object_name': 'Job', '_ormbases': ['main.UnifiedJob']}, - 'cloud_credential': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobs_as_cloud_credential+'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.Credential']", 'blank': 'True', 'null': 'True'}), - 'credential': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobs'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.Credential']", 'blank': 'True', 'null': 'True'}), - 'extra_vars': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), - 'force_handlers': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'forks': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0', 'blank': 'True'}), - 'hosts': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'jobs'", 'symmetrical': 'False', 'through': "orm['main.JobHostSummary']", 'to': "orm['main.Host']"}), - 'inventory': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobs'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Inventory']"}), - 'job_tags': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), - 'job_template': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobs'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.JobTemplate']", 'blank': 'True', 'null': 'True'}), - 'job_type': ('django.db.models.fields.CharField', [], {'max_length': '64'}), - 'limit': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), - 'playbook': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024'}), - 'project': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobs'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Project']"}), - 'skip_tags': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), - 'start_at_task': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), - u'unifiedjob_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['main.UnifiedJob']", 'unique': 'True', 'primary_key': 'True'}), - 'verbosity': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0', 'blank': 'True'}) - }, - 'main.jobevent': { - 'Meta': {'ordering': "('pk',)", 'object_name': 'JobEvent'}, - 'changed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'counter': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), - 'created': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), - 'event': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'event_data': ('jsonfield.fields.JSONField', [], {'default': '{}', 'blank': 'True'}), - 'failed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'host': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'job_events_as_primary_host'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Host']"}), - 'host_name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024'}), - 'hosts': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'job_events'", 'symmetrical': 'False', 'to': "orm['main.Host']"}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'job': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'job_events'", 'to': "orm['main.Job']"}), - 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), - 'parent': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'children'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.JobEvent']"}), - 'play': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024'}), - 'role': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024'}), - 'task': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024'}) - }, - 'main.jobhostsummary': { - 'Meta': {'ordering': "('-pk',)", 'unique_together': "[('job', 'host_name')]", 'object_name': 'JobHostSummary'}, - 'changed': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), - 'created': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), - 'dark': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), - 'failed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'failures': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), - 'host': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'job_host_summaries'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Host']"}), - 'host_name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'job': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'job_host_summaries'", 'to': "orm['main.Job']"}), - 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), - 'ok': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), - 'processed': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), - 'skipped': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}) - }, - 'main.jobtemplate': { - 'Meta': {'ordering': "('name',)", 'object_name': 'JobTemplate', '_ormbases': ['main.UnifiedJobTemplate']}, - 'ask_variables_on_launch': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'cloud_credential': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobtemplates_as_cloud_credential+'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.Credential']", 'blank': 'True', 'null': 'True'}), - 'credential': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobtemplates'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.Credential']", 'blank': 'True', 'null': 'True'}), - 'extra_vars': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), - 'force_handlers': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'forks': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0', 'blank': 'True'}), - 'host_config_key': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), - 'inventory': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobtemplates'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Inventory']"}), - 'job_tags': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), - 'job_type': ('django.db.models.fields.CharField', [], {'max_length': '64'}), - 'limit': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), - 'playbook': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024'}), - 'project': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobtemplates'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Project']"}), - 'skip_tags': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), - 'start_at_task': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), - 'survey_enabled': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'survey_spec': ('jsonfield.fields.JSONField', [], {'default': '{}', 'blank': 'True'}), - u'unifiedjobtemplate_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['main.UnifiedJobTemplate']", 'unique': 'True', 'primary_key': 'True'}), - 'verbosity': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0', 'blank': 'True'}) - }, - 'main.organization': { - 'Meta': {'ordering': "('name',)", 'object_name': 'Organization'}, - 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'admins': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'admin_of_organizations'", 'blank': 'True', 'to': u"orm['auth.User']"}), - 'created': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), - 'created_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'organization\', \'app_label\': \'main\'}(class)s_created+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), - 'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), - 'modified_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'organization\', \'app_label\': \'main\'}(class)s_modified+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), - 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '512'}), - 'projects': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'organizations'", 'blank': 'True', 'to': "orm['main.Project']"}), - 'users': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'organizations'", 'blank': 'True', 'to': u"orm['auth.User']"}) - }, - 'main.permission': { - 'Meta': {'object_name': 'Permission'}, - 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'created': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), - 'created_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'permission\', \'app_label\': \'main\'}(class)s_created+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), - 'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'inventory': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'permissions'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Inventory']"}), - 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), - 'modified_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'permission\', \'app_label\': \'main\'}(class)s_modified+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}), - 'permission_type': ('django.db.models.fields.CharField', [], {'max_length': '64'}), - 'project': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'permissions'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Project']"}), - 'team': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'permissions'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Team']"}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'permissions'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}) - }, - 'main.profile': { - 'Meta': {'object_name': 'Profile'}, - 'created': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'ldap_dn': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024'}), - 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), - 'user': ('awx.main.fields.AutoOneToOneField', [], {'related_name': "'profile'", 'unique': 'True', 'to': u"orm['auth.User']"}) - }, - 'main.project': { - 'Meta': {'ordering': "('id',)", 'object_name': 'Project', '_ormbases': ['main.UnifiedJobTemplate']}, - 'credential': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'projects'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.Credential']", 'blank': 'True', 'null': 'True'}), - 'local_path': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'blank': 'True'}), - 'scm_branch': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '256', 'blank': 'True'}), - 'scm_clean': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'scm_delete_on_next_update': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'scm_delete_on_update': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'scm_type': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '8', 'blank': 'True'}), - 'scm_update_cache_timeout': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), - 'scm_update_on_launch': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'scm_url': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), - u'unifiedjobtemplate_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['main.UnifiedJobTemplate']", 'unique': 'True', 'primary_key': 'True'}) - }, - 'main.projectupdate': { - 'Meta': {'object_name': 'ProjectUpdate', '_ormbases': ['main.UnifiedJob']}, - 'credential': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'projectupdates'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.Credential']", 'blank': 'True', 'null': 'True'}), - 'local_path': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'blank': 'True'}), - 'project': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'project_updates'", 'to': "orm['main.Project']"}), - 'scm_branch': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '256', 'blank': 'True'}), - 'scm_clean': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'scm_delete_on_update': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'scm_type': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '8', 'blank': 'True'}), - 'scm_url': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), - u'unifiedjob_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['main.UnifiedJob']", 'unique': 'True', 'primary_key': 'True'}) - }, - 'main.schedule': { - 'Meta': {'ordering': "['-next_run']", 'object_name': 'Schedule'}, - 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'created': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), - 'created_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'schedule\', \'app_label\': \'main\'}(class)s_created+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), - 'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), - 'dtend': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}), - 'dtstart': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}), - 'enabled': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'extra_data': ('jsonfield.fields.JSONField', [], {'default': '{}', 'blank': 'True'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), - 'modified_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'schedule\', \'app_label\': \'main\'}(class)s_modified+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), - 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '512'}), - 'next_run': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}), - 'rrule': ('django.db.models.fields.CharField', [], {'max_length': '255'}), - 'unified_job_template': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'schedules'", 'to': "orm['main.UnifiedJobTemplate']"}) - }, - 'main.systemjob': { - 'Meta': {'ordering': "('id',)", 'object_name': 'SystemJob', '_ormbases': ['main.UnifiedJob']}, - 'extra_vars': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), - 'job_type': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '32', 'blank': 'True'}), - 'system_job_template': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobs'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.SystemJobTemplate']", 'blank': 'True', 'null': 'True'}), - u'unifiedjob_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['main.UnifiedJob']", 'unique': 'True', 'primary_key': 'True'}) - }, - 'main.systemjobtemplate': { - 'Meta': {'object_name': 'SystemJobTemplate', '_ormbases': ['main.UnifiedJobTemplate']}, - 'job_type': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '32', 'blank': 'True'}), - u'unifiedjobtemplate_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['main.UnifiedJobTemplate']", 'unique': 'True', 'primary_key': 'True'}) - }, - 'main.team': { - 'Meta': {'ordering': "('organization__name', 'name')", 'unique_together': "[('organization', 'name')]", 'object_name': 'Team'}, - 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'created': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), - 'created_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'team\', \'app_label\': \'main\'}(class)s_created+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), - 'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), - 'modified_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'team\', \'app_label\': \'main\'}(class)s_modified+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}), - 'organization': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'teams'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Organization']"}), - 'projects': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'teams'", 'blank': 'True', 'to': "orm['main.Project']"}), - 'users': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'teams'", 'blank': 'True', 'to': u"orm['auth.User']"}) - }, - 'main.unifiedjob': { - 'Meta': {'object_name': 'UnifiedJob'}, - 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'cancel_flag': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'celery_task_id': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '100', 'blank': 'True'}), - 'created': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), - 'created_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'unifiedjob\', \'app_label\': \'main\'}(class)s_created+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), - 'dependent_jobs': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'dependent_jobs_rel_+'", 'to': "orm['main.UnifiedJob']"}), - 'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), - 'elapsed': ('django.db.models.fields.DecimalField', [], {'max_digits': '12', 'decimal_places': '3'}), - 'failed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'finished': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'job_args': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), - 'job_cwd': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), - 'job_env': ('jsonfield.fields.JSONField', [], {'default': '{}', 'blank': 'True'}), - 'job_explanation': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), - 'launch_type': ('django.db.models.fields.CharField', [], {'default': "'manual'", 'max_length': '20'}), - 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), - 'modified_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'unifiedjob\', \'app_label\': \'main\'}(class)s_modified+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}), - 'old_pk': ('django.db.models.fields.PositiveIntegerField', [], {'default': 'None', 'null': 'True'}), - 'polymorphic_ctype': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'polymorphic_main.unifiedjob_set'", 'null': 'True', 'to': u"orm['contenttypes.ContentType']"}), - 'result_stdout_file': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), - 'result_stdout_text': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), - 'result_traceback': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), - 'schedule': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': "orm['main.Schedule']", 'null': 'True', 'on_delete': 'models.SET_NULL'}), - 'start_args': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), - 'started': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}), - 'status': ('django.db.models.fields.CharField', [], {'default': "'new'", 'max_length': '20'}), - 'unified_job_template': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'unifiedjob_unified_jobs'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.UnifiedJobTemplate']"}) - }, - 'main.unifiedjobtemplate': { - 'Meta': {'unique_together': "[('polymorphic_ctype', 'name')]", 'object_name': 'UnifiedJobTemplate'}, - 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'created': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), - 'created_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'unifiedjobtemplate\', \'app_label\': \'main\'}(class)s_created+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), - 'current_job': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'unifiedjobtemplate_as_current_job+'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.UnifiedJob']"}), - 'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), - 'has_schedules': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'last_job': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'unifiedjobtemplate_as_last_job+'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.UnifiedJob']"}), - 'last_job_failed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'last_job_run': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}), - 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), - 'modified_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'unifiedjobtemplate\', \'app_label\': \'main\'}(class)s_modified+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}), - 'next_job_run': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}), - 'next_schedule': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'unifiedjobtemplate_as_next_schedule+'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Schedule']"}), - 'old_pk': ('django.db.models.fields.PositiveIntegerField', [], {'default': 'None', 'null': 'True'}), - 'polymorphic_ctype': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'polymorphic_main.unifiedjobtemplate_set'", 'null': 'True', 'to': u"orm['contenttypes.ContentType']"}), - 'status': ('django.db.models.fields.CharField', [], {'default': "'ok'", 'max_length': '32'}) - } - } - - complete_apps = ['main'] From 841d5ab0851732b3485b6fa2eb4b73bb69e4ef54 Mon Sep 17 00:00:00 2001 From: Luke Sneeringer Date: Fri, 17 Oct 2014 14:01:43 -0500 Subject: [PATCH 31/33] Merging migrations sucks. --- awx/main/migrations/0057_v210_changes.py | 475 +++++++++++++++++++++++ 1 file changed, 475 insertions(+) create mode 100644 awx/main/migrations/0057_v210_changes.py diff --git a/awx/main/migrations/0057_v210_changes.py b/awx/main/migrations/0057_v210_changes.py new file mode 100644 index 0000000000..1ff37aeb7c --- /dev/null +++ b/awx/main/migrations/0057_v210_changes.py @@ -0,0 +1,475 @@ +# -*- coding: utf-8 -*- +from south.utils import datetime_utils as datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + + +class Migration(SchemaMigration): + + def forwards(self, orm): + # Adding field 'Schedule.extra_data' + db.add_column(u'main_schedule', 'extra_data', + self.gf('jsonfield.fields.JSONField')(default={}, blank=True), + keep_default=False) + + # Adding field 'SystemJob.extra_vars' + db.add_column(u'main_systemjob', 'extra_vars', + self.gf('django.db.models.fields.TextField')(default='', blank=True), + keep_default=False) + + + def backwards(self, orm): + # Deleting field 'Schedule.extra_data' + db.delete_column(u'main_schedule', 'extra_data') + + # Deleting field 'SystemJob.extra_vars' + db.delete_column(u'main_systemjob', 'extra_vars') + + + models = { + u'auth.group': { + 'Meta': {'object_name': 'Group'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + u'auth.permission': { + 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + u'auth.user': { + 'Meta': {'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + u'contenttypes.contenttype': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + 'main.activitystream': { + 'Meta': {'object_name': 'ActivityStream'}, + 'actor': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'activity_stream'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), + 'changes': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'credential': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.Credential']", 'symmetrical': 'False', 'blank': 'True'}), + 'group': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.Group']", 'symmetrical': 'False', 'blank': 'True'}), + 'host': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.Host']", 'symmetrical': 'False', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'inventory': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.Inventory']", 'symmetrical': 'False', 'blank': 'True'}), + 'inventory_source': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.InventorySource']", 'symmetrical': 'False', 'blank': 'True'}), + 'inventory_update': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.InventoryUpdate']", 'symmetrical': 'False', 'blank': 'True'}), + 'job': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.Job']", 'symmetrical': 'False', 'blank': 'True'}), + 'job_template': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.JobTemplate']", 'symmetrical': 'False', 'blank': 'True'}), + 'object1': ('django.db.models.fields.TextField', [], {}), + 'object2': ('django.db.models.fields.TextField', [], {}), + 'object_relationship_type': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'operation': ('django.db.models.fields.CharField', [], {'max_length': '13'}), + 'organization': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.Organization']", 'symmetrical': 'False', 'blank': 'True'}), + 'permission': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.Permission']", 'symmetrical': 'False', 'blank': 'True'}), + 'project': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.Project']", 'symmetrical': 'False', 'blank': 'True'}), + 'project_update': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.ProjectUpdate']", 'symmetrical': 'False', 'blank': 'True'}), + 'schedule': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.Schedule']", 'symmetrical': 'False', 'blank': 'True'}), + 'team': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.Team']", 'symmetrical': 'False', 'blank': 'True'}), + 'timestamp': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'unified_job': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'activity_stream_as_unified_job+'", 'blank': 'True', 'to': "orm['main.UnifiedJob']"}), + 'unified_job_template': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'activity_stream_as_unified_job_template+'", 'blank': 'True', 'to': "orm['main.UnifiedJobTemplate']"}), + 'user': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.User']", 'symmetrical': 'False', 'blank': 'True'}) + }, + 'main.authtoken': { + 'Meta': {'object_name': 'AuthToken'}, + 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'expires': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'key': ('django.db.models.fields.CharField', [], {'max_length': '40', 'primary_key': 'True'}), + 'modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), + 'request_hash': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '40', 'blank': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'auth_tokens'", 'to': u"orm['auth.User']"}) + }, + 'main.credential': { + 'Meta': {'ordering': "('kind', 'name')", 'unique_together': "[('user', 'team', 'kind', 'name')]", 'object_name': 'Credential'}, + 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'cloud': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'created': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'created_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'credential\', \'app_label\': \'main\'}(class)s_created+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), + 'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'host': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'kind': ('django.db.models.fields.CharField', [], {'default': "'ssh'", 'max_length': '32'}), + 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'modified_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'credential\', \'app_label\': \'main\'}(class)s_modified+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}), + 'password': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), + 'project': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '100', 'blank': 'True'}), + 'ssh_key_data': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'ssh_key_unlock': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), + 'su_password': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), + 'su_username': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), + 'sudo_password': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), + 'sudo_username': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), + 'team': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'credentials'", 'null': 'True', 'blank': 'True', 'to': "orm['main.Team']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'credentials'", 'null': 'True', 'blank': 'True', 'to': u"orm['auth.User']"}), + 'username': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), + 'vault_password': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}) + }, + 'main.custominventoryscript': { + 'Meta': {'ordering': "('name',)", 'object_name': 'CustomInventoryScript'}, + 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'created': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'created_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'custominventoryscript\', \'app_label\': \'main\'}(class)s_created+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), + 'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'modified_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'custominventoryscript\', \'app_label\': \'main\'}(class)s_modified+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '512'}), + 'script': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}) + }, + 'main.group': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('name', 'inventory'),)", 'object_name': 'Group'}, + 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'created': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'created_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'group\', \'app_label\': \'main\'}(class)s_created+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), + 'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'groups_with_active_failures': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'has_active_failures': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'has_inventory_sources': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'hosts': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'groups'", 'blank': 'True', 'to': "orm['main.Host']"}), + 'hosts_with_active_failures': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'inventory': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'groups'", 'to': "orm['main.Inventory']"}), + 'inventory_sources': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'groups'", 'symmetrical': 'False', 'to': "orm['main.InventorySource']"}), + 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'modified_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'group\', \'app_label\': \'main\'}(class)s_modified+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}), + 'parents': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'children'", 'blank': 'True', 'to': "orm['main.Group']"}), + 'total_groups': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'total_hosts': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'variables': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}) + }, + 'main.host': { + 'Meta': {'ordering': "('inventory', 'name')", 'unique_together': "(('name', 'inventory'),)", 'object_name': 'Host'}, + 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'created': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'created_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'host\', \'app_label\': \'main\'}(class)s_created+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), + 'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'enabled': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'has_active_failures': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'has_inventory_sources': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'instance_id': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '100', 'blank': 'True'}), + 'inventory': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'hosts'", 'to': "orm['main.Inventory']"}), + 'inventory_sources': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'hosts'", 'symmetrical': 'False', 'to': "orm['main.InventorySource']"}), + 'last_job': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'hosts_as_last_job+'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Job']"}), + 'last_job_host_summary': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'hosts_as_last_job_summary+'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.JobHostSummary']", 'blank': 'True', 'null': 'True'}), + 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'modified_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'host\', \'app_label\': \'main\'}(class)s_modified+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}), + 'variables': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}) + }, + 'main.inventory': { + 'Meta': {'ordering': "('name',)", 'unique_together': "[('name', 'organization')]", 'object_name': 'Inventory'}, + 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'created': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'created_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'inventory\', \'app_label\': \'main\'}(class)s_created+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), + 'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'groups_with_active_failures': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'has_active_failures': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'has_inventory_sources': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'hosts_with_active_failures': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'inventory_sources_with_failures': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'modified_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'inventory\', \'app_label\': \'main\'}(class)s_modified+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '512'}), + 'organization': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'inventories'", 'to': "orm['main.Organization']"}), + 'total_groups': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'total_hosts': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'total_inventory_sources': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'variables': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}) + }, + 'main.inventorysource': { + 'Meta': {'object_name': 'InventorySource', '_ormbases': ['main.UnifiedJobTemplate']}, + 'credential': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'inventorysources'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.Credential']", 'blank': 'True', 'null': 'True'}), + 'group': ('awx.main.fields.AutoOneToOneField', [], {'default': 'None', 'related_name': "'inventory_source'", 'unique': 'True', 'null': 'True', 'to': "orm['main.Group']"}), + 'inventory': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'inventory_sources'", 'null': 'True', 'to': "orm['main.Inventory']"}), + 'overwrite': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'overwrite_vars': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'source': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '32', 'blank': 'True'}), + 'source_path': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), + 'source_regions': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), + 'source_script': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': "orm['main.CustomInventoryScript']", 'null': 'True', 'on_delete': 'models.SET_NULL', 'blank': 'True'}), + 'source_vars': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + u'unifiedjobtemplate_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['main.UnifiedJobTemplate']", 'unique': 'True', 'primary_key': 'True'}), + 'update_cache_timeout': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'update_on_launch': ('django.db.models.fields.BooleanField', [], {'default': 'False'}) + }, + 'main.inventoryupdate': { + 'Meta': {'object_name': 'InventoryUpdate', '_ormbases': ['main.UnifiedJob']}, + 'credential': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'inventoryupdates'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.Credential']", 'blank': 'True', 'null': 'True'}), + 'inventory_source': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'inventory_updates'", 'to': "orm['main.InventorySource']"}), + 'license_error': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'overwrite': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'overwrite_vars': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'source': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '32', 'blank': 'True'}), + 'source_path': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), + 'source_regions': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), + 'source_script': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': "orm['main.CustomInventoryScript']", 'null': 'True', 'on_delete': 'models.SET_NULL', 'blank': 'True'}), + 'source_vars': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + u'unifiedjob_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['main.UnifiedJob']", 'unique': 'True', 'primary_key': 'True'}) + }, + 'main.job': { + 'Meta': {'ordering': "('id',)", 'object_name': 'Job', '_ormbases': ['main.UnifiedJob']}, + 'cloud_credential': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobs_as_cloud_credential+'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.Credential']", 'blank': 'True', 'null': 'True'}), + 'credential': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobs'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.Credential']", 'blank': 'True', 'null': 'True'}), + 'extra_vars': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'force_handlers': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'forks': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0', 'blank': 'True'}), + 'hosts': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'jobs'", 'symmetrical': 'False', 'through': "orm['main.JobHostSummary']", 'to': "orm['main.Host']"}), + 'inventory': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobs'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Inventory']"}), + 'job_tags': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), + 'job_template': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobs'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.JobTemplate']", 'blank': 'True', 'null': 'True'}), + 'job_type': ('django.db.models.fields.CharField', [], {'max_length': '64'}), + 'limit': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), + 'playbook': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024'}), + 'project': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobs'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Project']"}), + 'skip_tags': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), + 'start_at_task': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), + u'unifiedjob_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['main.UnifiedJob']", 'unique': 'True', 'primary_key': 'True'}), + 'verbosity': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0', 'blank': 'True'}) + }, + 'main.jobevent': { + 'Meta': {'ordering': "('pk',)", 'object_name': 'JobEvent'}, + 'changed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'counter': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'created': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'event': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'event_data': ('jsonfield.fields.JSONField', [], {'default': '{}', 'blank': 'True'}), + 'failed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'host': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'job_events_as_primary_host'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Host']"}), + 'host_name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024'}), + 'hosts': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'job_events'", 'symmetrical': 'False', 'to': "orm['main.Host']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'job': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'job_events'", 'to': "orm['main.Job']"}), + 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'parent': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'children'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.JobEvent']"}), + 'play': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024'}), + 'role': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024'}), + 'task': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024'}) + }, + 'main.jobhostsummary': { + 'Meta': {'ordering': "('-pk',)", 'unique_together': "[('job', 'host_name')]", 'object_name': 'JobHostSummary'}, + 'changed': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'created': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'dark': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'failed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'failures': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'host': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'job_host_summaries'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Host']"}), + 'host_name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'job': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'job_host_summaries'", 'to': "orm['main.Job']"}), + 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'ok': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'processed': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'skipped': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}) + }, + 'main.jobtemplate': { + 'Meta': {'ordering': "('name',)", 'object_name': 'JobTemplate', '_ormbases': ['main.UnifiedJobTemplate']}, + 'ask_variables_on_launch': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'cloud_credential': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobtemplates_as_cloud_credential+'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.Credential']", 'blank': 'True', 'null': 'True'}), + 'credential': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobtemplates'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.Credential']", 'blank': 'True', 'null': 'True'}), + 'extra_vars': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'force_handlers': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'forks': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0', 'blank': 'True'}), + 'host_config_key': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), + 'inventory': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobtemplates'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Inventory']"}), + 'job_tags': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), + 'job_type': ('django.db.models.fields.CharField', [], {'max_length': '64'}), + 'limit': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), + 'playbook': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024'}), + 'project': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobtemplates'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Project']"}), + 'skip_tags': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), + 'start_at_task': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), + 'survey_enabled': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'survey_spec': ('jsonfield.fields.JSONField', [], {'default': '{}', 'blank': 'True'}), + u'unifiedjobtemplate_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['main.UnifiedJobTemplate']", 'unique': 'True', 'primary_key': 'True'}), + 'verbosity': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0', 'blank': 'True'}) + }, + 'main.organization': { + 'Meta': {'ordering': "('name',)", 'object_name': 'Organization'}, + 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'admins': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'admin_of_organizations'", 'blank': 'True', 'to': u"orm['auth.User']"}), + 'created': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'created_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'organization\', \'app_label\': \'main\'}(class)s_created+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), + 'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'modified_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'organization\', \'app_label\': \'main\'}(class)s_modified+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '512'}), + 'projects': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'organizations'", 'blank': 'True', 'to': "orm['main.Project']"}), + 'users': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'organizations'", 'blank': 'True', 'to': u"orm['auth.User']"}) + }, + 'main.permission': { + 'Meta': {'object_name': 'Permission'}, + 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'created': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'created_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'permission\', \'app_label\': \'main\'}(class)s_created+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), + 'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'inventory': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'permissions'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Inventory']"}), + 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'modified_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'permission\', \'app_label\': \'main\'}(class)s_modified+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}), + 'permission_type': ('django.db.models.fields.CharField', [], {'max_length': '64'}), + 'project': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'permissions'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Project']"}), + 'team': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'permissions'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Team']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'permissions'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}) + }, + 'main.profile': { + 'Meta': {'object_name': 'Profile'}, + 'created': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'ldap_dn': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024'}), + 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'user': ('awx.main.fields.AutoOneToOneField', [], {'related_name': "'profile'", 'unique': 'True', 'to': u"orm['auth.User']"}) + }, + 'main.project': { + 'Meta': {'ordering': "('id',)", 'object_name': 'Project', '_ormbases': ['main.UnifiedJobTemplate']}, + 'credential': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'projects'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.Credential']", 'blank': 'True', 'null': 'True'}), + 'local_path': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'blank': 'True'}), + 'scm_branch': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '256', 'blank': 'True'}), + 'scm_clean': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'scm_delete_on_next_update': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'scm_delete_on_update': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'scm_type': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '8', 'blank': 'True'}), + 'scm_update_cache_timeout': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'scm_update_on_launch': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'scm_url': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), + u'unifiedjobtemplate_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['main.UnifiedJobTemplate']", 'unique': 'True', 'primary_key': 'True'}) + }, + 'main.projectupdate': { + 'Meta': {'object_name': 'ProjectUpdate', '_ormbases': ['main.UnifiedJob']}, + 'credential': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'projectupdates'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.Credential']", 'blank': 'True', 'null': 'True'}), + 'local_path': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'blank': 'True'}), + 'project': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'project_updates'", 'to': "orm['main.Project']"}), + 'scm_branch': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '256', 'blank': 'True'}), + 'scm_clean': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'scm_delete_on_update': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'scm_type': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '8', 'blank': 'True'}), + 'scm_url': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), + u'unifiedjob_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['main.UnifiedJob']", 'unique': 'True', 'primary_key': 'True'}) + }, + 'main.schedule': { + 'Meta': {'ordering': "['-next_run']", 'object_name': 'Schedule'}, + 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'created': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'created_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'schedule\', \'app_label\': \'main\'}(class)s_created+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), + 'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'dtend': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}), + 'dtstart': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}), + 'enabled': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'extra_data': ('jsonfield.fields.JSONField', [], {'default': '{}', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'modified_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'schedule\', \'app_label\': \'main\'}(class)s_modified+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '512'}), + 'next_run': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}), + 'rrule': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'unified_job_template': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'schedules'", 'to': "orm['main.UnifiedJobTemplate']"}) + }, + 'main.systemjob': { + 'Meta': {'ordering': "('id',)", 'object_name': 'SystemJob', '_ormbases': ['main.UnifiedJob']}, + 'extra_vars': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'job_type': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '32', 'blank': 'True'}), + 'system_job_template': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobs'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.SystemJobTemplate']", 'blank': 'True', 'null': 'True'}), + u'unifiedjob_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['main.UnifiedJob']", 'unique': 'True', 'primary_key': 'True'}) + }, + 'main.systemjobtemplate': { + 'Meta': {'object_name': 'SystemJobTemplate', '_ormbases': ['main.UnifiedJobTemplate']}, + 'job_type': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '32', 'blank': 'True'}), + u'unifiedjobtemplate_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['main.UnifiedJobTemplate']", 'unique': 'True', 'primary_key': 'True'}) + }, + 'main.team': { + 'Meta': {'ordering': "('organization__name', 'name')", 'unique_together': "[('organization', 'name')]", 'object_name': 'Team'}, + 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'created': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'created_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'team\', \'app_label\': \'main\'}(class)s_created+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), + 'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'modified_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'team\', \'app_label\': \'main\'}(class)s_modified+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}), + 'organization': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'teams'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Organization']"}), + 'projects': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'teams'", 'blank': 'True', 'to': "orm['main.Project']"}), + 'users': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'teams'", 'blank': 'True', 'to': u"orm['auth.User']"}) + }, + 'main.unifiedjob': { + 'Meta': {'object_name': 'UnifiedJob'}, + 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'cancel_flag': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'celery_task_id': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '100', 'blank': 'True'}), + 'created': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'created_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'unifiedjob\', \'app_label\': \'main\'}(class)s_created+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), + 'dependent_jobs': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'dependent_jobs_rel_+'", 'to': "orm['main.UnifiedJob']"}), + 'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'elapsed': ('django.db.models.fields.DecimalField', [], {'max_digits': '12', 'decimal_places': '3'}), + 'failed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'finished': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'job_args': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'job_cwd': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), + 'job_env': ('jsonfield.fields.JSONField', [], {'default': '{}', 'blank': 'True'}), + 'job_explanation': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'launch_type': ('django.db.models.fields.CharField', [], {'default': "'manual'", 'max_length': '20'}), + 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'modified_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'unifiedjob\', \'app_label\': \'main\'}(class)s_modified+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}), + 'old_pk': ('django.db.models.fields.PositiveIntegerField', [], {'default': 'None', 'null': 'True'}), + 'polymorphic_ctype': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'polymorphic_main.unifiedjob_set'", 'null': 'True', 'to': u"orm['contenttypes.ContentType']"}), + 'result_stdout_file': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'result_stdout_text': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'result_traceback': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'schedule': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': "orm['main.Schedule']", 'null': 'True', 'on_delete': 'models.SET_NULL'}), + 'start_args': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'started': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}), + 'status': ('django.db.models.fields.CharField', [], {'default': "'new'", 'max_length': '20'}), + 'unified_job_template': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'unifiedjob_unified_jobs'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.UnifiedJobTemplate']"}) + }, + 'main.unifiedjobtemplate': { + 'Meta': {'unique_together': "[('polymorphic_ctype', 'name')]", 'object_name': 'UnifiedJobTemplate'}, + 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'created': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'created_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'unifiedjobtemplate\', \'app_label\': \'main\'}(class)s_created+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), + 'current_job': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'unifiedjobtemplate_as_current_job+'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.UnifiedJob']"}), + 'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'has_schedules': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_job': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'unifiedjobtemplate_as_last_job+'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.UnifiedJob']"}), + 'last_job_failed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_job_run': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}), + 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'modified_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'unifiedjobtemplate\', \'app_label\': \'main\'}(class)s_modified+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}), + 'next_job_run': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}), + 'next_schedule': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'unifiedjobtemplate_as_next_schedule+'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Schedule']"}), + 'old_pk': ('django.db.models.fields.PositiveIntegerField', [], {'default': 'None', 'null': 'True'}), + 'polymorphic_ctype': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'polymorphic_main.unifiedjobtemplate_set'", 'null': 'True', 'to': u"orm['contenttypes.ContentType']"}), + 'status': ('django.db.models.fields.CharField', [], {'default': "'ok'", 'max_length': '32'}) + } + } + + complete_apps = ['main'] From 4045a1e4fa8491c24a8b28810ebb675da2c68084 Mon Sep 17 00:00:00 2001 From: Luke Sneeringer Date: Mon, 20 Oct 2014 08:46:39 -0500 Subject: [PATCH 32/33] Migration, again! :) --- awx/main/migrations/0058_v210_changes.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 awx/main/migrations/0058_v210_changes.py diff --git a/awx/main/migrations/0058_v210_changes.py b/awx/main/migrations/0058_v210_changes.py new file mode 100644 index 0000000000..e69de29bb2 From fa82ed56e28086be20a600c101d5df6533c867f0 Mon Sep 17 00:00:00 2001 From: Luke Sneeringer Date: Mon, 20 Oct 2014 10:43:08 -0500 Subject: [PATCH 33/33] Adding Instance/JobOrigin migration --- awx/main/migrations/0058_v210_changes.py | 503 +++++++++++++++++++++++ 1 file changed, 503 insertions(+) diff --git a/awx/main/migrations/0058_v210_changes.py b/awx/main/migrations/0058_v210_changes.py index e69de29bb2..5abb296cf3 100644 --- a/awx/main/migrations/0058_v210_changes.py +++ b/awx/main/migrations/0058_v210_changes.py @@ -0,0 +1,503 @@ +# -*- coding: utf-8 -*- +from south.utils import datetime_utils as datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + + +class Migration(SchemaMigration): + + def forwards(self, orm): + # Adding model 'Instance' + db.create_table(u'main_instance', ( + (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('uuid', self.gf('django.db.models.fields.CharField')(unique=True, max_length=40)), + ('ip_address', self.gf('django.db.models.fields.GenericIPAddressField')(max_length=39)), + ('primary', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)), + ('modified', self.gf('django.db.models.fields.DateTimeField')(auto_now=True, blank=True)), + )) + db.send_create_signal('main', ['Instance']) + + # Adding model 'JobOrigin' + db.create_table(u'main_joborigin', ( + (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('unified_job', self.gf('django.db.models.fields.related.OneToOneField')(related_name='job_origin', unique=True, to=orm['main.UnifiedJob'])), + ('instance', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['main.Instance'])), + ('created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)), + ('modified', self.gf('django.db.models.fields.DateTimeField')(auto_now=True, blank=True)), + )) + db.send_create_signal('main', ['JobOrigin']) + + + def backwards(self, orm): + # Deleting model 'Instance' + db.delete_table(u'main_instance') + + # Deleting model 'JobOrigin' + db.delete_table(u'main_joborigin') + + + models = { + u'auth.group': { + 'Meta': {'object_name': 'Group'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + u'auth.permission': { + 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + u'auth.user': { + 'Meta': {'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + u'contenttypes.contenttype': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + 'main.activitystream': { + 'Meta': {'object_name': 'ActivityStream'}, + 'actor': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'activity_stream'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), + 'changes': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'credential': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.Credential']", 'symmetrical': 'False', 'blank': 'True'}), + 'group': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.Group']", 'symmetrical': 'False', 'blank': 'True'}), + 'host': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.Host']", 'symmetrical': 'False', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'inventory': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.Inventory']", 'symmetrical': 'False', 'blank': 'True'}), + 'inventory_source': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.InventorySource']", 'symmetrical': 'False', 'blank': 'True'}), + 'inventory_update': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.InventoryUpdate']", 'symmetrical': 'False', 'blank': 'True'}), + 'job': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.Job']", 'symmetrical': 'False', 'blank': 'True'}), + 'job_template': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.JobTemplate']", 'symmetrical': 'False', 'blank': 'True'}), + 'object1': ('django.db.models.fields.TextField', [], {}), + 'object2': ('django.db.models.fields.TextField', [], {}), + 'object_relationship_type': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'operation': ('django.db.models.fields.CharField', [], {'max_length': '13'}), + 'organization': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.Organization']", 'symmetrical': 'False', 'blank': 'True'}), + 'permission': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.Permission']", 'symmetrical': 'False', 'blank': 'True'}), + 'project': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.Project']", 'symmetrical': 'False', 'blank': 'True'}), + 'project_update': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.ProjectUpdate']", 'symmetrical': 'False', 'blank': 'True'}), + 'schedule': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.Schedule']", 'symmetrical': 'False', 'blank': 'True'}), + 'team': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.Team']", 'symmetrical': 'False', 'blank': 'True'}), + 'timestamp': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'unified_job': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'activity_stream_as_unified_job+'", 'blank': 'True', 'to': "orm['main.UnifiedJob']"}), + 'unified_job_template': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'activity_stream_as_unified_job_template+'", 'blank': 'True', 'to': "orm['main.UnifiedJobTemplate']"}), + 'user': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.User']", 'symmetrical': 'False', 'blank': 'True'}) + }, + 'main.authtoken': { + 'Meta': {'object_name': 'AuthToken'}, + 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'expires': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'key': ('django.db.models.fields.CharField', [], {'max_length': '40', 'primary_key': 'True'}), + 'modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), + 'request_hash': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '40', 'blank': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'auth_tokens'", 'to': u"orm['auth.User']"}) + }, + 'main.credential': { + 'Meta': {'ordering': "('kind', 'name')", 'unique_together': "[('user', 'team', 'kind', 'name')]", 'object_name': 'Credential'}, + 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'cloud': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'created': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'created_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'credential\', \'app_label\': \'main\'}(class)s_created+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), + 'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'host': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'kind': ('django.db.models.fields.CharField', [], {'default': "'ssh'", 'max_length': '32'}), + 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'modified_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'credential\', \'app_label\': \'main\'}(class)s_modified+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}), + 'password': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), + 'project': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '100', 'blank': 'True'}), + 'ssh_key_data': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'ssh_key_unlock': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), + 'su_password': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), + 'su_username': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), + 'sudo_password': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), + 'sudo_username': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), + 'team': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'credentials'", 'null': 'True', 'blank': 'True', 'to': "orm['main.Team']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'credentials'", 'null': 'True', 'blank': 'True', 'to': u"orm['auth.User']"}), + 'username': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), + 'vault_password': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}) + }, + 'main.custominventoryscript': { + 'Meta': {'ordering': "('name',)", 'object_name': 'CustomInventoryScript'}, + 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'created': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'created_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'custominventoryscript\', \'app_label\': \'main\'}(class)s_created+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), + 'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'modified_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'custominventoryscript\', \'app_label\': \'main\'}(class)s_modified+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '512'}), + 'script': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}) + }, + 'main.group': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('name', 'inventory'),)", 'object_name': 'Group'}, + 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'created': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'created_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'group\', \'app_label\': \'main\'}(class)s_created+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), + 'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'groups_with_active_failures': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'has_active_failures': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'has_inventory_sources': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'hosts': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'groups'", 'blank': 'True', 'to': "orm['main.Host']"}), + 'hosts_with_active_failures': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'inventory': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'groups'", 'to': "orm['main.Inventory']"}), + 'inventory_sources': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'groups'", 'symmetrical': 'False', 'to': "orm['main.InventorySource']"}), + 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'modified_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'group\', \'app_label\': \'main\'}(class)s_modified+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}), + 'parents': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'children'", 'blank': 'True', 'to': "orm['main.Group']"}), + 'total_groups': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'total_hosts': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'variables': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}) + }, + 'main.host': { + 'Meta': {'ordering': "('inventory', 'name')", 'unique_together': "(('name', 'inventory'),)", 'object_name': 'Host'}, + 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'created': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'created_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'host\', \'app_label\': \'main\'}(class)s_created+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), + 'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'enabled': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'has_active_failures': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'has_inventory_sources': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'instance_id': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '100', 'blank': 'True'}), + 'inventory': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'hosts'", 'to': "orm['main.Inventory']"}), + 'inventory_sources': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'hosts'", 'symmetrical': 'False', 'to': "orm['main.InventorySource']"}), + 'last_job': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'hosts_as_last_job+'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Job']"}), + 'last_job_host_summary': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'hosts_as_last_job_summary+'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.JobHostSummary']", 'blank': 'True', 'null': 'True'}), + 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'modified_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'host\', \'app_label\': \'main\'}(class)s_modified+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}), + 'variables': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}) + }, + 'main.instance': { + 'Meta': {'object_name': 'Instance'}, + 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'ip_address': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39'}), + 'modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), + 'primary': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'uuid': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '40'}) + }, + 'main.inventory': { + 'Meta': {'ordering': "('name',)", 'unique_together': "[('name', 'organization')]", 'object_name': 'Inventory'}, + 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'created': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'created_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'inventory\', \'app_label\': \'main\'}(class)s_created+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), + 'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'groups_with_active_failures': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'has_active_failures': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'has_inventory_sources': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'hosts_with_active_failures': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'inventory_sources_with_failures': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'modified_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'inventory\', \'app_label\': \'main\'}(class)s_modified+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '512'}), + 'organization': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'inventories'", 'to': "orm['main.Organization']"}), + 'total_groups': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'total_hosts': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'total_inventory_sources': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'variables': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}) + }, + 'main.inventorysource': { + 'Meta': {'object_name': 'InventorySource', '_ormbases': ['main.UnifiedJobTemplate']}, + 'credential': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'inventorysources'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.Credential']", 'blank': 'True', 'null': 'True'}), + 'group': ('awx.main.fields.AutoOneToOneField', [], {'default': 'None', 'related_name': "'inventory_source'", 'unique': 'True', 'null': 'True', 'to': "orm['main.Group']"}), + 'inventory': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'inventory_sources'", 'null': 'True', 'to': "orm['main.Inventory']"}), + 'overwrite': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'overwrite_vars': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'source': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '32', 'blank': 'True'}), + 'source_path': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), + 'source_regions': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), + 'source_script': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': "orm['main.CustomInventoryScript']", 'null': 'True', 'on_delete': 'models.SET_NULL', 'blank': 'True'}), + 'source_vars': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + u'unifiedjobtemplate_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['main.UnifiedJobTemplate']", 'unique': 'True', 'primary_key': 'True'}), + 'update_cache_timeout': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'update_on_launch': ('django.db.models.fields.BooleanField', [], {'default': 'False'}) + }, + 'main.inventoryupdate': { + 'Meta': {'object_name': 'InventoryUpdate', '_ormbases': ['main.UnifiedJob']}, + 'credential': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'inventoryupdates'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.Credential']", 'blank': 'True', 'null': 'True'}), + 'inventory_source': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'inventory_updates'", 'to': "orm['main.InventorySource']"}), + 'license_error': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'overwrite': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'overwrite_vars': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'source': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '32', 'blank': 'True'}), + 'source_path': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), + 'source_regions': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), + 'source_script': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': "orm['main.CustomInventoryScript']", 'null': 'True', 'on_delete': 'models.SET_NULL', 'blank': 'True'}), + 'source_vars': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + u'unifiedjob_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['main.UnifiedJob']", 'unique': 'True', 'primary_key': 'True'}) + }, + 'main.job': { + 'Meta': {'ordering': "('id',)", 'object_name': 'Job', '_ormbases': ['main.UnifiedJob']}, + 'cloud_credential': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobs_as_cloud_credential+'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.Credential']", 'blank': 'True', 'null': 'True'}), + 'credential': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobs'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.Credential']", 'blank': 'True', 'null': 'True'}), + 'extra_vars': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'force_handlers': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'forks': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0', 'blank': 'True'}), + 'hosts': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'jobs'", 'symmetrical': 'False', 'through': "orm['main.JobHostSummary']", 'to': "orm['main.Host']"}), + 'inventory': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobs'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Inventory']"}), + 'job_tags': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), + 'job_template': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobs'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.JobTemplate']", 'blank': 'True', 'null': 'True'}), + 'job_type': ('django.db.models.fields.CharField', [], {'max_length': '64'}), + 'limit': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), + 'playbook': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024'}), + 'project': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobs'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Project']"}), + 'skip_tags': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), + 'start_at_task': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), + u'unifiedjob_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['main.UnifiedJob']", 'unique': 'True', 'primary_key': 'True'}), + 'verbosity': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0', 'blank': 'True'}) + }, + 'main.jobevent': { + 'Meta': {'ordering': "('pk',)", 'object_name': 'JobEvent'}, + 'changed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'counter': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'created': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'event': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'event_data': ('jsonfield.fields.JSONField', [], {'default': '{}', 'blank': 'True'}), + 'failed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'host': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'job_events_as_primary_host'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Host']"}), + 'host_name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024'}), + 'hosts': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'job_events'", 'symmetrical': 'False', 'to': "orm['main.Host']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'job': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'job_events'", 'to': "orm['main.Job']"}), + 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'parent': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'children'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.JobEvent']"}), + 'play': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024'}), + 'role': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024'}), + 'task': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024'}) + }, + 'main.jobhostsummary': { + 'Meta': {'ordering': "('-pk',)", 'unique_together': "[('job', 'host_name')]", 'object_name': 'JobHostSummary'}, + 'changed': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'created': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'dark': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'failed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'failures': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'host': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'job_host_summaries'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Host']"}), + 'host_name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'job': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'job_host_summaries'", 'to': "orm['main.Job']"}), + 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'ok': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'processed': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'skipped': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}) + }, + 'main.joborigin': { + 'Meta': {'object_name': 'JobOrigin'}, + 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'instance': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['main.Instance']"}), + 'modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), + 'unified_job': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'job_origin'", 'unique': 'True', 'to': "orm['main.UnifiedJob']"}) + }, + 'main.jobtemplate': { + 'Meta': {'ordering': "('name',)", 'object_name': 'JobTemplate', '_ormbases': ['main.UnifiedJobTemplate']}, + 'ask_variables_on_launch': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'cloud_credential': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobtemplates_as_cloud_credential+'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.Credential']", 'blank': 'True', 'null': 'True'}), + 'credential': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobtemplates'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.Credential']", 'blank': 'True', 'null': 'True'}), + 'extra_vars': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'force_handlers': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'forks': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0', 'blank': 'True'}), + 'host_config_key': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), + 'inventory': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobtemplates'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Inventory']"}), + 'job_tags': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), + 'job_type': ('django.db.models.fields.CharField', [], {'max_length': '64'}), + 'limit': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), + 'playbook': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024'}), + 'project': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobtemplates'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Project']"}), + 'skip_tags': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), + 'start_at_task': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), + 'survey_enabled': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'survey_spec': ('jsonfield.fields.JSONField', [], {'default': '{}', 'blank': 'True'}), + u'unifiedjobtemplate_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['main.UnifiedJobTemplate']", 'unique': 'True', 'primary_key': 'True'}), + 'verbosity': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0', 'blank': 'True'}) + }, + 'main.organization': { + 'Meta': {'ordering': "('name',)", 'object_name': 'Organization'}, + 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'admins': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'admin_of_organizations'", 'blank': 'True', 'to': u"orm['auth.User']"}), + 'created': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'created_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'organization\', \'app_label\': \'main\'}(class)s_created+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), + 'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'modified_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'organization\', \'app_label\': \'main\'}(class)s_modified+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '512'}), + 'projects': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'organizations'", 'blank': 'True', 'to': "orm['main.Project']"}), + 'users': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'organizations'", 'blank': 'True', 'to': u"orm['auth.User']"}) + }, + 'main.permission': { + 'Meta': {'object_name': 'Permission'}, + 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'created': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'created_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'permission\', \'app_label\': \'main\'}(class)s_created+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), + 'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'inventory': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'permissions'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Inventory']"}), + 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'modified_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'permission\', \'app_label\': \'main\'}(class)s_modified+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}), + 'permission_type': ('django.db.models.fields.CharField', [], {'max_length': '64'}), + 'project': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'permissions'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Project']"}), + 'team': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'permissions'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Team']"}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'permissions'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}) + }, + 'main.profile': { + 'Meta': {'object_name': 'Profile'}, + 'created': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'ldap_dn': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024'}), + 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'user': ('awx.main.fields.AutoOneToOneField', [], {'related_name': "'profile'", 'unique': 'True', 'to': u"orm['auth.User']"}) + }, + 'main.project': { + 'Meta': {'ordering': "('id',)", 'object_name': 'Project', '_ormbases': ['main.UnifiedJobTemplate']}, + 'credential': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'projects'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.Credential']", 'blank': 'True', 'null': 'True'}), + 'local_path': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'blank': 'True'}), + 'scm_branch': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '256', 'blank': 'True'}), + 'scm_clean': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'scm_delete_on_next_update': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'scm_delete_on_update': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'scm_type': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '8', 'blank': 'True'}), + 'scm_update_cache_timeout': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'scm_update_on_launch': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'scm_url': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), + u'unifiedjobtemplate_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['main.UnifiedJobTemplate']", 'unique': 'True', 'primary_key': 'True'}) + }, + 'main.projectupdate': { + 'Meta': {'object_name': 'ProjectUpdate', '_ormbases': ['main.UnifiedJob']}, + 'credential': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'projectupdates'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.Credential']", 'blank': 'True', 'null': 'True'}), + 'local_path': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'blank': 'True'}), + 'project': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'project_updates'", 'to': "orm['main.Project']"}), + 'scm_branch': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '256', 'blank': 'True'}), + 'scm_clean': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'scm_delete_on_update': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'scm_type': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '8', 'blank': 'True'}), + 'scm_url': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), + u'unifiedjob_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['main.UnifiedJob']", 'unique': 'True', 'primary_key': 'True'}) + }, + 'main.schedule': { + 'Meta': {'ordering': "['-next_run']", 'object_name': 'Schedule'}, + 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'created': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'created_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'schedule\', \'app_label\': \'main\'}(class)s_created+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), + 'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'dtend': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}), + 'dtstart': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}), + 'enabled': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'extra_data': ('jsonfield.fields.JSONField', [], {'default': '{}', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'modified_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'schedule\', \'app_label\': \'main\'}(class)s_modified+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '512'}), + 'next_run': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}), + 'rrule': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'unified_job_template': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'schedules'", 'to': "orm['main.UnifiedJobTemplate']"}) + }, + 'main.systemjob': { + 'Meta': {'ordering': "('id',)", 'object_name': 'SystemJob', '_ormbases': ['main.UnifiedJob']}, + 'extra_vars': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'job_type': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '32', 'blank': 'True'}), + 'system_job_template': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobs'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.SystemJobTemplate']", 'blank': 'True', 'null': 'True'}), + u'unifiedjob_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['main.UnifiedJob']", 'unique': 'True', 'primary_key': 'True'}) + }, + 'main.systemjobtemplate': { + 'Meta': {'object_name': 'SystemJobTemplate', '_ormbases': ['main.UnifiedJobTemplate']}, + 'job_type': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '32', 'blank': 'True'}), + u'unifiedjobtemplate_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['main.UnifiedJobTemplate']", 'unique': 'True', 'primary_key': 'True'}) + }, + 'main.team': { + 'Meta': {'ordering': "('organization__name', 'name')", 'unique_together': "[('organization', 'name')]", 'object_name': 'Team'}, + 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'created': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'created_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'team\', \'app_label\': \'main\'}(class)s_created+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), + 'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'modified_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'team\', \'app_label\': \'main\'}(class)s_modified+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}), + 'organization': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'teams'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Organization']"}), + 'projects': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'teams'", 'blank': 'True', 'to': "orm['main.Project']"}), + 'users': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'teams'", 'blank': 'True', 'to': u"orm['auth.User']"}) + }, + 'main.unifiedjob': { + 'Meta': {'object_name': 'UnifiedJob'}, + 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'cancel_flag': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'celery_task_id': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '100', 'blank': 'True'}), + 'created': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'created_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'unifiedjob\', \'app_label\': \'main\'}(class)s_created+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), + 'dependent_jobs': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'dependent_jobs_rel_+'", 'to': "orm['main.UnifiedJob']"}), + 'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'elapsed': ('django.db.models.fields.DecimalField', [], {'max_digits': '12', 'decimal_places': '3'}), + 'failed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'finished': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'job_args': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'job_cwd': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), + 'job_env': ('jsonfield.fields.JSONField', [], {'default': '{}', 'blank': 'True'}), + 'job_explanation': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'launch_type': ('django.db.models.fields.CharField', [], {'default': "'manual'", 'max_length': '20'}), + 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'modified_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'unifiedjob\', \'app_label\': \'main\'}(class)s_modified+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}), + 'old_pk': ('django.db.models.fields.PositiveIntegerField', [], {'default': 'None', 'null': 'True'}), + 'polymorphic_ctype': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'polymorphic_main.unifiedjob_set'", 'null': 'True', 'to': u"orm['contenttypes.ContentType']"}), + 'result_stdout_file': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'result_stdout_text': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'result_traceback': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'schedule': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': "orm['main.Schedule']", 'null': 'True', 'on_delete': 'models.SET_NULL'}), + 'start_args': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'started': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}), + 'status': ('django.db.models.fields.CharField', [], {'default': "'new'", 'max_length': '20'}), + 'unified_job_template': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'unifiedjob_unified_jobs'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.UnifiedJobTemplate']"}) + }, + 'main.unifiedjobtemplate': { + 'Meta': {'unique_together': "[('polymorphic_ctype', 'name')]", 'object_name': 'UnifiedJobTemplate'}, + 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'created': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'created_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'unifiedjobtemplate\', \'app_label\': \'main\'}(class)s_created+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), + 'current_job': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'unifiedjobtemplate_as_current_job+'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.UnifiedJob']"}), + 'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'has_schedules': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_job': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'unifiedjobtemplate_as_last_job+'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.UnifiedJob']"}), + 'last_job_failed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_job_run': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}), + 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'modified_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'unifiedjobtemplate\', \'app_label\': \'main\'}(class)s_modified+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}), + 'next_job_run': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}), + 'next_schedule': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'unifiedjobtemplate_as_next_schedule+'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Schedule']"}), + 'old_pk': ('django.db.models.fields.PositiveIntegerField', [], {'default': 'None', 'null': 'True'}), + 'polymorphic_ctype': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'polymorphic_main.unifiedjobtemplate_set'", 'null': 'True', 'to': u"orm['contenttypes.ContentType']"}), + 'status': ('django.db.models.fields.CharField', [], {'default': "'ok'", 'max_length': '32'}) + } + } + + complete_apps = ['main']