From c899a675a957a1de6ae8ea2cbd9c1ffe0991d1df Mon Sep 17 00:00:00 2001 From: Chris Church Date: Thu, 27 Feb 2014 17:12:32 -0500 Subject: [PATCH 1/7] AC-1040 Add django-polymorphic as prerequisite for moving toward unified jobs. --- awx/lib/site-packages/README | 1 + awx/lib/site-packages/polymorphic/__init__.py | 46 + .../site-packages/polymorphic/__version__.py | 14 + awx/lib/site-packages/polymorphic/admin.py | 507 +++++++++++ awx/lib/site-packages/polymorphic/base.py | 243 ++++++ awx/lib/site-packages/polymorphic/manager.py | 46 + awx/lib/site-packages/polymorphic/models.py | 10 + .../polymorphic/polymorphic_model.py | 201 +++++ awx/lib/site-packages/polymorphic/query.py | 307 +++++++ .../polymorphic/query_translate.py | 248 ++++++ .../site-packages/polymorphic/showfields.py | 164 ++++ .../admin/polymorphic/add_type_form.html | 11 + .../admin/polymorphic/change_form.html | 6 + .../polymorphic/delete_confirmation.html | 6 + .../polymorphic/templatetags/__init__.py | 0 .../templatetags/polymorphic_admin_tags.py | 53 ++ awx/lib/site-packages/polymorphic/tests.py | 791 ++++++++++++++++++ .../polymorphic/tools_for_tests.py | 146 ++++ requirements/dev_local.txt | 2 + requirements/django_polymorphic-0.5.3.tar.gz | Bin 0 -> 33698 bytes requirements/prod.txt | 2 + requirements/prod_local.txt | 2 + 22 files changed, 2806 insertions(+) create mode 100644 awx/lib/site-packages/polymorphic/__init__.py create mode 100644 awx/lib/site-packages/polymorphic/__version__.py create mode 100644 awx/lib/site-packages/polymorphic/admin.py create mode 100644 awx/lib/site-packages/polymorphic/base.py create mode 100644 awx/lib/site-packages/polymorphic/manager.py create mode 100644 awx/lib/site-packages/polymorphic/models.py create mode 100644 awx/lib/site-packages/polymorphic/polymorphic_model.py create mode 100644 awx/lib/site-packages/polymorphic/query.py create mode 100644 awx/lib/site-packages/polymorphic/query_translate.py create mode 100644 awx/lib/site-packages/polymorphic/showfields.py create mode 100644 awx/lib/site-packages/polymorphic/templates/admin/polymorphic/add_type_form.html create mode 100644 awx/lib/site-packages/polymorphic/templates/admin/polymorphic/change_form.html create mode 100644 awx/lib/site-packages/polymorphic/templates/admin/polymorphic/delete_confirmation.html create mode 100644 awx/lib/site-packages/polymorphic/templatetags/__init__.py create mode 100644 awx/lib/site-packages/polymorphic/templatetags/polymorphic_admin_tags.py create mode 100644 awx/lib/site-packages/polymorphic/tests.py create mode 100644 awx/lib/site-packages/polymorphic/tools_for_tests.py create mode 100644 requirements/django_polymorphic-0.5.3.tar.gz diff --git a/awx/lib/site-packages/README b/awx/lib/site-packages/README index 31524309de..254e363882 100644 --- a/awx/lib/site-packages/README +++ b/awx/lib/site-packages/README @@ -18,6 +18,7 @@ django-auth-ldap==1.1.7 (django_auth_ldap/*) django-celery==3.1.1 (djcelery/*) django-extensions==1.2.5 (django_extensions/*) django-jsonfield==0.9.12 (jsonfield/*, minor fix in jsonfield/fields.py) +django-polymorphic==0.5.3 (polymorphic/*) django-split-settings==0.1.1 (split_settings/*) django-taggit==0.11.2 (taggit/*) djangorestframework==2.3.10 (rest_framework/*) diff --git a/awx/lib/site-packages/polymorphic/__init__.py b/awx/lib/site-packages/polymorphic/__init__.py new file mode 100644 index 0000000000..c598b84ef2 --- /dev/null +++ b/awx/lib/site-packages/polymorphic/__init__.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +""" +Seamless Polymorphic Inheritance for Django Models + +Copyright: +This code and affiliated files are (C) by Bert Constantin and individual contributors. +Please see LICENSE and AUTHORS for more information. +""" +from __future__ import absolute_import +import django +from .polymorphic_model import PolymorphicModel +from .manager import PolymorphicManager +from .query import PolymorphicQuerySet +from .query_translate import translate_polymorphic_Q_object +from .showfields import ShowFieldContent, ShowFieldType, ShowFieldTypeAndContent +from .showfields import ShowFields, ShowFieldTypes, ShowFieldsAndTypes # import old names for compatibility + + +# Monkey-patch Django < 1.5 to allow ContentTypes for proxy models. +if django.VERSION[:2] < (1, 5): + from django.contrib.contenttypes.models import ContentTypeManager + from django.utils.encoding import smart_text + + def get_for_model(self, model, for_concrete_model=True): + if for_concrete_model: + model = model._meta.concrete_model + elif model._deferred: + model = model._meta.proxy_for_model + + opts = model._meta + + try: + ct = self._get_from_cache(opts) + except KeyError: + ct, created = self.get_or_create( + app_label = opts.app_label, + model = opts.object_name.lower(), + defaults = {'name': smart_text(opts.verbose_name_raw)}, + ) + self._add_to_cache(self.db, ct) + + return ct + + ContentTypeManager.get_for_model__original = ContentTypeManager.get_for_model + ContentTypeManager.get_for_model = get_for_model + diff --git a/awx/lib/site-packages/polymorphic/__version__.py b/awx/lib/site-packages/polymorphic/__version__.py new file mode 100644 index 0000000000..202b7e2573 --- /dev/null +++ b/awx/lib/site-packages/polymorphic/__version__.py @@ -0,0 +1,14 @@ +# -*- coding: utf-8 -*- +""" +See PEP 386 (https://www.python.org/dev/peps/pep-0386/) + +Release logic: + 1. Remove "dev#" from current (this file, now AND setup.py!). + 2. git commit + 3. git tag + 4. push to pypi + push --tags to github + 5. bump the version, append ".dev0" + 6. git commit + 7. push to github +""" +__version__ = "0.5.3" diff --git a/awx/lib/site-packages/polymorphic/admin.py b/awx/lib/site-packages/polymorphic/admin.py new file mode 100644 index 0000000000..db1c8b29e1 --- /dev/null +++ b/awx/lib/site-packages/polymorphic/admin.py @@ -0,0 +1,507 @@ +""" +ModelAdmin code to display polymorphic models. +""" +from django import forms +from django.conf.urls import patterns, url +from django.contrib import admin +from django.contrib.admin.helpers import AdminForm, AdminErrorList +from django.contrib.admin.sites import AdminSite +from django.contrib.admin.widgets import AdminRadioSelect +from django.contrib.contenttypes.models import ContentType +from django.core.exceptions import PermissionDenied +from django.core.urlresolvers import RegexURLResolver +from django.http import Http404, HttpResponseRedirect +from django.shortcuts import render_to_response +from django.template.context import RequestContext +from django.utils import six +from django.utils.encoding import force_text +from django.utils.safestring import mark_safe +from django.utils.translation import ugettext_lazy as _ + +__all__ = ( + 'PolymorphicModelChoiceForm', 'PolymorphicParentModelAdmin', + 'PolymorphicChildModelAdmin', 'PolymorphicChildModelFilter' +) + + +class RegistrationClosed(RuntimeError): + "The admin model can't be registered anymore at this point." + pass + +class ChildAdminNotRegistered(RuntimeError): + "The admin site for the model is not registered." + pass + + +class PolymorphicModelChoiceForm(forms.Form): + """ + The default form for the ``add_type_form``. Can be overwritten and replaced. + """ + #: Define the label for the radiofield + type_label = _("Type") + + ct_id = forms.ChoiceField(label=type_label, widget=AdminRadioSelect(attrs={'class': 'radiolist'})) + + def __init__(self, *args, **kwargs): + # Allow to easily redefine the label (a commonly expected usecase) + super(PolymorphicModelChoiceForm, self).__init__(*args, **kwargs) + self.fields['ct_id'].label = self.type_label + + +class PolymorphicChildModelFilter(admin.SimpleListFilter): + """ + An admin list filter for the PolymorphicParentModelAdmin which enables + filtering by its child models. + """ + title = _('Content type') + parameter_name = 'polymorphic_ctype' + + def lookups(self, request, model_admin): + return model_admin.get_child_type_choices() + + def queryset(self, request, queryset): + try: + value = int(self.value()) + except TypeError: + value = None + if value: + # ensure the content type is allowed + for choice_value, _ in self.lookup_choices: + if choice_value == value: + return queryset.filter(polymorphic_ctype_id=choice_value) + raise PermissionDenied( + 'Invalid ContentType "{0}". It must be registered as child model.'.format(value)) + return queryset + + +class PolymorphicParentModelAdmin(admin.ModelAdmin): + """ + A admin interface that can displays different change/delete pages, depending on the polymorphic model. + To use this class, two variables need to be defined: + + * :attr:`base_model` should + * :attr:`child_models` should be a list of (Model, Admin) tuples + + Alternatively, the following methods can be implemented: + + * :func:`get_child_models` should return a list of (Model, ModelAdmin) tuples + * optionally, :func:`get_child_type_choices` can be overwritten to refine the choices for the add dialog. + + This class needs to be inherited by the model admin base class that is registered in the site. + The derived models should *not* register the ModelAdmin, but instead it should be returned by :func:`get_child_models`. + """ + + #: The base model that the class uses + base_model = None + + #: The child models that should be displayed + child_models = None + + #: Whether the list should be polymorphic too, leave to ``False`` to optimize + polymorphic_list = False + + add_type_template = None + add_type_form = PolymorphicModelChoiceForm + + + def __init__(self, model, admin_site, *args, **kwargs): + super(PolymorphicParentModelAdmin, self).__init__(model, admin_site, *args, **kwargs) + self._child_admin_site = AdminSite(name=self.admin_site.name) + self._is_setup = False + + + def _lazy_setup(self): + if self._is_setup: + return + + # By not having this in __init__() there is less stress on import dependencies as well, + # considering an advanced use cases where a plugin system scans for the child models. + child_models = self.get_child_models() + for Model, Admin in child_models: + self.register_child(Model, Admin) + self._child_models = dict(child_models) + + # This is needed to deal with the improved ForeignKeyRawIdWidget in Django 1.4 and perhaps other widgets too. + # The ForeignKeyRawIdWidget checks whether the referenced model is registered in the admin, otherwise it displays itself as a textfield. + # As simple solution, just make sure all parent admin models are also know in the child admin site. + # This should be done after all parent models are registered off course. + complete_registry = self.admin_site._registry.copy() + complete_registry.update(self._child_admin_site._registry) + + self._child_admin_site._registry = complete_registry + self._is_setup = True + + + def register_child(self, model, model_admin): + """ + Register a model with admin to display. + """ + # After the get_urls() is called, the URLs of the child model can't be exposed anymore to the Django URLconf, + # which also means that a "Save and continue editing" button won't work. + if self._is_setup: + raise RegistrationClosed("The admin model can't be registered anymore at this point.") + + if not issubclass(model, self.base_model): + raise TypeError("{0} should be a subclass of {1}".format(model.__name__, self.base_model.__name__)) + if not issubclass(model_admin, admin.ModelAdmin): + raise TypeError("{0} should be a subclass of {1}".format(model_admin.__name__, admin.ModelAdmin.__name__)) + + self._child_admin_site.register(model, model_admin) + + + def get_child_models(self): + """ + Return the derived model classes which this admin should handle. + This should return a list of tuples, exactly like :attr:`child_models` is. + + The model classes can be retrieved as ``base_model.__subclasses__()``, + a setting in a config file, or a query of a plugin registration system at your option + """ + if self.child_models is None: + raise NotImplementedError("Implement get_child_models() or child_models") + + return self.child_models + + + def get_child_type_choices(self): + """ + Return a list of polymorphic types which can be added. + """ + choices = [] + for model, _ in self.get_child_models(): + ct = ContentType.objects.get_for_model(model, for_concrete_model=False) + choices.append((ct.id, model._meta.verbose_name)) + return choices + + + def _get_real_admin(self, object_id): + obj = self.model.objects.non_polymorphic().values('polymorphic_ctype').get(pk=object_id) + return self._get_real_admin_by_ct(obj['polymorphic_ctype']) + + + def _get_real_admin_by_ct(self, ct_id): + try: + ct = ContentType.objects.get_for_id(ct_id) + except ContentType.DoesNotExist as e: + raise Http404(e) # Handle invalid GET parameters + + model_class = ct.model_class() + if not model_class: + raise Http404("No model found for '{0}.{1}'.".format(*ct.natural_key())) # Handle model deletion + + return self._get_real_admin_by_model(model_class) + + + def _get_real_admin_by_model(self, model_class): + # In case of a ?ct_id=### parameter, the view is already checked for permissions. + # Hence, make sure this is a derived object, or risk exposing other admin interfaces. + if model_class not in self._child_models: + raise PermissionDenied("Invalid model '{0}', it must be registered as child model.".format(model_class)) + + try: + # HACK: the only way to get the instance of an model admin, + # is to read the registry of the AdminSite. + return self._child_admin_site._registry[model_class] + except KeyError: + raise ChildAdminNotRegistered("No child admin site was registered for a '{0}' model.".format(model_class)) + + + def queryset(self, request): + # optimize the list display. + qs = super(PolymorphicParentModelAdmin, self).queryset(request) + if not self.polymorphic_list: + qs = qs.non_polymorphic() + return qs + + + def add_view(self, request, form_url='', extra_context=None): + """Redirect the add view to the real admin.""" + ct_id = int(request.GET.get('ct_id', 0)) + if not ct_id: + # Display choices + return self.add_type_view(request) + else: + real_admin = self._get_real_admin_by_ct(ct_id) + return real_admin.add_view(request, form_url, extra_context) + + + def change_view(self, request, object_id, *args, **kwargs): + """Redirect the change view to the real admin.""" + # between Django 1.3 and 1.4 this method signature differs. Hence the *args, **kwargs + real_admin = self._get_real_admin(object_id) + return real_admin.change_view(request, object_id, *args, **kwargs) + + + def delete_view(self, request, object_id, extra_context=None): + """Redirect the delete view to the real admin.""" + real_admin = self._get_real_admin(object_id) + return real_admin.delete_view(request, object_id, extra_context) + + + def get_urls(self): + """ + Expose the custom URLs for the subclasses and the URL resolver. + """ + urls = super(PolymorphicParentModelAdmin, self).get_urls() + info = self.model._meta.app_label, self.model._meta.module_name + + # Patch the change URL so it's not a big catch-all; allowing all custom URLs to be added to the end. + # The url needs to be recreated, patching url.regex is not an option Django 1.4's LocaleRegexProvider changed it. + new_change_url = url(r'^(\d+)/$', self.admin_site.admin_view(self.change_view), name='{0}_{1}_change'.format(*info)) + for i, oldurl in enumerate(urls): + if oldurl.name == new_change_url.name: + urls[i] = new_change_url + + # Define the catch-all for custom views + custom_urls = patterns('', + url(r'^(?P.+)$', self.admin_site.admin_view(self.subclass_view)) + ) + + # At this point. all admin code needs to be known. + self._lazy_setup() + + # Add reverse names for all polymorphic models, so the delete button and "save and add" just work. + # These definitions are masked by the definition above, since it needs special handling (and a ct_id parameter). + dummy_urls = [] + for model, _ in self.get_child_models(): + admin = self._get_real_admin_by_model(model) + dummy_urls += admin.get_urls() + + return urls + custom_urls + dummy_urls + + + def subclass_view(self, request, path): + """ + Forward any request to a custom view of the real admin. + """ + ct_id = int(request.GET.get('ct_id', 0)) + if not ct_id: + # See if the path started with an ID. + try: + pos = path.find('/') + object_id = long(path[0:pos]) + except ValueError: + raise Http404("No ct_id parameter, unable to find admin subclass for path '{0}'.".format(path)) + + ct_id = self.model.objects.values_list('polymorphic_ctype_id', flat=True).get(pk=object_id) + + + real_admin = self._get_real_admin_by_ct(ct_id) + resolver = RegexURLResolver('^', real_admin.urls) + resolvermatch = resolver.resolve(path) # May raise Resolver404 + if not resolvermatch: + raise Http404("No match for path '{0}' in admin subclass.".format(path)) + + return resolvermatch.func(request, *resolvermatch.args, **resolvermatch.kwargs) + + + def add_type_view(self, request, form_url=''): + """ + Display a choice form to select which page type to add. + """ + if not self.has_add_permission(request): + raise PermissionDenied + + extra_qs = '' + if request.META['QUERY_STRING']: + extra_qs = '&' + request.META['QUERY_STRING'] + + choices = self.get_child_type_choices() + if len(choices) == 1: + return HttpResponseRedirect('?ct_id={0}{1}'.format(choices[0][0], extra_qs)) + + # Create form + form = self.add_type_form( + data=request.POST if request.method == 'POST' else None, + initial={'ct_id': choices[0][0]} + ) + form.fields['ct_id'].choices = choices + + if form.is_valid(): + return HttpResponseRedirect('?ct_id={0}{1}'.format(form.cleaned_data['ct_id'], extra_qs)) + + # Wrap in all admin layout + fieldsets = ((None, {'fields': ('ct_id',)}),) + adminForm = AdminForm(form, fieldsets, {}, model_admin=self) + media = self.media + adminForm.media + opts = self.model._meta + + context = { + 'title': _('Add %s') % force_text(opts.verbose_name), + 'adminform': adminForm, + 'is_popup': "_popup" in request.REQUEST, + 'media': mark_safe(media), + 'errors': AdminErrorList(form, ()), + 'app_label': opts.app_label, + } + return self.render_add_type_form(request, context, form_url) + + + def render_add_type_form(self, request, context, form_url=''): + """ + Render the page type choice form. + """ + opts = self.model._meta + app_label = opts.app_label + context.update({ + 'has_change_permission': self.has_change_permission(request), + 'form_url': mark_safe(form_url), + 'opts': opts, + 'add': True, + 'save_on_top': self.save_on_top, + }) + if hasattr(self.admin_site, 'root_path'): + context['root_path'] = self.admin_site.root_path # Django < 1.4 + context_instance = RequestContext(request, current_app=self.admin_site.name) + return render_to_response(self.add_type_template or [ + "admin/%s/%s/add_type_form.html" % (app_label, opts.object_name.lower()), + "admin/%s/add_type_form.html" % app_label, + "admin/polymorphic/add_type_form.html", # added default here + "admin/add_type_form.html" + ], context, context_instance=context_instance) + + + @property + def change_list_template(self): + opts = self.model._meta + app_label = opts.app_label + + # Pass the base options + base_opts = self.base_model._meta + base_app_label = base_opts.app_label + + return [ + "admin/%s/%s/change_list.html" % (app_label, opts.object_name.lower()), + "admin/%s/change_list.html" % app_label, + # Added base class: + "admin/%s/%s/change_list.html" % (base_app_label, base_opts.object_name.lower()), + "admin/%s/change_list.html" % base_app_label, + "admin/change_list.html" + ] + + + +class PolymorphicChildModelAdmin(admin.ModelAdmin): + """ + The *optional* base class for the admin interface of derived models. + + This base class defines some convenience behavior for the admin interface: + + * It corrects the breadcrumbs in the admin pages. + * It adds the base model to the template lookup paths. + * It allows to set ``base_form`` so the derived class will automatically include other fields in the form. + * It allows to set ``base_fieldsets`` so the derived class will automatically display any extra fields. + + The ``base_model`` attribute must be set. + """ + base_model = None + base_form = None + base_fieldsets = None + extra_fieldset_title = _("Contents") # Default title for extra fieldset + + + def get_form(self, request, obj=None, **kwargs): + # The django admin validation requires the form to have a 'class Meta: model = ..' + # attribute, or it will complain that the fields are missing. + # However, this enforces all derived ModelAdmin classes to redefine the model as well, + # because they need to explicitly set the model again - it will stick with the base model. + # + # Instead, pass the form unchecked here, because the standard ModelForm will just work. + # If the derived class sets the model explicitly, respect that setting. + kwargs.setdefault('form', self.base_form or self.form) + return super(PolymorphicChildModelAdmin, self).get_form(request, obj, **kwargs) + + + @property + def change_form_template(self): + opts = self.model._meta + app_label = opts.app_label + + # Pass the base options + base_opts = self.base_model._meta + base_app_label = base_opts.app_label + + return [ + "admin/%s/%s/change_form.html" % (app_label, opts.object_name.lower()), + "admin/%s/change_form.html" % app_label, + # Added: + "admin/%s/%s/change_form.html" % (base_app_label, base_opts.object_name.lower()), + "admin/%s/change_form.html" % base_app_label, + "admin/polymorphic/change_form.html", + "admin/change_form.html" + ] + + + @property + def delete_confirmation_template(self): + opts = self.model._meta + app_label = opts.app_label + + # Pass the base options + base_opts = self.base_model._meta + base_app_label = base_opts.app_label + + return [ + "admin/%s/%s/delete_confirmation.html" % (app_label, opts.object_name.lower()), + "admin/%s/delete_confirmation.html" % app_label, + # Added: + "admin/%s/%s/delete_confirmation.html" % (base_app_label, base_opts.object_name.lower()), + "admin/%s/delete_confirmation.html" % base_app_label, + "admin/polymorphic/delete_confirmation.html", + "admin/delete_confirmation.html" + ] + + + def render_change_form(self, request, context, add=False, change=False, form_url='', obj=None): + context.update({ + 'base_opts': self.base_model._meta, + }) + return super(PolymorphicChildModelAdmin, self).render_change_form(request, context, add=add, change=change, form_url=form_url, obj=obj) + + + def delete_view(self, request, object_id, context=None): + extra_context = { + 'base_opts': self.base_model._meta, + } + return super(PolymorphicChildModelAdmin, self).delete_view(request, object_id, extra_context) + + + # ---- Extra: improving the form/fieldset default display ---- + + def get_fieldsets(self, request, obj=None): + # If subclass declares fieldsets, this is respected + if self.declared_fieldsets or not self.base_fieldsets: + return super(PolymorphicChildModelAdmin, self).get_fieldsets(request, obj) + + # Have a reasonable default fieldsets, + # where the subclass fields are automatically included. + other_fields = self.get_subclass_fields(request, obj) + + if other_fields: + return ( + self.base_fieldsets[0], + (self.extra_fieldset_title, {'fields': other_fields}), + ) + self.base_fieldsets[1:] + else: + return self.base_fieldsets + + + def get_subclass_fields(self, request, obj=None): + # Find out how many fields would really be on the form, + # if it weren't restricted by declared fields. + exclude = list(self.exclude or []) + exclude.extend(self.get_readonly_fields(request, obj)) + + # By not declaring the fields/form in the base class, + # get_form() will populate the form with all available fields. + form = self.get_form(request, obj, exclude=exclude) + subclass_fields = list(six.iterkeys(form.base_fields)) + list(self.get_readonly_fields(request, obj)) + + # Find which fields are not part of the common fields. + for fieldset in self.base_fieldsets: + for field in fieldset[1]['fields']: + try: + subclass_fields.remove(field) + except ValueError: + pass # field not found in form, Django will raise exception later. + return subclass_fields diff --git a/awx/lib/site-packages/polymorphic/base.py b/awx/lib/site-packages/polymorphic/base.py new file mode 100644 index 0000000000..95a124e6b3 --- /dev/null +++ b/awx/lib/site-packages/polymorphic/base.py @@ -0,0 +1,243 @@ +# -*- coding: utf-8 -*- +""" PolymorphicModel Meta Class + Please see README.rst or DOCS.rst or http://chrisglass.github.com/django_polymorphic/ +""" +from __future__ import absolute_import + +import sys +import inspect + +from django.db import models +from django.db.models.base import ModelBase +from django.db.models.manager import ManagerDescriptor + +from .manager import PolymorphicManager +from .query import PolymorphicQuerySet + +# PolymorphicQuerySet Q objects (and filter()) support these additional key words. +# These are forbidden as field names (a descriptive exception is raised) +POLYMORPHIC_SPECIAL_Q_KWORDS = ['instance_of', 'not_instance_of'] + +try: + from django.db.models.manager import AbstractManagerDescriptor # Django 1.5 +except ImportError: + AbstractManagerDescriptor = None + + +################################################################################### +### PolymorphicModel meta class + +class PolymorphicModelBase(ModelBase): + """ + Manager inheritance is a pretty complex topic which may need + more thought regarding how this should be handled for polymorphic + models. + + In any case, we probably should propagate 'objects' and 'base_objects' + from PolymorphicModel to every subclass. We also want to somehow + inherit/propagate _default_manager as well, as it needs to be polymorphic. + + The current implementation below is an experiment to solve this + problem with a very simplistic approach: We unconditionally + inherit/propagate any and all managers (using _copy_to_model), + as long as they are defined on polymorphic models + (the others are left alone). + + Like Django ModelBase, we special-case _default_manager: + if there are any user-defined managers, it is set to the first of these. + + We also require that _default_manager as well as any user defined + polymorphic managers produce querysets that are derived from + PolymorphicQuerySet. + """ + + def __new__(self, model_name, bases, attrs): + #print; print '###', model_name, '- bases:', bases + + # Workaround compatibility issue with six.with_metaclass() and custom Django model metaclasses: + # Let Django fully ignore the class which is inserted in between. + if not attrs and model_name == 'NewBase': + attrs['__module__'] = 'django.utils.six' + attrs['Meta'] = type('Meta', (), {'abstract': True}) + return super(PolymorphicModelBase, self).__new__(self, model_name, bases, attrs) + + # create new model + new_class = self.call_superclass_new_method(model_name, bases, attrs) + + # check if the model fields are all allowed + self.validate_model_fields(new_class) + + # create list of all managers to be inherited from the base classes + inherited_managers = new_class.get_inherited_managers(attrs) + + # add the managers to the new model + for source_name, mgr_name, manager in inherited_managers: + #print '** add inherited manager from model %s, manager %s, %s' % (source_name, mgr_name, manager.__class__.__name__) + new_manager = manager._copy_to_model(new_class) + new_class.add_to_class(mgr_name, new_manager) + + # get first user defined manager; if there is one, make it the _default_manager + # this value is used by the related objects, restoring access to custom queryset methods on related objects. + user_manager = self.get_first_user_defined_manager(new_class) + if user_manager: + def_mgr = user_manager._copy_to_model(new_class) + #print '## add default manager', type(def_mgr) + new_class.add_to_class('_default_manager', def_mgr) + new_class._default_manager._inherited = False # the default mgr was defined by the user, not inherited + + # validate resulting default manager + self.validate_model_manager(new_class._default_manager, model_name, '_default_manager') + + # for __init__ function of this class (monkeypatching inheritance accessors) + new_class.polymorphic_super_sub_accessors_replaced = False + + # determine the name of the primary key field and store it into the class variable + # polymorphic_primary_key_name (it is needed by query.py) + for f in new_class._meta.fields: + if f.primary_key and type(f) != models.OneToOneField: + new_class.polymorphic_primary_key_name = f.name + break + + return new_class + + def get_inherited_managers(self, attrs): + """ + Return list of all managers to be inherited/propagated from the base classes; + use correct mro, only use managers with _inherited==False (they are of no use), + skip managers that are overwritten by the user with same-named class attributes (in attrs) + """ + #print "** ", self.__name__ + add_managers = [] + add_managers_keys = set() + for base in self.__mro__[1:]: + if not issubclass(base, models.Model): + continue + if not getattr(base, 'polymorphic_model_marker', None): + continue # leave managers of non-polym. models alone + + for key, manager in base.__dict__.items(): + if type(manager) == models.manager.ManagerDescriptor: + manager = manager.manager + + if AbstractManagerDescriptor is not None: + # Django 1.4 unconditionally assigned managers to a model. As of Django 1.5 however, + # the abstract models don't get any managers, only a AbstractManagerDescriptor as substitute. + # Pretend that the manager is still there, so all code works like it used to. + if type(manager) == AbstractManagerDescriptor and base.__name__ == 'PolymorphicModel': + model = manager.model + if key == 'objects': + manager = PolymorphicManager() + manager.model = model + elif key == 'base_objects': + manager = models.Manager() + manager.model = model + + if not isinstance(manager, models.Manager): + continue + if key == '_base_manager': + continue # let Django handle _base_manager + if key in attrs: + continue + if key in add_managers_keys: + continue # manager with that name already added, skip + if manager._inherited: + continue # inherited managers (on the bases) have no significance, they are just copies + #print '## {0} {1}'.format(self.__name__, key) + + if isinstance(manager, PolymorphicManager): # validate any inherited polymorphic managers + self.validate_model_manager(manager, self.__name__, key) + add_managers.append((base.__name__, key, manager)) + add_managers_keys.add(key) + + # The ordering in the base.__dict__ may randomly change depending on which method is added. + # Make sure base_objects is on top, and 'objects' and '_default_manager' follow afterwards. + # This makes sure that the _base_manager is also assigned properly. + add_managers = sorted(add_managers, key=lambda item: (item[1].startswith('_'), item[1])) + return add_managers + + @classmethod + def get_first_user_defined_manager(mcs, new_class): + # See if there is a manager attribute directly stored at this inheritance level. + mgr_list = [] + for key, val in new_class.__dict__.items(): + if isinstance(val, ManagerDescriptor): + val = val.manager + if not isinstance(val, PolymorphicManager) or type(val) is PolymorphicManager: + continue + + mgr_list.append((val.creation_counter, key, val)) + + # if there are user defined managers, use first one as _default_manager + if mgr_list: + _, manager_name, manager = sorted(mgr_list)[0] + #sys.stderr.write( '\n# first user defined manager for model "{model}":\n# "{mgrname}": {mgr}\n# manager model: {mgrmodel}\n\n' + # .format( model=self.__name__, mgrname=manager_name, mgr=manager, mgrmodel=manager.model ) ) + return manager + return None + + @classmethod + def call_superclass_new_method(self, model_name, bases, attrs): + """call __new__ method of super class and return the newly created class. + Also work around a limitation in Django's ModelBase.""" + # There seems to be a general limitation in Django's app_label handling + # regarding abstract models (in ModelBase). See issue 1 on github - TODO: propose patch for Django + # We run into this problem if polymorphic.py is located in a top-level directory + # which is directly in the python path. To work around this we temporarily set + # app_label here for PolymorphicModel. + meta = attrs.get('Meta', None) + do_app_label_workaround = (meta + and attrs['__module__'] == 'polymorphic' + and model_name == 'PolymorphicModel' + and getattr(meta, 'app_label', None) is None) + + if do_app_label_workaround: + meta.app_label = 'poly_dummy_app_label' + new_class = super(PolymorphicModelBase, self).__new__(self, model_name, bases, attrs) + if do_app_label_workaround: + del(meta.app_label) + return new_class + + def validate_model_fields(self): + "check if all fields names are allowed (i.e. not in POLYMORPHIC_SPECIAL_Q_KWORDS)" + for f in self._meta.fields: + if f.name in POLYMORPHIC_SPECIAL_Q_KWORDS: + e = 'PolymorphicModel: "%s" - field name "%s" is not allowed in polymorphic models' + raise AssertionError(e % (self.__name__, f.name)) + + @classmethod + def validate_model_manager(self, manager, model_name, manager_name): + """check if the manager is derived from PolymorphicManager + and its querysets from PolymorphicQuerySet - throw AssertionError if not""" + + if not issubclass(type(manager), PolymorphicManager): + e = 'PolymorphicModel: "' + model_name + '.' + manager_name + '" manager is of type "' + type(manager).__name__ + e += '", but must be a subclass of PolymorphicManager' + raise AssertionError(e) + if not getattr(manager, 'queryset_class', None) or not issubclass(manager.queryset_class, PolymorphicQuerySet): + e = 'PolymorphicModel: "' + model_name + '.' + manager_name + '" (PolymorphicManager) has been instantiated with a queryset class which is' + e += ' not a subclass of PolymorphicQuerySet (which is required)' + raise AssertionError(e) + return manager + + # hack: a small patch to Django would be a better solution. + # Django's management command 'dumpdata' relies on non-polymorphic + # behaviour of the _default_manager. Therefore, we catch any access to _default_manager + # here and return the non-polymorphic default manager instead if we are called from 'dumpdata.py' + # (non-polymorphic default manager is 'base_objects' for polymorphic models). + # This way we don't need to patch django.core.management.commands.dumpdata + # for all supported Django versions. + # TODO: investigate Django how this can be avoided + _dumpdata_command_running = False + if len(sys.argv) > 1: + _dumpdata_command_running = (sys.argv[1] == 'dumpdata') + + def __getattribute__(self, name): + if name == '_default_manager': + if self._dumpdata_command_running: + frm = inspect.stack()[1] # frm[1] is caller file name, frm[3] is caller function name + if 'django/core/management/commands/dumpdata.py' in frm[1]: + return self.base_objects + #caller_mod_name = inspect.getmodule(frm[0]).__name__ # does not work with python 2.4 + #if caller_mod_name == 'django.core.management.commands.dumpdata': + + return super(PolymorphicModelBase, self).__getattribute__(name) diff --git a/awx/lib/site-packages/polymorphic/manager.py b/awx/lib/site-packages/polymorphic/manager.py new file mode 100644 index 0000000000..3e0e6d8143 --- /dev/null +++ b/awx/lib/site-packages/polymorphic/manager.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +""" PolymorphicManager + Please see README.rst or DOCS.rst or http://chrisglass.github.com/django_polymorphic/ +""" +from __future__ import unicode_literals +import warnings +from django.db import models +from polymorphic.query import PolymorphicQuerySet + + +class PolymorphicManager(models.Manager): + """ + Manager for PolymorphicModel + + Usually not explicitly needed, except if a custom manager or + a custom queryset class is to be used. + """ + # Tell Django that related fields also need to use this manager: + use_for_related_fields = True + queryset_class = PolymorphicQuerySet + + def __init__(self, queryset_class=None, *args, **kwrags): + # Up till polymorphic 0.4, the queryset class could be specified as parameter to __init__. + # However, this doesn't work for related managers which instantiate a new version of this class. + # Hence, for custom managers the new default is using the 'queryset_class' attribute at class level instead. + if queryset_class: + warnings.warn("Using PolymorphicManager(queryset_class=..) is deprecated; override the queryset_class attribute instead", DeprecationWarning) + # For backwards compatibility, still allow the parameter: + self.queryset_class = queryset_class + + super(PolymorphicManager, self).__init__(*args, **kwrags) + + def get_query_set(self): + return self.queryset_class(self.model, using=self._db) + + # Proxy all unknown method calls to the queryset, so that its members are + # directly accessible as PolymorphicModel.objects.* + # The advantage of this method is that not yet known member functions of derived querysets will be proxied as well. + # We exclude any special functions (__) from this automatic proxying. + def __getattr__(self, name): + if name.startswith('__'): + return super(PolymorphicManager, self).__getattr__(self, name) + return getattr(self.get_query_set(), name) + + def __unicode__(self): + return '%s (PolymorphicManager) using %s' % (self.__class__.__name__, self.queryset_class.__name__) diff --git a/awx/lib/site-packages/polymorphic/models.py b/awx/lib/site-packages/polymorphic/models.py new file mode 100644 index 0000000000..69652f9eed --- /dev/null +++ b/awx/lib/site-packages/polymorphic/models.py @@ -0,0 +1,10 @@ +# -*- coding: utf-8 -*- +""" +IMPORTANT: + +The models.py module is not used anymore. +Please use the following import method in your apps: + + from polymorphic import PolymorphicModel, ... + +""" diff --git a/awx/lib/site-packages/polymorphic/polymorphic_model.py b/awx/lib/site-packages/polymorphic/polymorphic_model.py new file mode 100644 index 0000000000..5b20751b1e --- /dev/null +++ b/awx/lib/site-packages/polymorphic/polymorphic_model.py @@ -0,0 +1,201 @@ +# -*- coding: utf-8 -*- +""" +Seamless Polymorphic Inheritance for Django Models +================================================== + +Please see README.rst and DOCS.rst for further information. + +Or on the Web: +http://chrisglass.github.com/django_polymorphic/ +http://github.com/chrisglass/django_polymorphic + +Copyright: +This code and affiliated files are (C) by Bert Constantin and individual contributors. +Please see LICENSE and AUTHORS for more information. +""" +from __future__ import absolute_import + +from django.db import models +from django.contrib.contenttypes.models import ContentType +from django.utils import six + +from .base import PolymorphicModelBase +from .manager import PolymorphicManager +from .query_translate import translate_polymorphic_Q_object + + +################################################################################### +### PolymorphicModel + +class PolymorphicModel(six.with_metaclass(PolymorphicModelBase, models.Model)): + """ + Abstract base class that provides polymorphic behaviour + for any model directly or indirectly derived from it. + + For usage instructions & examples please see documentation. + + PolymorphicModel declares one field for internal use (polymorphic_ctype) + and provides a polymorphic manager as the default manager + (and as 'objects'). + + PolymorphicModel overrides the save() and __init__ methods. + + If your derived class overrides any of these methods as well, then you need + to take care that you correctly call the method of the superclass, like: + + super(YourClass,self).save(*args,**kwargs) + """ + + # for PolymorphicModelBase, so it can tell which models are polymorphic and which are not (duck typing) + polymorphic_model_marker = True + + # for PolymorphicQuery, True => an overloaded __repr__ with nicer multi-line output is used by PolymorphicQuery + polymorphic_query_multiline_output = False + + class Meta: + abstract = True + + # avoid ContentType related field accessor clash (an error emitted by model validation) + polymorphic_ctype = models.ForeignKey(ContentType, null=True, editable=False, + related_name='polymorphic_%(app_label)s.%(class)s_set') + + # some applications want to know the name of the fields that are added to its models + polymorphic_internal_model_fields = ['polymorphic_ctype'] + + # Note that Django 1.5 removes these managers because the model is abstract. + # They are pretended to be there by the metaclass in PolymorphicModelBase.get_inherited_managers() + objects = PolymorphicManager() + base_objects = models.Manager() + + @classmethod + def translate_polymorphic_Q_object(self_class, q): + return translate_polymorphic_Q_object(self_class, q) + + def pre_save_polymorphic(self): + """Normally not needed. + This function may be called manually in special use-cases. When the object + is saved for the first time, we store its real class in polymorphic_ctype. + When the object later is retrieved by PolymorphicQuerySet, it uses this + field to figure out the real class of this object + (used by PolymorphicQuerySet._get_real_instances) + """ + if not self.polymorphic_ctype_id: + self.polymorphic_ctype = ContentType.objects.get_for_model(self, for_concrete_model=False) + + def save(self, *args, **kwargs): + """Overridden model save function which supports the polymorphism + functionality (through pre_save_polymorphic).""" + self.pre_save_polymorphic() + return super(PolymorphicModel, self).save(*args, **kwargs) + + def get_real_instance_class(self): + """ + Normally not needed. + If a non-polymorphic manager (like base_objects) has been used to + retrieve objects, then the real class/type of these objects may be + determined using this method. + """ + # the following line would be the easiest way to do this, but it produces sql queries + # return self.polymorphic_ctype.model_class() + # so we use the following version, which uses the CopntentType manager cache. + # Note that model_class() can return None for stale content types; + # when the content type record still exists but no longer refers to an existing model. + try: + return ContentType.objects.get_for_id(self.polymorphic_ctype_id).model_class() + except AttributeError: + # Django <1.6 workaround + return None + + def get_real_concrete_instance_class_id(self): + model_class = self.get_real_instance_class() + if model_class is None: + return None + return ContentType.objects.get_for_model(model_class, for_concrete_model=True).pk + + def get_real_concrete_instance_class(self): + model_class = self.get_real_instance_class() + if model_class is None: + return None + return ContentType.objects.get_for_model(model_class, for_concrete_model=True).model_class() + + def get_real_instance(self): + """Normally not needed. + If a non-polymorphic manager (like base_objects) has been used to + retrieve objects, then the complete object with it's real class/type + and all fields may be retrieved with this method. + Each method call executes one db query (if necessary).""" + real_model = self.get_real_instance_class() + if real_model == self.__class__: + return self + return real_model.objects.get(pk=self.pk) + + def __init__(self, * args, ** kwargs): + """Replace Django's inheritance accessor member functions for our model + (self.__class__) with our own versions. + We monkey patch them until a patch can be added to Django + (which would probably be very small and make all of this obsolete). + + If we have inheritance of the form ModelA -> ModelB ->ModelC then + Django creates accessors like this: + - ModelA: modelb + - ModelB: modela_ptr, modelb, modelc + - ModelC: modela_ptr, modelb, modelb_ptr, modelc + + These accessors allow Django (and everyone else) to travel up and down + the inheritance tree for the db object at hand. + + The original Django accessors use our polymorphic manager. + But they should not. So we replace them with our own accessors that use + our appropriate base_objects manager. + """ + super(PolymorphicModel, self).__init__(*args, ** kwargs) + + if self.__class__.polymorphic_super_sub_accessors_replaced: + return + self.__class__.polymorphic_super_sub_accessors_replaced = True + + def create_accessor_function_for_model(model, accessor_name): + def accessor_function(self): + attr = model.base_objects.get(pk=self.pk) + return attr + return accessor_function + + subclasses_and_superclasses_accessors = self._get_inheritance_relation_fields_and_models() + + from django.db.models.fields.related import SingleRelatedObjectDescriptor, ReverseSingleRelatedObjectDescriptor + for name, model in subclasses_and_superclasses_accessors.items(): + orig_accessor = getattr(self.__class__, name, None) + if type(orig_accessor) in [SingleRelatedObjectDescriptor, ReverseSingleRelatedObjectDescriptor]: + #print >>sys.stderr, '---------- replacing', name, orig_accessor, '->', model + setattr(self.__class__, name, property(create_accessor_function_for_model(model, name))) + + def _get_inheritance_relation_fields_and_models(self): + """helper function for __init__: + determine names of all Django inheritance accessor member functions for type(self)""" + + def add_model(model, as_ptr, result): + name = model.__name__.lower() + if as_ptr: + name += '_ptr' + result[name] = model + + def add_model_if_regular(model, as_ptr, result): + if (issubclass(model, models.Model) + and model != models.Model + and model != self.__class__ + and model != PolymorphicModel): + add_model(model, as_ptr, result) + + def add_all_super_models(model, result): + add_model_if_regular(model, True, result) + for b in model.__bases__: + add_all_super_models(b, result) + + def add_all_sub_models(model, result): + for b in model.__subclasses__(): + add_model_if_regular(b, False, result) + + result = {} + add_all_super_models(self.__class__, result) + add_all_sub_models(self.__class__, result) + return result diff --git a/awx/lib/site-packages/polymorphic/query.py b/awx/lib/site-packages/polymorphic/query.py new file mode 100644 index 0000000000..7f6d70dbbf --- /dev/null +++ b/awx/lib/site-packages/polymorphic/query.py @@ -0,0 +1,307 @@ +# -*- coding: utf-8 -*- +""" QuerySet for PolymorphicModel + Please see README.rst or DOCS.rst or http://chrisglass.github.com/django_polymorphic/ +""" +from __future__ import absolute_import + +from collections import defaultdict + +from django.db.models.query import QuerySet +from django.contrib.contenttypes.models import ContentType +from django.utils import six + +from .query_translate import translate_polymorphic_filter_definitions_in_kwargs, translate_polymorphic_filter_definitions_in_args +from .query_translate import translate_polymorphic_field_path + +# chunk-size: maximum number of objects requested per db-request +# by the polymorphic queryset.iterator() implementation; we use the same chunk size as Django +try: + from django.db.models.query import CHUNK_SIZE # this is 100 for Django 1.1/1.2 +except ImportError: + # CHUNK_SIZE was removed in Django 1.6 + CHUNK_SIZE = 100 +Polymorphic_QuerySet_objects_per_request = CHUNK_SIZE + + +def transmogrify(cls, obj): + """ + Upcast a class to a different type without asking questions. + """ + if not '__init__' in obj.__dict__: + # Just assign __class__ to a different value. + new = obj + new.__class__ = cls + else: + # Run constructor, reassign values + new = cls() + for k,v in obj.__dict__.items(): + new.__dict__[k] = v + return new + + +################################################################################### +### PolymorphicQuerySet + +class PolymorphicQuerySet(QuerySet): + """ + QuerySet for PolymorphicModel + + Contains the core functionality for PolymorphicModel + + Usually not explicitly needed, except if a custom queryset class + is to be used. + """ + + def __init__(self, *args, **kwargs): + "init our queryset object member variables" + self.polymorphic_disabled = False + super(PolymorphicQuerySet, self).__init__(*args, **kwargs) + + def _clone(self, *args, **kwargs): + "Django's _clone only copies its own variables, so we need to copy ours here" + new = super(PolymorphicQuerySet, self)._clone(*args, **kwargs) + new.polymorphic_disabled = self.polymorphic_disabled + return new + + def non_polymorphic(self, *args, **kwargs): + """switch off polymorphic behaviour for this query. + When the queryset is evaluated, only objects of the type of the + base class used for this query are returned.""" + self.polymorphic_disabled = True + return self + + def instance_of(self, *args): + """Filter the queryset to only include the classes in args (and their subclasses). + Implementation in _translate_polymorphic_filter_defnition.""" + return self.filter(instance_of=args) + + def not_instance_of(self, *args): + """Filter the queryset to exclude the classes in args (and their subclasses). + Implementation in _translate_polymorphic_filter_defnition.""" + return self.filter(not_instance_of=args) + + def _filter_or_exclude(self, negate, *args, **kwargs): + "We override this internal Django functon as it is used for all filter member functions." + translate_polymorphic_filter_definitions_in_args(self.model, args) # the Q objects + additional_args = translate_polymorphic_filter_definitions_in_kwargs(self.model, kwargs) # filter_field='data' + return super(PolymorphicQuerySet, self)._filter_or_exclude(negate, *(list(args) + additional_args), **kwargs) + + def order_by(self, *args, **kwargs): + """translate the field paths in the args, then call vanilla order_by.""" + new_args = [translate_polymorphic_field_path(self.model, a) for a in args] + return super(PolymorphicQuerySet, self).order_by(*new_args, **kwargs) + + def _process_aggregate_args(self, args, kwargs): + """for aggregate and annotate kwargs: allow ModelX___field syntax for kwargs, forbid it for args. + Modifies kwargs if needed (these are Aggregate objects, we translate the lookup member variable)""" + for a in args: + assert not '___' in a.lookup, 'PolymorphicModel: annotate()/aggregate(): ___ model lookup supported for keyword arguments only' + for a in six.itervalues(kwargs): + a.lookup = translate_polymorphic_field_path(self.model, a.lookup) + + def annotate(self, *args, **kwargs): + """translate the polymorphic field paths in the kwargs, then call vanilla annotate. + _get_real_instances will do the rest of the job after executing the query.""" + self._process_aggregate_args(args, kwargs) + return super(PolymorphicQuerySet, self).annotate(*args, **kwargs) + + def aggregate(self, *args, **kwargs): + """translate the polymorphic field paths in the kwargs, then call vanilla aggregate. + We need no polymorphic object retrieval for aggregate => switch it off.""" + self._process_aggregate_args(args, kwargs) + self.polymorphic_disabled = True + return super(PolymorphicQuerySet, self).aggregate(*args, **kwargs) + + # Since django_polymorphic 'V1.0 beta2', extra() always returns polymorphic results.^ + # The resulting objects are required to have a unique primary key within the result set + # (otherwise an error is thrown). + # The "polymorphic" keyword argument is not supported anymore. + #def extra(self, *args, **kwargs): + + def _get_real_instances(self, base_result_objects): + """ + Polymorphic object loader + + Does the same as: + + return [ o.get_real_instance() for o in base_result_objects ] + + but more efficiently. + + The list base_result_objects contains the objects from the executed + base class query. The class of all of them is self.model (our base model). + + Some, many or all of these objects were not created and stored as + class self.model, but as a class derived from self.model. We want to re-fetch + these objects from the db as their original class so we can return them + just as they were created/saved. + + We identify these objects by looking at o.polymorphic_ctype, which specifies + the real class of these objects (the class at the time they were saved). + + First, we sort the result objects in base_result_objects for their + subclass (from o.polymorphic_ctype), and then we execute one db query per + subclass of objects. Here, we handle any annotations from annotate(). + + Finally we re-sort the resulting objects into the correct order and + return them as a list. + """ + ordered_id_list = [] # list of ids of result-objects in correct order + results = {} # polymorphic dict of result-objects, keyed with their id (no order) + + # dict contains one entry per unique model type occurring in result, + # in the format idlist_per_model[modelclass]=[list-of-object-ids] + idlist_per_model = defaultdict(list) + + # - sort base_result_object ids into idlist_per_model lists, depending on their real class; + # - also record the correct result order in "ordered_id_list" + # - store objects that already have the correct class into "results" + base_result_objects_by_id = {} + self_model_class_id = ContentType.objects.get_for_model(self.model, for_concrete_model=False).pk + self_concrete_model_class_id = ContentType.objects.get_for_model(self.model, for_concrete_model=True).pk + + for base_object in base_result_objects: + ordered_id_list.append(base_object.pk) + + # check if id of the result object occeres more than once - this can happen e.g. with base_objects.extra(tables=...) + if not base_object.pk in base_result_objects_by_id: + base_result_objects_by_id[base_object.pk] = base_object + + if base_object.polymorphic_ctype_id == self_model_class_id: + # Real class is exactly the same as base class, go straight to results + results[base_object.pk] = base_object + + else: + real_concrete_class = base_object.get_real_instance_class() + real_concrete_class_id = base_object.get_real_concrete_instance_class_id() + + if real_concrete_class_id is None: + # Dealing with a stale content type + continue + elif real_concrete_class_id == self_concrete_model_class_id: + # Real and base classes share the same concrete ancestor, + # upcast it and put it in the results + results[base_object.pk] = transmogrify(real_concrete_class, base_object) + else: + real_concrete_class = ContentType.objects.get_for_id(real_concrete_class_id).model_class() + idlist_per_model[real_concrete_class].append(base_object.pk) + + # django's automatic ".pk" field does not always work correctly for + # custom fields in derived objects (unclear yet who to put the blame on). + # We get different type(o.pk) in this case. + # We work around this by using the real name of the field directly + # for accessing the primary key of the the derived objects. + # We might assume that self.model._meta.pk.name gives us the name of the primary key field, + # but it doesn't. Therefore we use polymorphic_primary_key_name, which we set up in base.py. + pk_name = self.model.polymorphic_primary_key_name + + # For each model in "idlist_per_model" request its objects (the real model) + # from the db and store them in results[]. + # Then we copy the annotate fields from the base objects to the real objects. + # Then we copy the extra() select fields from the base objects to the real objects. + # TODO: defer(), only(): support for these would be around here + for real_concrete_class, idlist in idlist_per_model.items(): + real_objects = real_concrete_class.base_objects.filter(pk__in=idlist) # use pk__in instead #### + real_objects.query.select_related = self.query.select_related # copy select related configuration to new qs + + for real_object in real_objects: + o_pk = getattr(real_object, pk_name) + real_class = real_object.get_real_instance_class() + + # If the real class is a proxy, upcast it + if real_class != real_concrete_class: + real_object = transmogrify(real_class, real_object) + + if self.query.aggregates: + for anno_field_name in six.iterkeys(self.query.aggregates): + attr = getattr(base_result_objects_by_id[o_pk], anno_field_name) + setattr(real_object, anno_field_name, attr) + + if self.query.extra_select: + for select_field_name in six.iterkeys(self.query.extra_select): + attr = getattr(base_result_objects_by_id[o_pk], select_field_name) + setattr(real_object, select_field_name, attr) + + results[o_pk] = real_object + + # re-create correct order and return result list + resultlist = [results[ordered_id] for ordered_id in ordered_id_list if ordered_id in results] + + # set polymorphic_annotate_names in all objects (currently just used for debugging/printing) + if self.query.aggregates: + annotate_names = six.iterkeys(self.query.aggregates) # get annotate field list + for real_object in resultlist: + real_object.polymorphic_annotate_names = annotate_names + + # set polymorphic_extra_select_names in all objects (currently just used for debugging/printing) + if self.query.extra_select: + extra_select_names = six.iterkeys(self.query.extra_select) # get extra select field list + for real_object in resultlist: + real_object.polymorphic_extra_select_names = extra_select_names + + return resultlist + + def iterator(self): + """ + This function is used by Django for all object retrieval. + By overriding it, we modify the objects that this queryset returns + when it is evaluated (or its get method or other object-returning methods are called). + + Here we do the same as: + + base_result_objects=list(super(PolymorphicQuerySet, self).iterator()) + real_results=self._get_real_instances(base_result_objects) + for o in real_results: yield o + + but it requests the objects in chunks from the database, + with Polymorphic_QuerySet_objects_per_request per chunk + """ + base_iter = super(PolymorphicQuerySet, self).iterator() + + # disabled => work just like a normal queryset + if self.polymorphic_disabled: + for o in base_iter: + yield o + raise StopIteration + + while True: + base_result_objects = [] + reached_end = False + + for i in range(Polymorphic_QuerySet_objects_per_request): + try: + o = next(base_iter) + base_result_objects.append(o) + except StopIteration: + reached_end = True + break + + real_results = self._get_real_instances(base_result_objects) + + for o in real_results: + yield o + + if reached_end: + raise StopIteration + + def __repr__(self, *args, **kwargs): + if self.model.polymorphic_query_multiline_output: + result = [repr(o) for o in self.all()] + return '[ ' + ',\n '.join(result) + ' ]' + else: + return super(PolymorphicQuerySet, self).__repr__(*args, **kwargs) + + class _p_list_class(list): + def __repr__(self, *args, **kwargs): + result = [repr(o) for o in self] + return '[ ' + ',\n '.join(result) + ' ]' + + def get_real_instances(self, base_result_objects=None): + "same as _get_real_instances, but make sure that __repr__ for ShowField... creates correct output" + if not base_result_objects: + base_result_objects = self + olist = self._get_real_instances(base_result_objects) + if not self.model.polymorphic_query_multiline_output: + return olist + clist = PolymorphicQuerySet._p_list_class(olist) + return clist diff --git a/awx/lib/site-packages/polymorphic/query_translate.py b/awx/lib/site-packages/polymorphic/query_translate.py new file mode 100644 index 0000000000..b6ee8cc609 --- /dev/null +++ b/awx/lib/site-packages/polymorphic/query_translate.py @@ -0,0 +1,248 @@ +# -*- coding: utf-8 -*- +""" PolymorphicQuerySet support functions + Please see README.rst or DOCS.rst or http://chrisglass.github.com/django_polymorphic/ +""" +from __future__ import absolute_import + +from django.db import models +from django.contrib.contenttypes.models import ContentType +from django.db.models import Q, FieldDoesNotExist +from django.db.models.related import RelatedObject + +from functools import reduce + + +################################################################################### +### PolymorphicQuerySet support functions + +# These functions implement the additional filter- and Q-object functionality. +# They form a kind of small framework for easily adding more +# functionality to filters and Q objects. +# Probably a more general queryset enhancement class could be made out of them. + +def translate_polymorphic_filter_definitions_in_kwargs(queryset_model, kwargs): + """ + Translate the keyword argument list for PolymorphicQuerySet.filter() + + Any kwargs with special polymorphic functionality are replaced in the kwargs + dict with their vanilla django equivalents. + + For some kwargs a direct replacement is not possible, as a Q object is needed + instead to implement the required functionality. In these cases the kwarg is + deleted from the kwargs dict and a Q object is added to the return list. + + Modifies: kwargs dict + Returns: a list of non-keyword-arguments (Q objects) to be added to the filter() query. + """ + additional_args = [] + for field_path, val in kwargs.copy().items(): # Python 3 needs copy + + new_expr = _translate_polymorphic_filter_definition(queryset_model, field_path, val) + + if type(new_expr) == tuple: + # replace kwargs element + del(kwargs[field_path]) + kwargs[new_expr[0]] = new_expr[1] + + elif isinstance(new_expr, models.Q): + del(kwargs[field_path]) + additional_args.append(new_expr) + + return additional_args + + +def translate_polymorphic_Q_object(queryset_model, potential_q_object): + def tree_node_correct_field_specs(my_model, node): + " process all children of this Q node " + for i in range(len(node.children)): + child = node.children[i] + + if type(child) == tuple: + # this Q object child is a tuple => a kwarg like Q( instance_of=ModelB ) + key, val = child + new_expr = _translate_polymorphic_filter_definition(my_model, key, val) + if new_expr: + node.children[i] = new_expr + else: + # this Q object child is another Q object, recursively process this as well + tree_node_correct_field_specs(my_model, child) + + if isinstance(potential_q_object, models.Q): + tree_node_correct_field_specs(queryset_model, potential_q_object) + + return potential_q_object + + +def translate_polymorphic_filter_definitions_in_args(queryset_model, args): + """ + Translate the non-keyword argument list for PolymorphicQuerySet.filter() + + In the args list, we replace all kwargs to Q-objects that contain special + polymorphic functionality with their vanilla django equivalents. + We traverse the Q object tree for this (which is simple). + + TODO: investigate: we modify the Q-objects ina args in-place. Is this OK? + + Modifies: args list + """ + + for q in args: + translate_polymorphic_Q_object(queryset_model, q) + + +def _translate_polymorphic_filter_definition(queryset_model, field_path, field_val): + """ + Translate a keyword argument (field_path=field_val), as used for + PolymorphicQuerySet.filter()-like functions (and Q objects). + + A kwarg with special polymorphic functionality is translated into + its vanilla django equivalent, which is returned, either as tuple + (field_path, field_val) or as Q object. + + Returns: kwarg tuple or Q object or None (if no change is required) + """ + + # handle instance_of expressions or alternatively, + # if this is a normal Django filter expression, return None + if field_path == 'instance_of': + return _create_model_filter_Q(field_val) + elif field_path == 'not_instance_of': + return _create_model_filter_Q(field_val, not_instance_of=True) + elif not '___' in field_path: + return None # no change + + # filter expression contains '___' (i.e. filter for polymorphic field) + # => get the model class specified in the filter expression + newpath = translate_polymorphic_field_path(queryset_model, field_path) + return (newpath, field_val) + + +def translate_polymorphic_field_path(queryset_model, field_path): + """ + Translate a field path from a keyword argument, as used for + PolymorphicQuerySet.filter()-like functions (and Q objects). + Supports leading '-' (for order_by args). + + E.g.: if queryset_model is ModelA, then "ModelC___field3" is translated + into modela__modelb__modelc__field3. + Returns: translated path (unchanged, if no translation needed) + """ + classname, sep, pure_field_path = field_path.partition('___') + if not sep: + return field_path + assert classname, 'PolymorphicModel: %s: bad field specification' % field_path + + negated = False + if classname[0] == '-': + negated = True + classname = classname.lstrip('-') + + if '__' in classname: + # the user has app label prepended to class name via __ => use Django's get_model function + appname, sep, classname = classname.partition('__') + model = models.get_model(appname, classname) + assert model, 'PolymorphicModel: model %s (in app %s) not found!' % (model.__name__, appname) + if not issubclass(model, queryset_model): + e = 'PolymorphicModel: queryset filter error: "' + model.__name__ + '" is not derived from "' + queryset_model.__name__ + '"' + raise AssertionError(e) + + else: + # the user has only given us the class name via ___ + # => select the model from the sub models of the queryset base model + + # Test whether it's actually a regular relation__ _fieldname (the field starting with an _) + # so no tripple ClassName___field was intended. + try: + # rel = (field_object, model, direct, m2m) + field = queryset_model._meta.get_field_by_name(classname)[0] + if isinstance(field, RelatedObject): + # Can also test whether the field exists in the related object to avoid ambiguity between + # class names and field names, but that never happens when your class names are in CamelCase. + return field_path # No exception raised, field does exist. + except FieldDoesNotExist: + pass + + # function to collect all sub-models, this should be optimized (cached) + def add_all_sub_models(model, result): + if issubclass(model, models.Model) and model != models.Model: + # model name is occurring twice in submodel inheritance tree => Error + if model.__name__ in result and model != result[model.__name__]: + e = 'PolymorphicModel: model name alone is ambiguous: %s.%s and %s.%s!\n' + e += 'In this case, please use the syntax: applabel__ModelName___field' + assert model, e % ( + model._meta.app_label, model.__name__, + result[model.__name__]._meta.app_label, result[model.__name__].__name__) + + result[model.__name__] = model + + for b in model.__subclasses__(): + add_all_sub_models(b, result) + + submodels = {} + add_all_sub_models(queryset_model, submodels) + model = submodels.get(classname, None) + assert model, 'PolymorphicModel: model %s not found (not a subclass of %s)!' % (classname, queryset_model.__name__) + + # create new field path for expressions, e.g. for baseclass=ModelA, myclass=ModelC + # 'modelb__modelc" is returned + def _create_base_path(baseclass, myclass): + bases = myclass.__bases__ + for b in bases: + if b == baseclass: + return myclass.__name__.lower() + path = _create_base_path(baseclass, b) + if path: + return path + '__' + myclass.__name__.lower() + return '' + + basepath = _create_base_path(queryset_model, model) + + if negated: + newpath = '-' + else: + newpath = '' + + newpath += basepath + if basepath: + newpath += '__' + + newpath += pure_field_path + return newpath + + +def _create_model_filter_Q(modellist, not_instance_of=False): + """ + Helper function for instance_of / not_instance_of + Creates and returns a Q object that filters for the models in modellist, + including all subclasses of these models (as we want to do the same + as pythons isinstance() ). + . + We recursively collect all __subclasses__(), create a Q filter for each, + and or-combine these Q objects. This could be done much more + efficiently however (regarding the resulting sql), should an optimization + be needed. + """ + + if not modellist: + return None + + from .polymorphic_model import PolymorphicModel + + if type(modellist) != list and type(modellist) != tuple: + if issubclass(modellist, PolymorphicModel): + modellist = [modellist] + else: + assert False, 'PolymorphicModel: instance_of expects a list of (polymorphic) models or a single (polymorphic) model' + + def q_class_with_subclasses(model): + q = Q(polymorphic_ctype=ContentType.objects.get_for_model(model, for_concrete_model=False)) + for subclass in model.__subclasses__(): + q = q | q_class_with_subclasses(subclass) + return q + + qlist = [q_class_with_subclasses(m) for m in modellist] + + q_ored = reduce(lambda a, b: a | b, qlist) + if not_instance_of: + q_ored = ~q_ored + return q_ored diff --git a/awx/lib/site-packages/polymorphic/showfields.py b/awx/lib/site-packages/polymorphic/showfields.py new file mode 100644 index 0000000000..1a279d6392 --- /dev/null +++ b/awx/lib/site-packages/polymorphic/showfields.py @@ -0,0 +1,164 @@ +# -*- coding: utf-8 -*- + +from django.db import models +from django.utils import six + +class ShowFieldBase(object): + """ base class for the ShowField... model mixins, does the work """ + + polymorphic_query_multiline_output = True # cause nicer multiline PolymorphicQuery output + + polymorphic_showfield_type = False + polymorphic_showfield_content = False + + # these may be overridden by the user + polymorphic_showfield_max_line_width = None + polymorphic_showfield_max_field_width = 20 + polymorphic_showfield_old_format = False + + def __repr__(self): + return self.__unicode__() + + def _showfields_get_content(self, field_name, field_type=type(None)): + "helper for __unicode__" + content = getattr(self, field_name) + if self.polymorphic_showfield_old_format: + out = ': ' + else: + out = ' ' + if issubclass(field_type, models.ForeignKey): + if content is None: + out += 'None' + else: + out += content.__class__.__name__ + elif issubclass(field_type, models.ManyToManyField): + out += '%d' % content.count() + elif isinstance(content, six.integer_types): + out += str(content) + elif content is None: + out += 'None' + else: + txt = str(content) + if len(txt) > self.polymorphic_showfield_max_field_width: + txt = txt[:self.polymorphic_showfield_max_field_width - 2] + '..' + out += '"' + txt + '"' + return out + + def _showfields_add_regular_fields(self, parts): + "helper for __unicode__" + done_fields = set() + for field in self._meta.fields + self._meta.many_to_many: + if field.name in self.polymorphic_internal_model_fields or '_ptr' in field.name: + continue + if field.name in done_fields: + continue # work around django diamond inheritance problem + done_fields.add(field.name) + + out = field.name + + # if this is the standard primary key named "id", print it as we did with older versions of django_polymorphic + if field.primary_key and field.name == 'id' and type(field) == models.AutoField: + out += ' ' + str(getattr(self, field.name)) + + # otherwise, display it just like all other fields (with correct type, shortened content etc.) + else: + if self.polymorphic_showfield_type: + out += ' (' + type(field).__name__ + if field.primary_key: + out += '/pk' + out += ')' + + if self.polymorphic_showfield_content: + out += self._showfields_get_content(field.name, type(field)) + + parts.append((False, out, ',')) + + def _showfields_add_dynamic_fields(self, field_list, title, parts): + "helper for __unicode__" + parts.append((True, '- ' + title, ':')) + for field_name in field_list: + out = field_name + content = getattr(self, field_name) + if self.polymorphic_showfield_type: + out += ' (' + type(content).__name__ + ')' + if self.polymorphic_showfield_content: + out += self._showfields_get_content(field_name) + + parts.append((False, out, ',')) + + def __unicode__(self): + # create list ("parts") containing one tuple for each title/field: + # ( bool: new section , item-text , separator to use after item ) + + # start with model name + parts = [(True, self.__class__.__name__, ':')] + + # add all regular fields + self._showfields_add_regular_fields(parts) + + # add annotate fields + if hasattr(self, 'polymorphic_annotate_names'): + self._showfields_add_dynamic_fields(self.polymorphic_annotate_names, 'Ann', parts) + + # add extra() select fields + if hasattr(self, 'polymorphic_extra_select_names'): + self._showfields_add_dynamic_fields(self.polymorphic_extra_select_names, 'Extra', parts) + + # format result + + indent = len(self.__class__.__name__) + 5 + indentstr = ''.rjust(indent) + out = '' + xpos = 0 + possible_line_break_pos = None + + for i in range(len(parts)): + new_section, p, separator = parts[i] + final = (i == len(parts) - 1) + if not final: + next_new_section, _, _ = parts[i + 1] + + if (self.polymorphic_showfield_max_line_width + and xpos + len(p) > self.polymorphic_showfield_max_line_width + and possible_line_break_pos != None): + rest = out[possible_line_break_pos:] + out = out[:possible_line_break_pos] + out += '\n' + indentstr + rest + xpos = indent + len(rest) + + out += p + xpos += len(p) + + if not final: + if not next_new_section: + out += separator + xpos += len(separator) + out += ' ' + xpos += 1 + + if not new_section: + possible_line_break_pos = len(out) + + return '<' + out + '>' + + +class ShowFieldType(ShowFieldBase): + """ model mixin that shows the object's class and it's field types """ + polymorphic_showfield_type = True + + +class ShowFieldContent(ShowFieldBase): + """ model mixin that shows the object's class, it's fields and field contents """ + polymorphic_showfield_content = True + + +class ShowFieldTypeAndContent(ShowFieldBase): + """ model mixin, like ShowFieldContent, but also show field types """ + polymorphic_showfield_type = True + polymorphic_showfield_content = True + + +# compatibility with old class names +ShowFieldTypes = ShowFieldType +ShowFields = ShowFieldContent +ShowFieldsAndTypes = ShowFieldTypeAndContent diff --git a/awx/lib/site-packages/polymorphic/templates/admin/polymorphic/add_type_form.html b/awx/lib/site-packages/polymorphic/templates/admin/polymorphic/add_type_form.html new file mode 100644 index 0000000000..20cc8ab1ef --- /dev/null +++ b/awx/lib/site-packages/polymorphic/templates/admin/polymorphic/add_type_form.html @@ -0,0 +1,11 @@ +{% extends "admin/change_form.html" %} + +{% if save_on_top %} + {% block submit_buttons_top %} + {% include 'admin/submit_line.html' with show_save=1 %} + {% endblock %} +{% endif %} + +{% block submit_buttons_bottom %} + {% include 'admin/submit_line.html' with show_save=1 %} +{% endblock %} diff --git a/awx/lib/site-packages/polymorphic/templates/admin/polymorphic/change_form.html b/awx/lib/site-packages/polymorphic/templates/admin/polymorphic/change_form.html new file mode 100644 index 0000000000..4224c12631 --- /dev/null +++ b/awx/lib/site-packages/polymorphic/templates/admin/polymorphic/change_form.html @@ -0,0 +1,6 @@ +{% extends "admin/change_form.html" %} +{% load polymorphic_admin_tags %} + +{% block breadcrumbs %} + {% breadcrumb_scope base_opts %}{{ block.super }}{% endbreadcrumb_scope %} +{% endblock %} diff --git a/awx/lib/site-packages/polymorphic/templates/admin/polymorphic/delete_confirmation.html b/awx/lib/site-packages/polymorphic/templates/admin/polymorphic/delete_confirmation.html new file mode 100644 index 0000000000..ca0073dac4 --- /dev/null +++ b/awx/lib/site-packages/polymorphic/templates/admin/polymorphic/delete_confirmation.html @@ -0,0 +1,6 @@ +{% extends "admin/delete_confirmation.html" %} +{% load polymorphic_admin_tags %} + +{% block breadcrumbs %} + {% breadcrumb_scope base_opts %}{{ block.super }}{% endbreadcrumb_scope %} +{% endblock %} diff --git a/awx/lib/site-packages/polymorphic/templatetags/__init__.py b/awx/lib/site-packages/polymorphic/templatetags/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/awx/lib/site-packages/polymorphic/templatetags/polymorphic_admin_tags.py b/awx/lib/site-packages/polymorphic/templatetags/polymorphic_admin_tags.py new file mode 100644 index 0000000000..8fc5dca394 --- /dev/null +++ b/awx/lib/site-packages/polymorphic/templatetags/polymorphic_admin_tags.py @@ -0,0 +1,53 @@ +from django.template import Library, Node, TemplateSyntaxError +from django.utils import six + +register = Library() + + +class BreadcrumbScope(Node): + def __init__(self, base_opts, nodelist): + self.base_opts = base_opts + self.nodelist = nodelist # Note, takes advantage of Node.child_nodelists + + @classmethod + def parse(cls, parser, token): + bits = token.split_contents() + if len(bits) == 2: + (tagname, base_opts) = bits + base_opts = parser.compile_filter(base_opts) + nodelist = parser.parse(('endbreadcrumb_scope',)) + parser.delete_first_token() + + return cls( + base_opts=base_opts, + nodelist=nodelist + ) + else: + raise TemplateSyntaxError("{0} tag expects 1 argument".format(token.contents[0])) + + + def render(self, context): + # app_label is really hard to overwrite in the standard Django ModelAdmin. + # To insert it in the template, the entire render_change_form() and delete_view() have to copied and adjusted. + # Instead, have an assignment tag that inserts that in the template. + base_opts = self.base_opts.resolve(context) + new_vars = {} + if base_opts and not isinstance(base_opts, six.string_types): + new_vars = { + 'app_label': base_opts.app_label, # What this is all about + 'opts': base_opts, + } + + new_scope = context.push() + new_scope.update(new_vars) + html = self.nodelist.render(context) + context.pop() + return html + + +@register.tag +def breadcrumb_scope(parser, token): + """ + Easily allow the breadcrumb to be generated in the admin change templates. + """ + return BreadcrumbScope.parse(parser, token) diff --git a/awx/lib/site-packages/polymorphic/tests.py b/awx/lib/site-packages/polymorphic/tests.py new file mode 100644 index 0000000000..376f0f3a04 --- /dev/null +++ b/awx/lib/site-packages/polymorphic/tests.py @@ -0,0 +1,791 @@ +# -*- coding: utf-8 -*- +""" Test Cases + Please see README.rst or DOCS.rst or http://chrisglass.github.com/django_polymorphic/ +""" +from __future__ import print_function +import uuid +import re +from django.db.models.query import QuerySet + +from django.test import TestCase +from django.db.models import Q,Count +from django.db import models +from django.contrib.contenttypes.models import ContentType +from django.utils import six + +from polymorphic import PolymorphicModel, PolymorphicManager, PolymorphicQuerySet +from polymorphic import ShowFieldContent, ShowFieldType, ShowFieldTypeAndContent +from polymorphic.tools_for_tests import UUIDField + + +class PlainA(models.Model): + field1 = models.CharField(max_length=10) +class PlainB(PlainA): + field2 = models.CharField(max_length=10) +class PlainC(PlainB): + field3 = models.CharField(max_length=10) + +class Model2A(ShowFieldType, PolymorphicModel): + field1 = models.CharField(max_length=10) +class Model2B(Model2A): + field2 = models.CharField(max_length=10) +class Model2C(Model2B): + field3 = models.CharField(max_length=10) +class Model2D(Model2C): + field4 = models.CharField(max_length=10) + +class ModelExtraA(ShowFieldTypeAndContent, PolymorphicModel): + field1 = models.CharField(max_length=10) +class ModelExtraB(ModelExtraA): + field2 = models.CharField(max_length=10) +class ModelExtraC(ModelExtraB): + field3 = models.CharField(max_length=10) +class ModelExtraExternal(models.Model): + topic = models.CharField(max_length=10) + +class ModelShow1(ShowFieldType,PolymorphicModel): + field1 = models.CharField(max_length=10) + m2m = models.ManyToManyField('self') +class ModelShow2(ShowFieldContent, PolymorphicModel): + field1 = models.CharField(max_length=10) + m2m = models.ManyToManyField('self') +class ModelShow3(ShowFieldTypeAndContent, PolymorphicModel): + field1 = models.CharField(max_length=10) + m2m = models.ManyToManyField('self') + +class ModelShow1_plain(PolymorphicModel): + field1 = models.CharField(max_length=10) +class ModelShow2_plain(ModelShow1_plain): + field2 = models.CharField(max_length=10) + + +class Base(ShowFieldType, PolymorphicModel): + field_b = models.CharField(max_length=10) +class ModelX(Base): + field_x = models.CharField(max_length=10) +class ModelY(Base): + field_y = models.CharField(max_length=10) + +class Enhance_Plain(models.Model): + field_p = models.CharField(max_length=10) +class Enhance_Base(ShowFieldTypeAndContent, PolymorphicModel): + field_b = models.CharField(max_length=10) +class Enhance_Inherit(Enhance_Base, Enhance_Plain): + field_i = models.CharField(max_length=10) + +class DiamondBase(models.Model): + field_b = models.CharField(max_length=10) +class DiamondX(DiamondBase): + field_x = models.CharField(max_length=10) +class DiamondY(DiamondBase): + field_y = models.CharField(max_length=10) +class DiamondXY(DiamondX, DiamondY): + pass + +class RelationBase(ShowFieldTypeAndContent, PolymorphicModel): + field_base = models.CharField(max_length=10) + fk = models.ForeignKey('self', null=True, related_name='relationbase_set') + m2m = models.ManyToManyField('self') +class RelationA(RelationBase): + field_a = models.CharField(max_length=10) +class RelationB(RelationBase): + field_b = models.CharField(max_length=10) +class RelationBC(RelationB): + field_c = models.CharField(max_length=10) + +class RelatingModel(models.Model): + many2many = models.ManyToManyField(Model2A) + +class One2OneRelatingModel(PolymorphicModel): + one2one = models.OneToOneField(Model2A) + field1 = models.CharField(max_length=10) + +class One2OneRelatingModelDerived(One2OneRelatingModel): + field2 = models.CharField(max_length=10) + +class MyManagerQuerySet(PolymorphicQuerySet): + def my_queryset_foo(self): + return self.all() # Just a method to prove the existance of the custom queryset. + +class MyManager(PolymorphicManager): + queryset_class = MyManagerQuerySet + + def get_query_set(self): + return super(MyManager, self).get_query_set().order_by('-field1') + +class ModelWithMyManager(ShowFieldTypeAndContent, Model2A): + objects = MyManager() + field4 = models.CharField(max_length=10) + +class MROBase1(ShowFieldType, PolymorphicModel): + objects = MyManager() + field1 = models.CharField(max_length=10) # needed as MyManager uses it +class MROBase2(MROBase1): + pass # Django vanilla inheritance does not inherit MyManager as _default_manager here +class MROBase3(models.Model): + objects = PolymorphicManager() +class MRODerived(MROBase2, MROBase3): + pass + +class ParentModelWithManager(PolymorphicModel): + pass +class ChildModelWithManager(PolymorphicModel): + # Also test whether foreign keys receive the manager: + fk = models.ForeignKey(ParentModelWithManager, related_name='childmodel_set') + objects = MyManager() + + +class PlainMyManagerQuerySet(QuerySet): + def my_queryset_foo(self): + return self.all() # Just a method to prove the existance of the custom queryset. + +class PlainMyManager(models.Manager): + def my_queryset_foo(self): + return self.get_query_set().my_queryset_foo() + + def get_query_set(self): + return PlainMyManagerQuerySet(self.model, using=self._db) + +class PlainParentModelWithManager(models.Model): + pass + +class PlainChildModelWithManager(models.Model): + fk = models.ForeignKey(PlainParentModelWithManager, related_name='childmodel_set') + objects = PlainMyManager() + + +class MgrInheritA(models.Model): + mgrA = models.Manager() + mgrA2 = models.Manager() + field1 = models.CharField(max_length=10) +class MgrInheritB(MgrInheritA): + mgrB = models.Manager() + field2 = models.CharField(max_length=10) +class MgrInheritC(ShowFieldTypeAndContent, MgrInheritB): + pass + +class BlogBase(ShowFieldTypeAndContent, PolymorphicModel): + name = models.CharField(max_length=10) +class BlogA(BlogBase): + info = models.CharField(max_length=10) +class BlogB(BlogBase): + pass +class BlogEntry(ShowFieldTypeAndContent, PolymorphicModel): + blog = models.ForeignKey(BlogA) + text = models.CharField(max_length=10) + +class BlogEntry_limit_choices_to(ShowFieldTypeAndContent, PolymorphicModel): + blog = models.ForeignKey(BlogBase) + text = models.CharField(max_length=10) + +class ModelFieldNameTest(ShowFieldType, PolymorphicModel): + modelfieldnametest = models.CharField(max_length=10) + +class InitTestModel(ShowFieldType, PolymorphicModel): + bar = models.CharField(max_length=100) + def __init__(self, *args, **kwargs): + kwargs['bar'] = self.x() + super(InitTestModel, self).__init__(*args, **kwargs) +class InitTestModelSubclass(InitTestModel): + def x(self): + return 'XYZ' + +# models from github issue +class Top(PolymorphicModel): + name = models.CharField(max_length=50) + class Meta: + ordering = ('pk',) +class Middle(Top): + description = models.TextField() +class Bottom(Middle): + author = models.CharField(max_length=50) + +class UUIDProject(ShowFieldTypeAndContent, PolymorphicModel): + uuid_primary_key = UUIDField(primary_key = True) + topic = models.CharField(max_length = 30) +class UUIDArtProject(UUIDProject): + artist = models.CharField(max_length = 30) +class UUIDResearchProject(UUIDProject): + supervisor = models.CharField(max_length = 30) + +class UUIDPlainA(models.Model): + uuid_primary_key = UUIDField(primary_key = True) + field1 = models.CharField(max_length=10) +class UUIDPlainB(UUIDPlainA): + field2 = models.CharField(max_length=10) +class UUIDPlainC(UUIDPlainB): + field3 = models.CharField(max_length=10) + +# base -> proxy +class ProxyBase(PolymorphicModel): + some_data = models.CharField(max_length=128) +class ProxyChild(ProxyBase): + class Meta: + proxy = True + +# base -> proxy -> real models +class ProxiedBase(ShowFieldTypeAndContent, PolymorphicModel): + name = models.CharField(max_length=10) +class ProxyModelBase(ProxiedBase): + class Meta: + proxy = True +class ProxyModelA(ProxyModelBase): + field1 = models.CharField(max_length=10) +class ProxyModelB(ProxyModelBase): + field2 = models.CharField(max_length=10) + + +# test bad field name +#class TestBadFieldModel(ShowFieldType, PolymorphicModel): +# instance_of = models.CharField(max_length=10) + +# validation error: "polymorphic.relatednameclash: Accessor for field 'polymorphic_ctype' clashes +# with related field 'ContentType.relatednameclash_set'." (reported by Andrew Ingram) +# fixed with related_name +class RelatedNameClash(ShowFieldType, PolymorphicModel): + ctype = models.ForeignKey(ContentType, null=True, editable=False) + + +class PolymorphicTests(TestCase): + """ + The test suite + """ + def test_diamond_inheritance(self): + # Django diamond problem + # https://code.djangoproject.com/ticket/10808 + o1 = DiamondXY.objects.create(field_b='b', field_x='x', field_y='y') + o2 = DiamondXY.objects.get() + + if o2.field_b != 'b': + print('') + print('# known django model inheritance diamond problem detected') + print('DiamondXY fields 1: field_b "{0}", field_x "{1}", field_y "{2}"'.format(o1.field_b, o1.field_x, o1.field_y)) + print('DiamondXY fields 2: field_b "{0}", field_x "{1}", field_y "{2}"'.format(o2.field_b, o2.field_x, o2.field_y)) + + + def test_annotate_aggregate_order(self): + # create a blog of type BlogA + # create two blog entries in BlogA + # create some blogs of type BlogB to make the BlogBase table data really polymorphic + blog = BlogA.objects.create(name='B1', info='i1') + blog.blogentry_set.create(text='bla') + BlogEntry.objects.create(blog=blog, text='bla2') + BlogB.objects.create(name='Bb1') + BlogB.objects.create(name='Bb2') + BlogB.objects.create(name='Bb3') + + qs = BlogBase.objects.annotate(entrycount=Count('BlogA___blogentry')) + self.assertEqual(len(qs), 4) + + for o in qs: + if o.name == 'B1': + self.assertEqual(o.entrycount, 2) + else: + self.assertEqual(o.entrycount, 0) + + x = BlogBase.objects.aggregate(entrycount=Count('BlogA___blogentry')) + self.assertEqual(x['entrycount'], 2) + + # create some more blogs for next test + BlogA.objects.create(name='B2', info='i2') + BlogA.objects.create(name='B3', info='i3') + BlogA.objects.create(name='B4', info='i4') + BlogA.objects.create(name='B5', info='i5') + + # test ordering for field in all entries + expected = ''' +[ , + , + , + , + , + , + , + ]''' + x = '\n' + repr(BlogBase.objects.order_by('-name')) + self.assertEqual(x, expected) + + # test ordering for field in one subclass only + # MySQL and SQLite return this order + expected1=''' +[ , + , + , + , + , + , + , + ]''' + + # PostgreSQL returns this order + expected2=''' +[ , + , + , + , + , + , + , + ]''' + + x = '\n' + repr(BlogBase.objects.order_by('-BlogA___info')) + self.assertTrue(x == expected1 or x == expected2) + + + def test_limit_choices_to(self): + """ + this is not really a testcase, as limit_choices_to only affects the Django admin + """ + # create a blog of type BlogA + blog_a = BlogA.objects.create(name='aa', info='aa') + blog_b = BlogB.objects.create(name='bb') + # create two blog entries + entry1 = BlogEntry_limit_choices_to.objects.create(blog=blog_b, text='bla2') + entry2 = BlogEntry_limit_choices_to.objects.create(blog=blog_b, text='bla2') + + + def test_primary_key_custom_field_problem(self): + """ + object retrieval problem occuring with some custom primary key fields (UUIDField as test case) + """ + UUIDProject.objects.create(topic="John's gathering") + UUIDArtProject.objects.create(topic="Sculpting with Tim", artist="T. Turner") + UUIDResearchProject.objects.create(topic="Swallow Aerodynamics", supervisor="Dr. Winter") + + qs = UUIDProject.objects.all() + ol = list(qs) + a = qs[0] + b = qs[1] + c = qs[2] + self.assertEqual(len(qs), 3) + self.assertIsInstance(a.uuid_primary_key, uuid.UUID) + self.assertIsInstance(a.pk, uuid.UUID) + + res = re.sub(' "(.*?)..", topic',', topic', repr(qs)) + res_exp = """[ , + , + ]""" + self.assertEqual(res, res_exp) + #if (a.pk!= uuid.UUID or c.pk!= uuid.UUID): + # print() + # print('# known inconstency with custom primary key field detected (django problem?)') + + a = UUIDPlainA.objects.create(field1='A1') + b = UUIDPlainB.objects.create(field1='B1', field2='B2') + c = UUIDPlainC.objects.create(field1='C1', field2='C2', field3='C3') + qs = UUIDPlainA.objects.all() + if a.pk!= uuid.UUID or c.pk!= uuid.UUID: + print('') + print('# known type inconstency with custom primary key field detected (django problem?)') + + + def create_model2abcd(self): + """ + Create the chain of objects of Model2, + this is reused in various tests. + """ + Model2A.objects.create(field1='A1') + Model2B.objects.create(field1='B1', field2='B2') + Model2C.objects.create(field1='C1', field2='C2', field3='C3') + Model2D.objects.create(field1='D1', field2='D2', field3='D3', field4='D4') + + + def test_simple_inheritance(self): + self.create_model2abcd() + + objects = list(Model2A.objects.all()) + self.assertEqual(repr(objects[0]), '') + self.assertEqual(repr(objects[1]), '') + self.assertEqual(repr(objects[2]), '') + self.assertEqual(repr(objects[3]), '') + + + def test_manual_get_real_instance(self): + self.create_model2abcd() + + o = Model2A.objects.non_polymorphic().get(field1='C1') + self.assertEqual(repr(o.get_real_instance()), '') + + + def test_non_polymorphic(self): + self.create_model2abcd() + + objects = list(Model2A.objects.all().non_polymorphic()) + self.assertEqual(repr(objects[0]), '') + self.assertEqual(repr(objects[1]), '') + self.assertEqual(repr(objects[2]), '') + self.assertEqual(repr(objects[3]), '') + + + def test_get_real_instances(self): + self.create_model2abcd() + qs = Model2A.objects.all().non_polymorphic() + + # from queryset + objects = qs.get_real_instances() + self.assertEqual(repr(objects[0]), '') + self.assertEqual(repr(objects[1]), '') + self.assertEqual(repr(objects[2]), '') + self.assertEqual(repr(objects[3]), '') + + # from a manual list + objects = Model2A.objects.get_real_instances(list(qs)) + self.assertEqual(repr(objects[0]), '') + self.assertEqual(repr(objects[1]), '') + self.assertEqual(repr(objects[2]), '') + self.assertEqual(repr(objects[3]), '') + + + def test_translate_polymorphic_q_object(self): + self.create_model2abcd() + + q = Model2A.translate_polymorphic_Q_object(Q(instance_of=Model2C)) + objects = Model2A.objects.filter(q) + self.assertEqual(repr(objects[0]), '') + self.assertEqual(repr(objects[1]), '') + + + def test_base_manager(self): + def show_base_manager(model): + return "{0} {1}".format( + repr(type(model._base_manager)), + repr(model._base_manager.model) + ) + + self.assertEqual(show_base_manager(PlainA), " ") + self.assertEqual(show_base_manager(PlainB), " ") + self.assertEqual(show_base_manager(PlainC), " ") + + self.assertEqual(show_base_manager(Model2A), " ") + self.assertEqual(show_base_manager(Model2B), " ") + self.assertEqual(show_base_manager(Model2C), " ") + + self.assertEqual(show_base_manager(One2OneRelatingModel), " ") + self.assertEqual(show_base_manager(One2OneRelatingModelDerived), " ") + + + def test_foreignkey_field(self): + self.create_model2abcd() + + object2a = Model2A.base_objects.get(field1='C1') + self.assertEqual(repr(object2a.model2b), '') + + object2b = Model2B.base_objects.get(field1='C1') + self.assertEqual(repr(object2b.model2c), '') + + + def test_onetoone_field(self): + self.create_model2abcd() + + a = Model2A.base_objects.get(field1='C1') + b = One2OneRelatingModelDerived.objects.create(one2one=a, field1='f1', field2='f2') + + # this result is basically wrong, probably due to Django cacheing (we used base_objects), but should not be a problem + self.assertEqual(repr(b.one2one), '') + + c = One2OneRelatingModelDerived.objects.get(field1='f1') + self.assertEqual(repr(c.one2one), '') + self.assertEqual(repr(a.one2onerelatingmodel), '') + + + def test_manytomany_field(self): + # Model 1 + o = ModelShow1.objects.create(field1='abc') + o.m2m.add(o) + o.save() + self.assertEqual(repr(ModelShow1.objects.all()), '[ ]') + + # Model 2 + o = ModelShow2.objects.create(field1='abc') + o.m2m.add(o) + o.save() + self.assertEqual(repr(ModelShow2.objects.all()), '[ ]') + + # Model 3 + o=ModelShow3.objects.create(field1='abc') + o.m2m.add(o) + o.save() + self.assertEqual(repr(ModelShow3.objects.all()), '[ ]') + self.assertEqual(repr(ModelShow1.objects.all().annotate(Count('m2m'))), '[ ]') + self.assertEqual(repr(ModelShow2.objects.all().annotate(Count('m2m'))), '[ ]') + self.assertEqual(repr(ModelShow3.objects.all().annotate(Count('m2m'))), '[ ]') + + # no pretty printing + ModelShow1_plain.objects.create(field1='abc') + ModelShow2_plain.objects.create(field1='abc', field2='def') + self.assertEqual(repr(ModelShow1_plain.objects.all()), '[, ]') + + + def test_extra_method(self): + self.create_model2abcd() + + objects = list(Model2A.objects.extra(where=['id IN (2, 3)'])) + self.assertEqual(repr(objects[0]), '') + self.assertEqual(repr(objects[1]), '') + + objects = Model2A.objects.extra(select={"select_test": "field1 = 'A1'"}, where=["field1 = 'A1' OR field1 = 'B1'"], order_by=['-id']) + self.assertEqual(repr(objects[0]), '') + self.assertEqual(repr(objects[1]), '') + self.assertEqual(len(objects), 2) # Placed after the other tests, only verifying whether there are no more additional objects. + + ModelExtraA.objects.create(field1='A1') + ModelExtraB.objects.create(field1='B1', field2='B2') + ModelExtraC.objects.create(field1='C1', field2='C2', field3='C3') + ModelExtraExternal.objects.create(topic='extra1') + ModelExtraExternal.objects.create(topic='extra2') + ModelExtraExternal.objects.create(topic='extra3') + objects = ModelExtraA.objects.extra(tables=["polymorphic_modelextraexternal"], select={"topic":"polymorphic_modelextraexternal.topic"}, where=["polymorphic_modelextraa.id = polymorphic_modelextraexternal.id"]) + if six.PY3: + self.assertEqual(repr(objects[0]), '') + self.assertEqual(repr(objects[1]), '') + self.assertEqual(repr(objects[2]), '') + else: + self.assertEqual(repr(objects[0]), '') + self.assertEqual(repr(objects[1]), '') + self.assertEqual(repr(objects[2]), '') + self.assertEqual(len(objects), 3) + + + def test_instance_of_filter(self): + self.create_model2abcd() + + objects = Model2A.objects.instance_of(Model2B) + self.assertEqual(repr(objects[0]), '') + self.assertEqual(repr(objects[1]), '') + self.assertEqual(repr(objects[2]), '') + self.assertEqual(len(objects), 3) + + objects = Model2A.objects.filter(instance_of=Model2B) + self.assertEqual(repr(objects[0]), '') + self.assertEqual(repr(objects[1]), '') + self.assertEqual(repr(objects[2]), '') + self.assertEqual(len(objects), 3) + + objects = Model2A.objects.filter(Q(instance_of=Model2B)) + self.assertEqual(repr(objects[0]), '') + self.assertEqual(repr(objects[1]), '') + self.assertEqual(repr(objects[2]), '') + self.assertEqual(len(objects), 3) + + objects = Model2A.objects.not_instance_of(Model2B) + self.assertEqual(repr(objects[0]), '') + self.assertEqual(len(objects), 1) + + + def test_polymorphic___filter(self): + self.create_model2abcd() + + objects = Model2A.objects.filter(Q( Model2B___field2='B2') | Q( Model2C___field3='C3')) + self.assertEqual(len(objects), 2) + self.assertEqual(repr(objects[0]), '') + self.assertEqual(repr(objects[1]), '') + + + def test_delete(self): + self.create_model2abcd() + + oa = Model2A.objects.get(id=2) + self.assertEqual(repr(oa), '') + self.assertEqual(Model2A.objects.count(), 4) + + oa.delete() + objects = Model2A.objects.all() + self.assertEqual(repr(objects[0]), '') + self.assertEqual(repr(objects[1]), '') + self.assertEqual(repr(objects[2]), '') + self.assertEqual(len(objects), 3) + + + def test_combine_querysets(self): + ModelX.objects.create(field_x='x') + ModelY.objects.create(field_y='y') + + qs = Base.objects.instance_of(ModelX) | Base.objects.instance_of(ModelY) + self.assertEqual(repr(qs[0]), '') + self.assertEqual(repr(qs[1]), '') + self.assertEqual(len(qs), 2) + + + def test_multiple_inheritance(self): + # multiple inheritance, subclassing third party models (mix PolymorphicModel with models.Model) + + Enhance_Base.objects.create(field_b='b-base') + Enhance_Inherit.objects.create(field_b='b-inherit', field_p='p', field_i='i') + + qs = Enhance_Base.objects.all() + self.assertEqual(repr(qs[0]), '') + self.assertEqual(repr(qs[1]), '') + self.assertEqual(len(qs), 2) + + + def test_relation_base(self): + # ForeignKey, ManyToManyField + obase = RelationBase.objects.create(field_base='base') + oa = RelationA.objects.create(field_base='A1', field_a='A2', fk=obase) + ob = RelationB.objects.create(field_base='B1', field_b='B2', fk=oa) + oc = RelationBC.objects.create(field_base='C1', field_b='C2', field_c='C3', fk=oa) + oa.m2m.add(oa) + oa.m2m.add(ob) + + objects = RelationBase.objects.all() + self.assertEqual(repr(objects[0]), '') + self.assertEqual(repr(objects[1]), '') + self.assertEqual(repr(objects[2]), '') + self.assertEqual(repr(objects[3]), '') + self.assertEqual(len(objects), 4) + + oa = RelationBase.objects.get(id=2) + self.assertEqual(repr(oa.fk), '') + + objects = oa.relationbase_set.all() + self.assertEqual(repr(objects[0]), '') + self.assertEqual(repr(objects[1]), '') + self.assertEqual(len(objects), 2) + + ob = RelationBase.objects.get(id=3) + self.assertEqual(repr(ob.fk), '') + + oa = RelationA.objects.get() + objects = oa.m2m.all() + self.assertEqual(repr(objects[0]), '') + self.assertEqual(repr(objects[1]), '') + self.assertEqual(len(objects), 2) + + + def test_user_defined_manager(self): + self.create_model2abcd() + ModelWithMyManager.objects.create(field1='D1a', field4='D4a') + ModelWithMyManager.objects.create(field1='D1b', field4='D4b') + + objects = ModelWithMyManager.objects.all() # MyManager should reverse the sorting of field1 + self.assertEqual(repr(objects[0]), '') + self.assertEqual(repr(objects[1]), '') + self.assertEqual(len(objects), 2) + + self.assertIs(type(ModelWithMyManager.objects), MyManager) + self.assertIs(type(ModelWithMyManager._default_manager), MyManager) + self.assertIs(type(ModelWithMyManager.base_objects), models.Manager) + + + def test_manager_inheritance(self): + # by choice of MRO, should be MyManager from MROBase1. + self.assertIs(type(MRODerived.objects), MyManager) + + # check for correct default manager + self.assertIs(type(MROBase1._default_manager), MyManager) + + # Django vanilla inheritance does not inherit MyManager as _default_manager here + self.assertIs(type(MROBase2._default_manager), MyManager) + + + def test_queryset_assignment(self): + # This is just a consistency check for now, testing standard Django behavior. + parent = PlainParentModelWithManager.objects.create() + child = PlainChildModelWithManager.objects.create(fk=parent) + self.assertIs(type(PlainParentModelWithManager._default_manager), models.Manager) + self.assertIs(type(PlainChildModelWithManager._default_manager), PlainMyManager) + self.assertIs(type(PlainChildModelWithManager.objects), PlainMyManager) + self.assertIs(type(PlainChildModelWithManager.objects.all()), PlainMyManagerQuerySet) + + # A related set is created using the model's _default_manager, so does gain extra methods. + self.assertIs(type(parent.childmodel_set.my_queryset_foo()), PlainMyManagerQuerySet) + + # For polymorphic models, the same should happen. + parent = ParentModelWithManager.objects.create() + child = ChildModelWithManager.objects.create(fk=parent) + self.assertIs(type(ParentModelWithManager._default_manager), PolymorphicManager) + self.assertIs(type(ChildModelWithManager._default_manager), MyManager) + self.assertIs(type(ChildModelWithManager.objects), MyManager) + self.assertIs(type(ChildModelWithManager.objects.my_queryset_foo()), MyManagerQuerySet) + + # A related set is created using the model's _default_manager, so does gain extra methods. + self.assertIs(type(parent.childmodel_set.my_queryset_foo()), MyManagerQuerySet) + + + def test_proxy_models(self): + # prepare some data + for data in ('bleep bloop', 'I am a', 'computer'): + ProxyChild.objects.create(some_data=data) + + # this caches ContentType queries so they don't interfere with our query counts later + list(ProxyBase.objects.all()) + + # one query per concrete class + with self.assertNumQueries(1): + items = list(ProxyBase.objects.all()) + + self.assertIsInstance(items[0], ProxyChild) + + + def test_content_types_for_proxy_models(self): + """Checks if ContentType is capable of returning proxy models.""" + from django.db.models import Model + from django.contrib.contenttypes.models import ContentType + + ct = ContentType.objects.get_for_model(ProxyChild, for_concrete_model=False) + self.assertEqual(ProxyChild, ct.model_class()) + + + def test_proxy_model_inheritance(self): + """ + Polymorphic abilities should also work when the base model is a proxy object. + """ + # The managers should point to the proper objects. + # otherwise, the whole excersise is pointless. + self.assertEqual(ProxiedBase.objects.model, ProxiedBase) + self.assertEqual(ProxyModelBase.objects.model, ProxyModelBase) + self.assertEqual(ProxyModelA.objects.model, ProxyModelA) + self.assertEqual(ProxyModelB.objects.model, ProxyModelB) + + # Create objects + ProxyModelA.objects.create(name="object1") + ProxyModelB.objects.create(name="object2", field2="bb") + + # Getting single objects + object1 = ProxyModelBase.objects.get(name='object1') + object2 = ProxyModelBase.objects.get(name='object2') + self.assertEqual(repr(object1), '') + self.assertEqual(repr(object2), '') + self.assertIsInstance(object1, ProxyModelA) + self.assertIsInstance(object2, ProxyModelB) + + # Same for lists + objects = list(ProxyModelBase.objects.all().order_by('name')) + self.assertEqual(repr(objects[0]), '') + self.assertEqual(repr(objects[1]), '') + self.assertIsInstance(objects[0], ProxyModelA) + self.assertIsInstance(objects[1], ProxyModelB) + + + def test_fix_getattribute(self): + ### fixed issue in PolymorphicModel.__getattribute__: field name same as model name + o = ModelFieldNameTest.objects.create(modelfieldnametest='1') + self.assertEqual(repr(o), '') + + # if subclass defined __init__ and accessed class members, + # __getattribute__ had a problem: "...has no attribute 'sub_and_superclass_dict'" + o = InitTestModelSubclass.objects.create() + self.assertEqual(o.bar, 'XYZ') + + +class RegressionTests(TestCase): + + def test_for_query_result_incomplete_with_inheritance(self): + """ https://github.com/bconstantin/django_polymorphic/issues/15 """ + + top = Top() + top.save() + middle = Middle() + middle.save() + bottom = Bottom() + bottom.save() + + expected_queryset = [top, middle, bottom] + self.assertQuerysetEqual(Top.objects.all(), [repr(r) for r in expected_queryset]) + + expected_queryset = [middle, bottom] + self.assertQuerysetEqual(Middle.objects.all(), [repr(r) for r in expected_queryset]) + + expected_queryset = [bottom] + self.assertQuerysetEqual(Bottom.objects.all(), [repr(r) for r in expected_queryset]) + diff --git a/awx/lib/site-packages/polymorphic/tools_for_tests.py b/awx/lib/site-packages/polymorphic/tools_for_tests.py new file mode 100644 index 0000000000..b7c017dcb2 --- /dev/null +++ b/awx/lib/site-packages/polymorphic/tools_for_tests.py @@ -0,0 +1,146 @@ +# -*- coding: utf-8 -*- + +#################################################################### + +import uuid + +from django import forms +from django.db import models +from django.utils.encoding import smart_text +from django.utils import six + +class UUIDVersionError(Exception): + pass + + +class UUIDField(six.with_metaclass(models.SubfieldBase, models.CharField)): + """Encode and stores a Python uuid.UUID in a manner that is appropriate + for the given datatabase that we are using. + + For sqlite3 or MySQL we save it as a 36-character string value + For PostgreSQL we save it as a uuid field + + This class supports type 1, 2, 4, and 5 UUID's. + """ + + _CREATE_COLUMN_TYPES = { + 'postgresql_psycopg2': 'uuid', + 'postgresql': 'uuid' + } + + def __init__(self, verbose_name=None, name=None, auto=True, version=1, node=None, clock_seq=None, namespace=None, **kwargs): + """Contruct a UUIDField. + + @param verbose_name: Optional verbose name to use in place of what + Django would assign. + @param name: Override Django's name assignment + @param auto: If True, create a UUID value if one is not specified. + @param version: By default we create a version 1 UUID. + @param node: Used for version 1 UUID's. If not supplied, then the uuid.getnode() function is called to obtain it. This can be slow. + @param clock_seq: Used for version 1 UUID's. If not supplied a random 14-bit sequence number is chosen + @param namespace: Required for version 3 and version 5 UUID's. + @param name: Required for version4 and version 5 UUID's. + + See Also: + - Python Library Reference, section 18.16 for more information. + - RFC 4122, "A Universally Unique IDentifier (UUID) URN Namespace" + + If you want to use one of these as a primary key for a Django + model, do this:: + id = UUIDField(primary_key=True) + This will currently I{not} work with Jython because PostgreSQL support + in Jython is not working for uuid column types. + """ + self.max_length = 36 + kwargs['max_length'] = self.max_length + if auto: + kwargs['blank'] = True + kwargs.setdefault('editable', False) + + self.auto = auto + self.version = version + if version == 1: + self.node, self.clock_seq = node, clock_seq + elif version == 3 or version == 5: + self.namespace, self.name = namespace, name + + super(UUIDField, self).__init__(verbose_name=verbose_name, + name=name, **kwargs) + + def create_uuid(self): + if not self.version or self.version == 4: + return uuid.uuid4() + elif self.version == 1: + return uuid.uuid1(self.node, self.clock_seq) + elif self.version == 2: + raise UUIDVersionError("UUID version 2 is not supported.") + elif self.version == 3: + return uuid.uuid3(self.namespace, self.name) + elif self.version == 5: + return uuid.uuid5(self.namespace, self.name) + else: + raise UUIDVersionError("UUID version %s is not valid." % self.version) + + def db_type(self, connection): + from django.conf import settings + full_database_type = settings.DATABASES['default']['ENGINE'] + database_type = full_database_type.split('.')[-1] + return UUIDField._CREATE_COLUMN_TYPES.get(database_type, "char(%s)" % self.max_length) + + def to_python(self, value): + """Return a uuid.UUID instance from the value returned by the database.""" + # + # This is the proper way... But this doesn't work correctly when + # working with an inherited model + # + if not value: + return None + if isinstance(value, uuid.UUID): + return value + # attempt to parse a UUID + return uuid.UUID(smart_text(value)) + + # + # If I do the following (returning a String instead of a UUID + # instance), everything works. + # + + #if not value: + # return None + #if isinstance(value, uuid.UUID): + # return smart_text(value) + #else: + # return value + + def pre_save(self, model_instance, add): + if self.auto and add: + value = self.create_uuid() + setattr(model_instance, self.attname, value) + else: + value = super(UUIDField, self).pre_save(model_instance, add) + if self.auto and not value: + value = self.create_uuid() + setattr(model_instance, self.attname, value) + return value + + def get_db_prep_value(self, value, connection, prepared): + """Casts uuid.UUID values into the format expected by the back end for use in queries""" + if isinstance(value, uuid.UUID): + return smart_text(value) + return value + + def value_to_string(self, obj): + val = self._get_val_from_obj(obj) + if val is None: + data = '' + else: + data = smart_text(val) + return data + + def formfield(self, **kwargs): + defaults = { + 'form_class': forms.CharField, + 'max_length': self.max_length + } + defaults.update(kwargs) + return super(UUIDField, self).formfield(**defaults) diff --git a/requirements/dev_local.txt b/requirements/dev_local.txt index 95621ec79c..f40ce27076 100644 --- a/requirements/dev_local.txt +++ b/requirements/dev_local.txt @@ -62,6 +62,7 @@ Django-1.5.5.tar.gz #django-celery-3.1.1.tar.gz #django-extensions-1.2.5.tar.gz #django-jsonfield-0.9.12.tar.gz + #django_polymorphic-0.5.3.tar.gz #django-split-settings-0.1.1.tar.gz #django-taggit-0.11.2.tar.gz #djangorestframework-2.3.10.tar.gz @@ -93,3 +94,4 @@ ipython-1.1.0.tar.gz # - psycopg2 (via "yum install python-psycopg2") # - python-ldap (via "yum install python-ldap") # - readline-6.2.4.1.tar.gz (for the ipython shell) +# - python-zmq (for using the job callback receiver) diff --git a/requirements/django_polymorphic-0.5.3.tar.gz b/requirements/django_polymorphic-0.5.3.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..0050d4f75595707117ee93243eeb3f7fd64f3dc9 GIT binary patch literal 33698 zcmV)TK(W6ciwFqiemPPC|72-%bT4FTVQyz{UvO`1d2MfUaA;{`Eif)ME;BB4VR8WM zy=!~h)|D`t&wQT#2b4Z}2__UQO0qpi4c(DtrP0*4NOIG>u7(ClNJ32lGyq!GWO9D{ zS(kms1}}=^rmgg}u|)3c+H0@9?rZY*IJ?Y;^L%-rf2CX3u|;%#&=AWaFFRG|k?XQT4G} zasChY_LiJ~-#GuBFSd8L0Rg@Uw(rjWSN~~!arg7@{Bx`O|LV_w+B$ym?aK}5|C0Ov zsQ=)hegAhJ>^-`>|DWaOc~ZrbxQe&_k`!f{XZt}v+HSpwXUTrRD6nOqKufhEBx#*4 zX0y1s*$+;Wcs5PSGI*sM2glhJK&*tIn`<;8w*h^?x84)X+m!p7p8tz;Ib)BT_- z(oq~w|ML?6#Bp2C(s7cNFz1ugr>&<+IWE$9MLUY3Af4fI_5-z`s)#?N<<>Zj^5Sy& znxc7j`NvTKo4p#$;<8GLR-k_N0mm+rig&u%xaKJF6owcr(&=Oiu(n#1>Pz*D34aE( z0eaPHuPYOW8ynw|QQSbxIZ_S{70f@xeB)E=YZ&i*^ zFVf@#oY-_4trvo4 zR{)53TIRuZUc4&-7(g8mawbh<`hpF|91yMW6TPi84he5E3z!ON59 z{7pe$c@7jB0hZ14qM|oIZ=kmRp1t^BA|A%PF!q6qN~eINa8~#8VnV+J`9+=dhi~8N zn>HK{`4YW-+w~770AJnAlX4&EahjFHGz{~L5J*oK2s4tOw{Nq&8rHuw$2`nuqcp=Y z>1`>Ks>Bse(u<3vK-APLd|&PcgW!GH5B?Yay928;2RbzXHwGRNo{B}86kC(zBF%88 zaR$6X;XCH9;Jzj$VHcd1Y%&wT~^cn7Pglk6leZ*X<6Y5kJxYe^3)P@^Ep z#_$3FC}d;U$c%6DI9?FW21hY$(47L>K=&efzetP3;WTh8ppF2009^(LfBfRb(Mj-M zFOOdUE?6+*u`c)$(u*jq#qSV=6;cD(6&%lm-Yj^Z@QwNqPl3L`+gaur z^G(d#)W8!Nge9&zB@+}Y={u%d$S*4P!vYNwQfMCyN*x?zh zb%9q0y1cppxh316DgL$-J>0m*qYZoPf|zIaIHRW*zBtV! zU!NQvovwNPSKa^q-ow6Q|9iM|cmF@n&$HvhqZg+~t>*_Xj=w!RJ&V$;b#ip@^!ZU# zlvRt!Lo~l>tz!;ot%)K*P2|=;;G0PFor^fF?)Vi&O|v%>z{N zW!ZSzRwMHyXwo5m3|;Q%zjKp51^>6_@PCi`{fBq-|8xA9mZm#y=#KwW_g^pupJI*` z_aD7|zUcQKZSOwZ?LT_>2=4#(_Rbyu_gQ`p^Z8AYUS3r}IPL}j`2QD88Tbqq!RSV) zr6=i!bh3!20lczkQeUuP;MFuiyOY#d9=tyL?&Zm8aFI@vsMR_^^)8NF2Ed&q#RpVP z|E_hCOwy7EA-!fckvirwUliknJ{hGM>QIpzKuZ>ClTpbH|K^M8cP(Iz(u;H~G^VJ7 znkU69tx$E28oQKK>sP{{e37G(2sK=={7H(P$Rr8lB-Q@!U`?!Iw^v4X1F@truwuas zFa@ocamtpXc$9y@uLS&lC-j_IUZvxtCzZh^Y5mQKvx&1Rm~}jj(-|;{&5MCa4WP)y z%tolXr!~reK?dH)#t$s5hjhNrGmd4h7ON<8~ZUfdIn!* z@hl;DV>=VaVB8zrK`=@XOUPaV(gA#v07A$qV9HruB>_XDLdAQLqS{v217PE&R8|Tc z3d(shMjX;(kQt>wB+3|_%2KZM?7QRB;PmCUXFnXA90l;+Et?aPzjwGM(;2PbF8hp(RY;fC~YhX6cS;IrQETBom$4v*nCfX5MR=iubWo*4A>==;~u z3cd`U9y~wz6YMTr1r<1$!`CNA&vDfNiqqFmPS1|dUY{KWe|q`yDFOTR=;SZ(ww?YV zc=qy?0QUOy2p016;Ou~=hA{wK@ICzg0q*$4+0n_#>sM#TFJE-wlz#xoz$y=* z?^A;C%NMv?#Fe9$CqLq_2nRZWUhuujLi`IYvr^fq9RZtw0s>|>n3&h~@d zJNfUk{G{1_ckj`i|Ho(fxfg7GwS^82@B-`yi|S(QKk$=QyWMWxLaEnM{v`V? zlDWur0=f72;v$`<%)Ai_$4@UV+sCQlOJv=4LQ?BOY;_Um|^2nz+ZSKcQct}3GK z5O+8nUMx@u8xDhXMjU=TD)Z^0N{0M*OMJ{1gF8hvzg*ebfDA!Ev=`EWuN8kI+6e_% zt=0GV`Ds#_&9sBB?4Uj{ukY~tAq(%KulD|x-A>^X67vA!z#3IO{mB`KV9uWhnQXUu zz|!e!{$0XA^jQ$xlO1yqHQD!r#H@TahvOOnnp8KfR_h)hRrW5q*@91j+ZTxTP0)`X zpbWsGzgQcOjH3X@_VGrs>FI?y$mlOeC#T0RU%c7hIfpUAelK{?Wto|_C0Yqoqkmyo z5=kSe(BwrMGs?qsM*+D9CP&d|LaI^jSk6EW9#+Z6szp6Oltcv%xmwc{VVO)XdQ$g^ zAHy=n1-duWXM?k1k#x1751Xqu+P73EjI0Bp*c{H1Dvs>-s(CVn@kBdVT2d6ImZ)hk z0=M2mOLfTSAbMME^>_s3`Kn z9i$hq;&UQL!@&?jtPXXQN%*s~y zj6bTQY-Azc5P+0krdf;|T-A835n&v=(;e&oPtE_CaWJ3U|Kq{lBj*3NcR)_q#r%&u z+jssSzXAR)30@t&3U>eFVGv4n)AjW=-~dYXq*|IJAMVeSd5Qno+J=_*fef7_%%e^7 z%XG{{x*r86$qYSa+tB4+o8Qavq9CnoNUAgB3wuF^3jG&P0~vbud!a(wiGs_tLM~yJ zR`kg(e^SMl!8ZayAJZ3mQ7~VWSENR~nWw?m{O8sd#_-^$Y-pyo529eSn9WI_)( z5amDk?e6}6jvqu>l3WhR)I{PMAoL_H=hOJ6ZXPQQS&DH-vbW@{-*TAgi)c}3))^T2 zDk(A$3*gh1hwoN087{`xAYxR!N~Wm0mCb4G-@^Po{*{=+XK7h28KO+l9nBoz6h2wf z;X0jMqB+UzauQF{{1m9&*gw^JVuaJRNFwHQ+3{Zphsq=UX_5gd*82cRiv&d34+daP zlFQ`d>yu|E;tQ)6QgqqyJNSKXd#^{oK*v7NVck zUb_A)ggb{s)mx=_icr2}} za^QPtNkW4#jmDy+9J@f;K#CG-N|Q)oa~QVq;|cUzKV-WpvPZ*_3j#fGqel$f&zqdts`RCXl@Ddys}nM9KSgi01YZpP*ukHJOdu`APhC(Gbk3Hl5kHe<;yarqboxLucW_)JB9q*7{8|e`4CSRxCNju ztk9qj!fs9RgO|pm`H}r!AoPy-#vI}+HSLZlm zcL#$J3EDqx|J;s(^l2a`WA0N&oAu>Y*=wb}Cgw65fvDD!C#kcQFy0M_~0@vLOs_Puitw`w>la~z= z#Sy(J=nS;q60wZ?NQC#_qUQ;#z1{}EE-l0hpuXpe#8+Onz~N#QpBX-99WcWp06`e( z2ZI8UB7^t+Lo&VTIiaLL5U%n`Nq`xVonV@vUEW;d#UdN;zttDoS%)~i`dW;`kqhDx zbK+Ft?!a6r5<$z% zQ83mR-jVD8T$*Stf?JUvi41OmBS;0$E@1N&uqR)szSK=ar5B7A=v)k6#V~4R9IW(x z#lJTzSC)b6{&pAKE&&~^;M2>zpmDV5*} zU4-CGxlX2rx#b={%4I5?OJiibKA^3cvjiYpNzS_{mIU+Z;u4=?_PZ*9xM;#rXRACo zu53i+=Z3#C4rWqf+^E@fziyq8#DRyj>A3gQ)nXL4=+UuXG@(V{eu(e*7$iDe-Q5Ee%( zheO!^)Cb{02o1t7fDPZn+BE7LL#}98;!seO1`*=ZtW=1>dcE#!=7Lw9H# zw2WHDn2EC*AqU7nGLkLdzO{~D`P`StRJ?twuU?F%!HQ!J1Jpld7wM%i9_ED#D}?nb z7NIcijpP^LF5F=78jCMpsLDHOz0?37h!EZp3NEToh>#zQFbf%S|rM^E* zRhgs%XH!MS2Vw11F}_^3g!YSEh8*RKj3Rr24!k50ycnHGy%}G@bQuQw0c_tTz{qvG z#>#mBQcoe}S@%?pTfhrlah5foLea}q@gHX-Q!%mpBc0da-o1Mopv*meNRw+;kYZ@j z4Rik-*kt6&DoyVBJCp=^247wY2_{xA6k`k#?IJDTF$+c-I+7_Im0xM`O6KVjSCDz6 zs{M5|qiv}Oc~o4(Sn($yBi4$=?7*;+5XFi)a+M$8%k)us1I7~y)s zcAZnFuiOjpRCt!i_q7Qm)I>Ji8= z+K>&KSrh}NCV18Xi~(7Z(6e~(xxv2ns70Zxs zaV>BIWeyK@hdF>a7=ai##%5dbbovLj=8_h9I<=s}CLZKO72d zl`e*1r(?5B5|V#>^$oPSdK`V-T?d}><}gGxuq@^Lfu&X>e2cX^rHMqSdp5FoFf}oZ zGxo3()WM)XUt)wwk@C6bmf6F*V9+(8X~f&!E~P>eP`=ITa$EOE2ww_&woZ@?%zODx zn^g6;oNE}SO!4UeR++a*Idy@Al1>S)M@W+j{y~WpMoNImVm7;xNB2wB2&>+HLw>TK ze`6J24+8D*B8Ztw)48FAcV8Q07?j&W9{1rwENr0W-{u88fuy#T?J45Tya1BZHy$m& zn&wk7Zx|7f^1QhG0DY&?=+5f;EI58@%NsQTh^@ckqFzOSP?NB8ztgQXQV%0Eo#xqP zi0$8O??dNvyR{HY{(_1Wk6_}L;T@Fh1q<@gqTC{Bro z?ot1+vWEl$kH&|O;$j+C9O&oK|Fl}aklU3nK6G+@gTu~$cX}qnLPWpTb4Ks*K=Tgb z7ls8Q$#dZDrMZIJ0MuRdvW8o!aiKZwLm=g^bxO_0qL?vb&ItW5G$Zzv{iS3@?N95B zsV${63uX-$T?#|75Qo@16_Btbr%s`Zol|-p^v^;fFlo@on&RhGTvC{z*3E=<;ka2R z(lTUzWJ*b1?R3nkBq@1*bawEj^Zo0ilOKne(E7!nI_LY&{nSJJpAL}9WnEhy^|C|! z9S1~XP17U`#TQ*Xy4Ev&NNgb;o%w*x zw0+lbS+O1QFi+7y!sFG;(=!vaLS%!DbnvSV$-HEHusIugl;bJ-{t`Lg53FVX+^PqY zQkf;!jaEZk>Avkq<5`rJL(-MGPwy>2OXH2FNt`8g0<` z?}|2*P{eH*5}<;gI{Ya>MLl=jpSwK`i&zGaNUs~^OWxBX!azS;hC1@d(Syujx3MDn z^vBnFWd6hrjdmp;1NTL!#31;|0&|C4f?+Geu!GFumu06Ld}#zf)Psthxa1D42{#9$ zsP#E*;FRb2d@+Y6ZT_ttkP(gX@&xnppPo6LXp7K8g;s?0i93ISFEpNp9jGJV9d>K$ zm69TKX$sN)*{eYpaVhrgQ?yxtSQF{4<;>ve>JazZ0L@hXgoYDblO*K^!S~biCM;PU zyzb(W^c8WC2_Fd|fa!MvW7OpfQu|UpBF-U65Lm~r0P8fywTi>6;U*F<QVheHe^+3uTwy<-9s3&u11FNp!=V1Bu{VE?A*Aq?%@pF4(|5v}jlM9aR9$`Z3KUy{H3kGe4bJ!m zY`_>&iJ(G4Idt!DxKJA!Jp&lObji-hzMi#i8arFdgO%0_l0c>9SJD~(E7R*;d(+!N z6qp&+a&$MH?2Y~$=YUm|W)w8@0i^__YAXL|!wf3w;20z43*-j{QlsT^Tr6gz(sB&t zXpKnsf;(M0X~Ct=R*^Xl!y(zw>Wcc`lBKCix)*VnpH`Of?s=P(ku+XZIcAMQ=fRsm z7PDZBv`l-HiLeX#bT64sGLRe0DPylu`$L?tm{%Q6V);s8cHD~dVX7hEu1E(OaCl^ZRS))6N}nj|7(**yl4C+z@ez?{ESG+hW#t$d zNKcCFQFdv$KL82&!0r=pmy(Qlbc!%j2w;ZY3*!u#^o<}(;Q&x~k{>1GSY+G1Q4vYW z$N4lJr|6ki3WowQz$LDHOKqkERC}j=$Mw}Rc3?S)P)tjY0&z7|7nyVe!3Vi#t_c-` z*#uRX9BYZqX=bnT`S`+fF$nkc7WCc_Nl?>ViEtM71=Qm)wnXr`;1@#TPdlcMDXkw) zm%~XhV7MkixK=NR7@I~fTe1Mmts5~LISJyD|E)QRPse@w23*cb>~FZbPs%=6L$AR; zEGw7YUdC|v*x^RJ^wiV-H^tAU%HqEmPnQjRYkXb0+E0VG%cj^6e;bGL_H1lj!)HT# zV<3N{?gqF^b{_5tdMy94e5xcbVqpGq&58oA)K<7S>s487`0{wR>E9syUu}>7G4`k3 znsAr!|IOWQ8XRscf0nu`a}yZd7DTslxw%JWIf5hnZePUJaik;jJ@+LStMn0)VW(0a zHfJlj=qC2ocE;5fV;BMcMJCozK}!!>!T%VE3S^*y=ru9eci?iAS;*$>y(;{T_#U-8 zb6=Lu{yS#7xugPFSXCYtwJ$5CDiNs}wCPo|*E7+KOuJSV!lRpe!SWxq_b^O56>;_DsdeIZM@I~E!L$y_ev8I( ztfzdHUt>*_8+l&WB7%sH3Pb+2%xoSwz#N4Vj2rEcQ5a;eu?XXr$gIR)!{Sdu`G6dH zC18c1UIcH>yKYm2JBEQMltA?ZI$(QIqU#BF=EW#FK)vph7$LL)T3ur9Pl*RzmVeNi zLOKg2MX~DyDgi#k>6EUByI<3o*dT9+eGbIGX6ha5P!-J5k5O7B#k=IDWK*1h8eK#* z4cg7%MHs<$Yvbx72(dhrF7k~@gM2$xghBcJETdYg1GbiJ-t^Dk$QyND_XhDgrFdWk zFDxdk4C$}Bhsqj$Co*{z0fv`}fZ)&(Tre5EgaLu;;gCIErGE<$R}A+|MWn5TwtnsW zk5o$M*6ANtQ@Z5B{57{W*+6TdDWj1*W_3dY|> z#Y})A=MgawvmES7z>;xGgWy3%KBp)?!NOq;) zCsJsjMWYmC%na3yf>x2wX&9?=aOnq=Hc@FoAXh*eU%h9Iy^pj zHvE40=O134JUvCv&W=&F4U-u3}S72wSOpnNzQjq8Cw4Vcu?n>7+W?HhLBNt40QA!3A6R*%{5-WsJh;0TgBoB^cJrVK>hmQ$8ll5QvA7w4(Mpa?5X6=~*JVF!DrB%h`LHV2WU z`a?kf1RWqR9lKv=i@WZ3#2A)CU0%G43t~pC+AEY|BVoiuK>>dum5hj;=Hw>qiY`uh zrYM;(Wtl?aGdLsB?qWfr`(>8P6pU;Im9=W&QAo(69MiUONL%E3xDpU(4SJ{KCHW$` zMnvm4VFB3uO=mb1fki`d>FL-Rg42&3UngXEs5!cog#0IZsiDXoizh_5EdAVFOPyj| z2bnf(tur^zjpL9ofF`g@xKK!q2zcjcAk0xrYhZZ+8?akxxZX@?;FBKzR;kTcWLk1l zX3F%PXp9x=JSj7()%i9f^HEr|%gybl>U(No+lU}l?S^WAfd&bQvGpclebX2fOZzpJ zfq&QGjqhNYFVOpv0Xe%YbZs}Q&MtFLHkqYA7TgSO4k|FYCW!}(

>(X#)9<>N#a0|>B^UfsOB)4+*Kj?QL z#q4o1l|agNZI^-@;}Xxp`Bqa(lc)liieyT~fmDfX)HmgvXpSmA<4Fs;CW*RAsY#9n zR)0;Ha03PawW0>MH>7XH_GBv`G-1Q$KsJ&<{~^E>LjsL9Yo5_P^*(SyO`(Dng8)S% z@+PKO>v%iv0d#u7ivDhoNZ&@8u~3|!RubcmF-?F(4snnOf}TkGAcin8OOhWvUl;|? z*V*z?a#cH`+R~jjwgw9e&yh&T?1%vdoe-NyY>G-{3e*@YovFA|lb2`I%nRd8^~%g3 zBBJxC#T}|HLz%YR&alY~n_%SAOuCxTD=M^efG#tvVT__8i-P#t;$5K&2)L9RkGD*X zYYc5JOALm2Q2411nR64F4B<%Wu0``3I}{b`iks*|!NES&JO(F3#w;A-j2L~<4Sqk6 zl8IH}ysoSB!?d>e0nA0A$!>r2XnR*PFRM{)RlDaM;`iTW@I1Mj)_EzlP|)yb{=uYO z(lsxb6?u>IlHjLmaAE}Yng?toB{_g)h8!6)>|+=#%6IA9SfAvK&D6ifZ5GTX0Co$Z zE1iIpFBV)8jQrrY+M5NCNn9Hq(YEmPk#C(5>0z-3M!c!{4W2bKP?eJkl=VY0eaaA^ zH5{VxrG}19nz|9Odjbugd$Q?7t=e05TS5Lwe!i5HptoZvnV5s|Dpsi4L!$TgLBz-jVVe2rdkJuiWG7MY?z3A zU&Tr#{3nzk5;-IkN43mLcQanHF?cHh?aC^x7H;kz!{G)~r%@UR;mW9v6w~#h8KPp3 zzB1?B2^htWPJ1P1{7WlltE${TgYUeTEIFG-tye zrEAVX4B7WXa8Jv}QCK|HS_Rfi2G%f5^T}uAcB`eJW9O|{bG`DIgxf7#Jz^+iN;L{` z>Cv<4o4n36uQjc*v%5kiJgB)gT$f#TkcL+rNn3i6j$=ySrk;3m+y!AHby7At;sqvE zHKRPOhq#9z?0QkmhhFvT*4?+*d!&teV?G_7-^{y&=U0>a7G5hKYhZ#(G-;8tp7msQ zmk&Y6gkn}`gNeP}^FriAH~bCM+e-@l0&YP*o8HI-Iab9Bq4(#IVoCyQxz1qJzD(3- zk{%Ym(RR>d1--4VuSq_l76s?Y#vB%9Eu%Jy@uf@&C>|i|=5nGze0$_O%TB6OBWIh# z%7Lr{C=i;T66gohcs82E0kS6hD0n2ZH~sU7(pHps5kZjcbbEpLqMilR98q}85>Ll~ zbbP%Uh5gyM>}gTJa-h)}H40(2Q95ZA)WLz&Xgxs*Y@)I_n^NKwSPa8`AJs3SvVxOV zg%A?3-;u7CGI90=h0eXY!P7(jKTthk_;2K+$@PbY2KL-~G$Rv30SzdzcfHLLe%dZ! zE#RWAE3S@Ikm%<;&KDVF1Cc6gimROg$+w(h`@C5WwWLViMm*gz51ad7>+Jc z;koSBeY1UTD|$+xAY}!VqKHt+O2VM?x9r{$J)2Io6SRM#e}8W8V;B7MvcLtv2Lb;6 zGkq-kaj|jwg1h}K`&-s=oR;B7z69K1;Lueu#lYF{WiilPhL~VrGc4V}t8jOrEI!uN zOuYAZiJp9ITMS5}IE*ynNLrg;un|B?w3*7QEp*CAutn8!zKd$a12Sg<-yH}m4W@0L zrNYptN;-5(ZDez@0-h1NmI>Txne_~4RhATRGaH7|4)ijOlQEvQ4!aTyis#xw9Wh-a zGg2QP5cc^9wt};lPhaj6LC1V`bCuYI=QoX0Nl+{@scTA0WiL&wq}9><*LS2nUJRyTyxA}Uc^PpF;=G4K*KFzcZ!}_Ux5MYp*)@>Kv2AJ3+)J`%ei{lMBNtd3;Z#es8Cc8~nP3g(3m3PIkG^{hJy%gLY%9m^l<|wfGx&;Kms3}JUzmC&V`1obF);dRu z38D-N^L5aP=pzF@_+i@wMb7#r?rbfjt^?+|zlO=%T(C_>Oxp!O>g(^cR%1&oiJl^H z^2|H(82A<|QYWG`%-SY`+p#cs5Ew$Y_Iv%i# zT&)ejR=60dXIgmfOuCz$fWr@p(4MP!{B9qopK%Q*$|;*G7i?V(W`q@=3sq$*YMEN$ zPASGE*DmyBCuta-7YqlBJ7_7!>Sn-ADBZf@DtAxjO~C3S7hZdI#H<_8R`#2sJgDs8 zr7YE6$>JWfA1<3|ufjEl>Z*koI2pbOTsw(rh1wV}TOBb=xN^wSQDVAYgMt!wC1^=G zfcfyR6QTc>aqWCeX03A#{YXH+jN~F)+U$yFEc{?$Byq@?PgNHyxFrL%t^Ow4AtjNpIJ49 zTUIG&L0?EspcoS84M9>QnYEg}ruIbhW7o8@`qO+tp((=a8Wk(!cVQP7jYm+RQbkqb zDyT+Jzz-gNw`+YTE#qG6Dy&R+Y~4o$xUUi5zC?igCYDlk1x>%S)~=2(5m;K+ZSwN) zC6@+Zxmf@{^V1>Dw0*8$8?vtF3G*Q&Mi8A80>+M!CrV9|UIew7w3pgSr0?vvRt8CW z_*e&jINj72cR&9=KWoMR$VcgxAwbLHf42Af{XHlCXLon+!Cm~%Zz=xAU@<;>*v}$M z(F8r5V#Fdmt}@o=Ixg^0D%XhhF*Qc3Lv1`^7*dn(GkLm^7(U$(ljqmvf;m~B@K&FEcec8P{H0?p7eHSn@f@xE5cvG_G_Bba~qsvi=r-T zCgw##>exS!yH^2Rvvn>*$GJ!rC9Snk#@mH;u$b;cpjVZJ$3HekiL|8Q5&{qV^g>omr>H2QTa=lTlYn zw6BW%;|)nVi;SvENW%lNlgf8pjw{MU0DhoOXqL=IB8o?hrgY*gW~La99@hiXR7U%+ zTG~QQmAWfTa4S(=o159+0jS;$TuZr3oLuq!rJ0RTE2}6fdPEUqAH~hZNF6D>{g9|^ z04N;G3KV+Ka5(Hr7f3X($`leb;EhTgW{FcPBq`f`JnVGWOQcc58t-f_R!9w!@+sG7 z)RkR~9muD0*nni6FH66AhslZzCt!`I8#K`K;iwT(aK}ymtMdQM_1rcCzzY6ZV66 zAs)y~kn9jdj!S|q7mq^5<(K36ycEg{ms9rz>CrMNx~Ecz1z6$NjH4oNq=7mf!!K z?MJ&0SpI*|fADYz@Bf3nhY#=W|3CWvpC<8an%IJHaBMi8X~zxr{U}?5jelA#zdivi z7)qf)Hs(b^Ntn5O1t$S)wO$r7wbT#EXuq|w+Cg+MTIs%?4z1Qn;C$8SFs<*<19EFn%sxWi4 zlcY80B9o={nku7XOS)}Pa0wS9mvSH4`!n^IE8M5jsi=b&no=#7avYmk`;YX#F-Si-xZ_8a@$z(sxw zZxAS#C@i&ObGK=YQkB7DVf_)22|)#Sicn#h1LcAl96PPG9tD9flU1lFW0i#jJ|+f9 zr)fb+9(}aOvGknAuSMt{IuXVkxMMgTaw0|P)!3uxoqboa@gppfays=`Fr}TbDnn?lEt(_t)p-|7g1$}l}m+y#|>nPxNx!Apbef64`Y()+qnYNOs-+Xc`XQW+?tm#0Sd3uKa{(SpJCxc{O)@GA5#5nyz*wT3e#X=oupxqXh=`6^qw7~Nz-*1lk8bYQNLV2CVrINQpqwjsf5XD_dn#T8AyVuJE7!zexQ$`DaO}=}MN{bi<W&05Gq7{}wQ#57ClXU>|JcsnDihLa#w@iYm9m`Ez#?Tzq$ns0?g|~ z*zA&zX$dEUV9IjJN|&IG^+HD1XWRm}By!!PD zopKNpTd)x69{2Ug_7F z<0mb0X>y(_={SFtU==W+->7$?kEE-#l)ap=KH=4WEt9}`+;OfwD!xDKRr5ZyBSQg_e2_;!PH%CO5*ISmg79{I4u|wl=%PRxjn1 z>kdAF#V}j0^U7;t-PCM8s$%o|n~!NJlvI#2p|@&1l;pvE#d-?HZaA78sWycBUYTiB zr6$4hv#-&^1_yl{z(;j!D`?d!UL@rZBNw#(6F*SMBWb&#GodGebXEiudb4NlD4n2CiH?6ysl-kw3QWWDFOyrnUt-!U4L2!yuPXp zK*aJjQb^YmGuolaW}YW&oGvcv%_rEjCvrn1ntA+Kr#ZkB$LdFr4H&f}S8c5g8$XsA zl0B7tmTg}a$_v-OMjR(EN~Uu&P{vFwxnCD*MR>2s6euY4`s@OoEG@!{ z{G{tYnK<;Km8;S0P@SlG%nU!IxHwOLo&IGWsz$&hR7SKC!c%q&1z{Q-SW2XJLMz1D~_lRAe8|_ zBB1E#15|CTtkLheN3$g_<55Q(f zNlVm*!@O;nZ)&t9K7av)Dbth+r8ha1ql3%gE9l|Pu;ZA=l&>j-ci=rAF43@Zu< zS*LyY-Rl>B9-bcm-y=^tRxYv$#K`n->qq_j{b;ALpwK;YOiWqM2H}a$tpr0nq^3s0 z0Z!9;Wm-K29!f!Ji0_2}Aey{X-&U)oEU&ZtvPdt0HJz4Rk@=NL{>XuZ-L50KP71Sz`BeHiGeqmZFtG-w@C($7S``#@~hCv5F*cUIbmlc1-cfeSt&HXMdH{jKV^)g z9k16CMs#01W24rz*=CFFNHe5n5h^Vq^~mh?rE6q0F6AUGvB|_r?%>rMX~TPSY?xze z1>^?Fdi6$>%9lHEE@;lkO5Oydvz43a38SEl>clb;2!)c;gS4I7uzDN3#@Z&#JJA5J zMqqkUTWO$VAQQW89V<-p7?3r-f`{nB@AW9OnyE;IHDFl!fRcNgMyS%M$d$j4V!O?DX=#QSV21zb(D2M zhlJcwa1hof!xw2`=$X2P-N~+f2Hl3MxDsYc98-<9dW!;v#;yj=eQ|0BZoFw3FZi3< zud^w4&vLxH7>eb~n85@y)-1glKO|-pE~SkXUbU(w7ZCP56NT?m1AEzaM^JQiL{Zx? zz;DKfT2ZaETIpD!idmW>u*kblU9l3^#+pMVb+Zq}i9nuAx~kCeNzl=&=$lz`NYOaMhdy1%F&;w+s`V>O9| zlbBdgK={onQNTXHE~ARPL+2aAP;L4vxd{I|IWKZlSPtXM%YtC6v8g9E>w^=mPIh6F zbOzTA|KR5P!iGjX%wLB?-f2+Yz%~EKyrGb|xJD}85*idf)1(1AP?QDF5 zOs2teo0QaDyH9dTjSC(}NDgG5xjjy1B zS~Hufk>fK$R?cbpAP`TR<<_u*rx&gzm;u1L^@GQOU=L9kxVZSGaNU??TX_Hqy8aWm zhi1fa64cdYLFX_1XdCkt#ycGpuK@NKm@>VNZ%Q%09S6k9;WGMfBX@(YlqMNnW>-1& zBC<{7XAxsA9>7eiLKx}}Qt5$7s&APY`CbrGo!Dzk)u^HrC>=xr;);>_FA3Vl65BQM zB14Te5mNESGz4NOZ@mdSZ6ln0IYlQjQ1cd)rpRq8!h8Xie&2|0V-j7$CMt}OhzK4EG@JTj95X=={hqb z{igQ&{yXc$*z1LMCU$k7LIw=Tz^Z^@&#Ls|##zPahF)Y!!Vbi&?!zkmePz0%(sK53 zef-U#LtWHQ6z0IF1!J|eO7j4}#n=W8YY@feB@IvoMEp1`T#VA9=C=`q1ZU62x?F>V z-id34p|(fhJn@XEmD5r1T_RGdilRYWG@G73wteH|nklmO%H_YvJ!#9?uSq&}eMC`L zk2qXhdoA(>ZwnzQ6{Yaf8tR-(hUr9C^bi%0L?ysYB_T0n^01PpRuRMoUE`vr;M1~yFvWkyLJ|j#ZSeY`$g6g8c4NuxLYj0%A zs}GYGO>pl+WlMd-UUGQY=Yu!+-Bx}f*1QGa(L#ya6QE$2ib!O$HnGKsT}NSpI-PWF zNc^+x+4XlAR{HY&!J0#qC?|h-6LI8SBK!dmv>jw<+bgBWB6{g$2M%yXfEcd7m+e^h< zcPi^_WQiGL814D%DY2cZkX?&{;>AcXGHh-9e(U=^J}kw3Qg2cng79Jv`AF(kt7+f~G2tCq{@}iSg+a zDs8Z323yk$F7p5*GcmgZvjcQ58WIT8cbo3eHe1;PnjsJ}yuloPwg38x@%XlQhg=eN z;wji>`pVa*@CH{nVKUGY38P3KUk@K@?AutNPgPKC+W2588CkYkLLynFQt6D#D-Oh$ zHfb?#KoSL-AeW4|V2f@>f8z!xmjUem@P$A3mlu2 zEfgQU$i~woE-2gK^;J$u>_v?2Xi72bSvRta9bvIo+bAFAxCurJqV#3r^r=-S8r>NA zL5bO@MaZjEA5MvKk?>LUHRXG0@}dkH)<&J>%!qKpfh=Ysa?p^oxG>E89hZQ)Ofgt~ zQLZjMZZd%)h*IQYHEJYC50Pc1yQNr!vI@X@F;^9g=Y}zG{!XTOH`cyvSQE)GF-j84 zgcroHx%k_b?lEk$H3cs^ubJ&tde0U*RTXv?vol2u&h0XbEFh85mn;EN;Vn?sE(xv} z#$2O~=YVUYN>vj83i*^@G&a>>m|(akrnN*>GU}j(wnqw!r4ef@upSY>V%of9j}HOi z@8^K$AQKbeBz>w%Y>+EQ(`4+W6fs0)vSo>j-tUkc z;em)lkRQWpDYl>OlvPfK{`Y0Qq_;6U%)fL;kwOlwg|y7OUV0qbv)ejo;!c@%Ut@f!0FAU&{o2QD9MmfxEV46 z^VfroIpimVPHhbv!l%~15kiu()5P}8X;~QqwpfK&S2o$s;G~ssbU;#{q~=l*>^Wpl!aUp6Lhc zT}=sM`p{w}el;+A7hC_Z9o8gF^ZjI$jB=u{coh{!?9r+fwDK!g@^Q` ztZ<*9!@-SZyb<-ZQ(f&(8UWQ$l!_y@UEG2Yt#Z&G4?<>-gWFH(HiZ(E$D#BaGF6?b z5@ssNQN7L;yp|ZhJY;r2&N3_Qq}oZmTW6vK{Tb-UPRGpWGw{_gELVJx7;itgA$-hj zvs+q8R^GOtq23++(@lF(T*WxImSsrsv9{kgl@G=-z4%4DLcpx!$*BQotLmls`Y{WY zL?S5q9rH?H<_U#THR9m2gYWyns+L;6trEud8h@u%K0l^qTXDW1%}o=sw(qY(F1rf4 zz?bnAJX}dOvD5UKOHK(B;EpEYx<}<c;xjS!oS)A zS|fvNz`$}_u%?H0?^=zw&5ER6=f16R;Tn;nRcGzx7WNw|x_YpO9mqKe=cRW{qXPX5yXQX7fS~gx!1A1(-rw+#=SH1cTr0gr%n8oESbKo{@07Z$)6P4a_w_a%*5TXVY2Y-$A8@%y(Ow1w801>cwJe zl5!z)u&QLDxQWxN{Q6r&)hLQoHW9^_6MEE=;H@+(`RSRJb|x2${Ouk-GaKJ+v7AmR zw>Y-3Sd=$YpoLL6TV0*esQ+Dp|KCFXefi~ zaQiO)_cv7kPeqI=m8=W|_$|c&|H?V-RWPXv8tw%|?$OupMP40YhQfwmV<#z$mGeZb zp5ribJ$#X1uE@_DP3Sq`);*DQN+$?W0lI8nP@xSXrecfKPu~j%96NF_YKer$l%OjP z-lZ8iK5+7{3#`|sYV2V$O{_&WnQ-36B7x3!93myL#W_o!Q(G6PG#V!ui`jYNGRd%h zq!x~o>Tx>aETOedlUy(S<^2uhFDwVnZ*oR3vXETZi=py_fo?-}qQ67MD zcZ+4j!sI9?G5vYxITxAhu@{^?KKh!XCpa2Z*iO*d%ECP5plqX9aGVKy5#?&uI|@V+ zWH^YVlFp!dzr0rp5wVt{(%JEx#GbIjUds&q*f)ovZ%$bIvM(I`5ScJbqd4C!9Xt^# z#O;c}S8Gmr#AfKCM4ftwl#q3)Xo?D)=wTo<9xtykLaR~ORrW6`CCK%ucM0?**_B#W zfKc*rj!K5%nzx{a`p#V&buNl`WxaVBr{jOVtf zEWVfXz1coLCvjZ-**BEf5mQlMA+Z<#UWPUF@xTBOpZ zyTG64_^1IX7`~VGs(mAYdy)(@tQ;uB6=9-4>QRQX8#xFzF~y}ogiVkFb9|LfCq<%5 zoqkX413PfZ(5e8{2(d*Zdv+a2(&ud1Ad*Pdl`e3h`F;&}%zFN+TihNEbvb<3XGfDm`;|N{-b$q4lAB!8#G@Bm59Rn&TQUKKaS`hn?Y)xACtBm0Sa-4heQR^p zz{?n{WDAU^<5sM}v5pI+Zap*8CSG7cQ{mD1e#^2c2rq8QOt^J49EM^|W+j72O6Wj@J6%D*FZXu_Si&QOMWgn=G_xG-rLbgLlMkZOxa zq)}?uV!-7Q9SC~5CNqk`VRGRU@=xcB4=31&OVYC|EmeYrUXY|jpfK15Njn#N^23c{ zk2IAN3s<}wub&@?T$4Qfof6S`=&iSnk7LJ}zf&v5G8FkOWkno9#qUE6t(M}6 zoMD|D2AdDvb8|beW4@lyifY!g*CwK40l=wKQDvfBaOwCI9yd%QAPk}z-u7DTYF7*e ztOA-#bzvV7|D|fo%ZL?s%9h{<7;dWro}2G}*L;^kF{FvuD_*8`rf8-qI+9n!Ox38& zCnhHpFepo_OhFz*r9fv34o&&03`aNojEXya6kSI9R<(Oogo(3wi>Tu^XXBQ!|GRCQ z4hbO?-bInEdnht=^S@)+EwTxRLC6S9=oU=q2;_-rhHQbD$ntL2f;Zt5y9t%a9GDYS zf|=LOII3tK7ZpDjgv;HQrQDy_Zi$iG&Bz>JOzFuM@Fi?(6w5+n0@=Ad7gi28)5S5G zUkVRKoi_!dneyR?O_ zyrpId)u3t&BTFcso4C53GviUQ@H;Xtu;nkyE+NGQy3qcfD!$v91bHkD<{QQw^{elYSbMnhAg>iy;bscLfR^AZItAs1xVy%sM zTycK2I1ssL1C>R37%*|5rG?t%A59#Uj<+{tpQath`i!Gw*<1DPyxc9J2S`ShUOU5j*`L!D2#-L8?m>2s4oD}4p$3c$c7v{ zVC&htJ^}YI&N%$CGC{3jCkhj(;2fssQcB51vBr2dN-r14z>bpYIx%WX7-1s{ZCF>$ z^q_1RmEh-~w^``2-u=E)`T2@#{BZ=pVPQp6`pBuUmlb#v>LR*d8 zf=4wAhYiI!rtCB06{MpZWu2qEtR!0k>TfaX_n4a%MIT1MRKtp9>HnZ38dag1bbm>H zXTpP}IlG&4bo&s58?wJ~X@n_P*XcMB8Te(qhf_xbXaNx#pW4QuSjv~tUYtm7ZZ|&n zt9lxUt+D=?5(lCfLFk$okmx>DP~qV5FWb^Q&^RQpTixs@aLJ z>TpO)Fo}tOZ2JjI@Ih*Ht2W7lDk9o*z}Z_7J?8?nK3-Eh@mr(Aw%engk^a^>$elaj zONTB|v24mdu6nyHzv@}%M$}hSw8P*J?TQfV^C61&z{CNVm)1JFMa#QRAvO@vVGP0Y7A4n-+c4Pc~D2DCWTz=bBFc|4OS*Rr!8>&HLa@_;S343X#Sn2I*6%gy6=v{X?|tND-|wcnPG_|k@j_2 z6-xR*2R+}E?_!pS#cE#ycHvjP0TX;hXA6q+6yb+P`la9s za2$EK5W`4{i4Mn=d1A`#QXVY$!qb2Upp zrpUTaWHv?e4O9=}YDaaUMkXmCMnN?LsU7H&Y*sT#2tWP$`05f2MfrKH()Kr#`E0EC zqI;4P;##=5t|u>QqoCe#$)L0Ns z%}KgTBiMYfaPoW+R(1A+WdS&%kIRROA(e9h~h5&ZYf z{`$iNTfxpbirrDv@otZ-B{;Ng8IgfIi^_jjQE?=!45CD(xJ_umDmS^7C^Ly6C{U?# z%I~n=Mux?)I!-kI+WZW2#SW`{i2v4Z33Z56Y6us6vhabDv}t&loU2MIr-H~f8ZJ#e zR-4t>X!8*G4w%WCgiFgLjc0i_u@uQzC3|Y5kad6=!4ZXe1&&^lsgVBKO+ILNmXHJv zQ%*o+wX!f_zX>KXYGV;ptiPI8?9>PA6`4SRRAR1rQ863^tU6!m2b+;jNgG8NnB=Mg zG((A=?0&GeAM2JzZ@UIT_$EhD2!S&de!az2HZ8g^_%L}RQzS&0M& zg#-f`=f{*0E>Qtwf>ZGj`AMp=lY7xmnU_CGIC?`kvD|S;cU=RlPSRJMM036rIm!L` zyUx;8bUUpLcP8MpbaPAy8kh-vrag1}&iNAMlJ3@_&>z6?y`a4fOTU@Y z;wo6jQKc0IGHgs5?Gu|!#5<%*buuWsOyVA*wQvoN!l~8IR`H=5l*mUe( z5C)?>pYD@YqvYzAK@Ss-%(kioUUKpQ}XlNz(fonn3P&y(oyq&@d%h?IOEww@IgmoqleHE7mvUZyD=X4xC(YqSY zrCySf2j)A-vW~pt?y9{B@zz{>J^#!nS$}<4nD+=j^zK54exiJ^UV1iRN`X9X1A1T_ z{sX5+Ny)W3ov6UqGvp67RS`0hzWX2NIU?e=MokeO#v(6eq8M@;t?6!vE8)%6Yc~$X zU4reKH)z1nz}OPoJ0+v2jxa^GLyrp#ci)>xnL2ptm%~8}t=Zu|4fU)5yna2ZC0ro^ zXhndxU^s#EYhLvlV#$ipn$F_)d>CDyNsyGpaLjKSI`5x*i8%M!Z|HR1_{{t*!)He0 z-q*B*T62MB0;?H7*wDi~qaCkR>-)7pg>GvD6cFFKn6QH15%}qCWUfWE>@H!2TTLVM zy&GA&%I2$y%Yiw&wFFw7Z}50%IYH+!Fo>?E5bYtMr8hJbhK52=B$tJTX6mI*DQj1t z2!(&LP)SMyWhY&#(j$-4+OmYT=9jOmXDrL~0Tay0szqv!&A(0r-$Ay?a(gV%xH}ca zQ_w38XTK#JH`oX!F`dohDjlUdf+$DGXs@@HwNFGe>jV9@^_AF>@hw2eJAj5<>(2gT z+kb$eoTJ}kdH+^(kiF-@g9iH#n@jpTJN<_{j~?yr!RI@>yAK|I5j?oF|NPd@Kc39e z?EbHQ{(F0Scjy1xJ%97NU*-HCZTENY&i|j{{80*}+AJtLMpxBrx}p7ldwXwh7w!KK zA3W%9?>+<&?(RI;-n+B^e~zD@zC^V}k^$G$=ELO>HGQ1z;LD#|Eog^Yx%fje%(G#Y z&+*eBfR9JheEg1_gwtvWd}D<%?y3PbktN1EJcDS9f&zL0=6H3*+(O z1O5|MA=cxac$8OIn?v@$)y&Skcl_V7`|qO5#{NIsK<*z>{+}q=F-;JWlh>r30((|L(SX|92m4Ke)U9|CsyVbf9;1;NSlK z;~C#V1#}DffBV7Co&5LPJb$ca1w8a{eOK^R^qcl7_a zc>aFUzYH5zod51#f7kZ^-|hDw-tqsR<;V2om&Yuf`JbhuA}($)(07vbf-~{;DTR4+ zVEghwfFij}OD;?z#zLoXVYYgrp7m3F)x#G$wIsXQFqtuP_amRcIVhbX1Z3IPti(V! zx0}eWBBdn#%9#-=bQ+7_VJPI}Lkt_dq>_{`RQklB>>#oo{3q>#i{Yq6&*P%R92I4c ze=T6p{9Tfn0l+COkUoye`7~9&NoE;T;ZKZ>$>DLwHo%6kK6Z3d8|~t*Q>SjM2@+lq zCflB;(?rCXhPr>tO&ciyCHnE!!j6X_>-4&ATrqVKoFuT3Wi_M?yS4pPs{bnP zb86-ux5r#6Wtm=PoS`|sWP3O-tdxIPYl~VwWVJ7JR3v3S{UDqNKN>DX=%Vleu+7eQ zpz4U@V7PKlU8G_Q3}S-O1(-uByYvPZnB&)wucMB!v#%#Kvq)fFTvd}R# zV_{cw7#r7rwi7Y495j%)70nmrRoJaJi5Bw-z&MoK&`nUHlW>-IClYvDgR+_?pVwpe zaU{U~|CGc&f@7z+c9%?qK9VTi364an_vtjh=JK(sw@8T1+1o3fS&x_xnRZdBDD33e zVvWvQBZ!&3o_|jva!vjZp1oUzey-;K`u*((kEs5~gZ?&1e!Cd|xx4*v_m2Pj96!tI ze^Bx<%rEs1D)K?mCPS5BPkg#qq?4AakkL?XgMvX-nGTU^(hh2+d|#pk?i4q=s@%sR z2CaRTS|fF4n!YvDkv61qu#+vs8E~>i&zE_#am2binB^$dYxJ9P2aKqk31u}P5+Wyf z{rdPR^;g2ct7)8O2ceawiysK`80+h#h=;%@QQwe!R+H?qx*GJiyXHVoLLSc?VrR1< z4tat?EZSlw)T>0=QNxn*$F=(wiDRJu@evSSV- z4$aAX_TH=+()9uKlp~dCJB{F3f5l?BzlO%Rw>*6@!jFwZ-E6!nHP&ByYIrduXFuiU zCn62+FF9jmu-79m7w>dKojF1fmR^u8rqcn(^NF0b6sI-l$YjB!Xeg7avoQgc`#cEE z9b5Z|*M_kgqIs~<=7SyT(X631cshB2?DDxz$7SORBjh=-i>v+n^wL{-`8$T0*5Z?&#LrNUJO2mfBe|9reIUX9v#b@lW3_pNutykYjb8JCD7ZKK7ySHQ9 zPhR3}?XSrSteAKW1jd>klo$~cP^dvL_8DZ$%3jq@D3@o@Y8XIh(PcFmGuH-XnIc^= ze`rjBC86PPW2~S&6Q4nw#GZ54M=12R>*y7B^#Jk)%JuiusGi5>Rb0T)Y9#O=u(1T{ z$sG^Tn6+-dd%;01HTnfVHkca(Z5QJt757bmWq;Z8&UxIUL$xLv!O5v2wg>cZeXxM}bv3^)XQGU{4;Yd}fQjj#}zv@Kqw z^f8tVXw^LbhPdUNl18xSmxbV`y=to2WpQ9J0tR)%?{=EL+*G7f%XktROVX=&vUH-I zTTFDg^$VS#O~@%RwmT5+kJ9MZVDpPuvjJpaz)sANA^MG6yuis$NoY z>VP#TJ@H z$^NNH+~IxuJe3LgtWS-H4?bKmbpm zMN-9jA;i{VHk?5acINLoJwtc;niZReA@v6wFV&kS)34hQoH8j(i4YZvjv_IEn?bg)k!neDMT;Zq(MJ3m2tlL-( z7W`Rtg=(XoBxMp8S?!<*o3wDQ~vcpE;QY6VY1y_nl+{#E}&J=Er= zqI;YKck3~-lOJy+LxjK6v)O=bSX+HKiK~@LmYx6Tnqv}^6{_LIXukVN%Td`GoMqxK z=&~dYo_dBfnf&_CJ*}S$F%yjRyz6er9p@ml$GoNCQID}?y!Djq_gLc6h4v_4*F8a& z;j1U{gu1T#;N4@MNN2=f3p+o=({#ec31x*g)3_`6YFrzx>}o$a7-QMzyf89)c52D* zJ9I)GbEm_F(G2i(nih&Mp$O6x2mplZkM3nOhV->8k*uGNNr1N&?l&znZ@r|HzNg^ zfbL;HZ>I3J^(Cei0ujyVA~Y)xp7a5OQMMd((!PNf*fYZaBqW-l+DG(5=?QMZG&Wi* z8P1&qM;PFLdV%V<<8*w|u(DBq-G*zAxZ5!<-}_R41_7#iNJI!}iNlPGvtw8V=vfQ zCl&9CF}97Re)K{|-i}`ko{w)jdWg>a@y`%BlMU$p3 zySmHnnqBsEm%TN+JkVVpbgaG86R9LhE0;LBTMJTRRJEKFQK!t4oz|P+8#=cAAe{tz zJ?2G2#T9jfHr#{uWAw&08t(cV?$jFY_#5_(h6mK}KfDbew0YO|$LWJw_eb9Dd;acw zweAnS-FN-ncWd1rc)RcTyYJMx_r2Zw{_X&};Jjld4GmQ0N32f~)^4F;M8j#8-?N@V zkadv^jkLOeVK%)nx;?)+{r(w6Ai%#E(jinZ6c0ed)$p=EFwpW2H#WtM&F|laH@cZd zFj^X?|0*vlcmNOuWNp1A2fs6@(WB3~`a62`3+d6V2$JLiaNq{Qgu-O_5g8ptBGA#^ z`ediZq1UVf4reYUNm4+H=p?j!3-&msQMk%)Tn6rFTogUNxFD+;vf4t%q?jD?Sn&dJ>@eZvEVP8F9gRBO)pCcvo5*wZ#gKlpOCt}D@|2g0r$Ki<(V)(; z8>-SF8=_?iQkH3#p@FFR38V^O@FAWmIhbl*tMc*0WC|mziI$I6!E zPH8BZ-7S+=e9-={{3`2|0Wi^5^!B#9R%fjTZ|HwIUQFkeTKri$gKNyn@j?463eK>a zZ{dvU=)s$YzUFAPgQUns9`>@`Gt}dQ_R}H?exR~5ZC8}?ZJqoL^m$-_9>(RNV5AlM zSh^7-PBq^1Cw=|Nm_OM$Uqjy7^%9-q@>m8-#*wR>?~%Gb!X2#cJb!03H;hpwRe+3u zcM3Z}JB+^iV>gQ0J+_B*dL8u}lTlc$8GBd`f%w4)fKKpc8qnOY8xu56-k-ngig9f^ zUc)nf6l@&3-Ox)=&~B*FQBUrm;w@LO3RCUo2G+vcX5QBt8WmVjKpciaSTT1!9{ukJ z`t0%18atm^sv@P@>iRxZ>bo=>=NNRHjYXd5CR(KQcR?sreuAL=v1>|@vAm3A5ArH9 zfhRw()IDaGCrw>QS;Sg@lB~Pd{nRF;rv8U!|HB>m$1eO~3fh{Q*c-5k37p6}2XYH_ zD!t;L>QK~cX4b^siAUqfvX|>nJmctnbrqvbcA;E);8%8k?A7?4B3YCiPW&M*(tN?s zRT+8b5I&S^;fIK++8i-N9Mvzx2oaUlG|E$Rl&9t>Pj}@Xd+^6zoxLd2*?gKTvo;Wg zs2`qj-?Xn4y=^XB32nQ}C=R>@qA})O=mni`#2Au!7nVDNrakVgJ7V7)QAuI-5hVm~ zH_MJW%b^tE)|*8h*X?HBHD`V*Wy0IfEb+x%je|I|ID@57B_@5s?(io5Jz~tmQ%eIQ=Ms?+oyUP}YGo-QsgH;2JZ^V4Uc{46yND;ZTEyX} zUBn?RVv|+KC_`fz=Gbxt^&q&VixH!43KE&t!jCZ?b9Dd?uY<@Q0sNPR|P`)WP z1=o_me|Zk*-M@N(QlRu#kX-gibdUTJp|UddhM zNUie8r&y&pp`G!sE==cHQswZU+n&IY0?D49Wb4+quI_ZiYJpWH$TL>NGml3p1D|&3jlc& ze51c^mJfTBgCulvXmruL!nzl{)gAvV~a|Kml#5m64llJ+yaIoGt66-&&xo8=#{z zvc4MMxNY`pyO2b^XC8j7@s8d2y#53vm>F=$2`E0fp@0StuQ8v=;7tdx;P^!l?x1f- z=lphhz+X*k*Z&ptJ8P(+7(%c#_-pV}n}4CCrtSTptwIIS4BY;?7YI<=Uj#2tbWkB0 zf!pW3K>7j#+_%yRfcrB*8}2J5n%obJeF)O`OKdrQ+HuRtsEWK|T6enaQ9F&tnEdAg zi%L*^bxKJ?f?bcD5mS{s)*`_Tsv+qx}3!-W}_|z_EVsJ=nXG{U<)zEVoGfFCxOX^@p+7-LJ>_ z7%b`VS9pXJc1vRr&7uXE;C}=4-J$$Wh$I^bb^rRR1t(n#l~}vQLB)RGtuUPoRzorV zm7rI1i6`}Gw8z{b=1o{|q-9 zo!)yvQeE5OVp^puf;R32vXz++si)E!pf;_#N{b0r_N;DX;>d88eypX-;_x3U#h*S+ zvl2yf%BU^0SR31Q>RBx5C|0l1Ow9+Kx%wj=bkZ7Xc~`U!75e|%yY}X`aU-6;^(k0+ zZYX(VS}!{{np0ZGc5ZxgaqjG-osOH*ltfEBQzVZMJD&Ewd-nm507*UU%cW_@nn^5? zz+wR`fW>05zd~YE5^LnfXmZ7xkCBy9)z=6Ok{8v_Lp?=$f+&CCl`gS2pDJAvO@iEb zs$x|{N$VJ;b0cLjV9*N{|6xTJ!yD*jT{viI%pob(Wjx9askQ^Z$dY!pdt;NvEokc8cTP6^|#iie7CiKVj8X>6C;XyHgiT zlzOa!(JBO@ZJdXJyXs7_`{+eG7lG0ksc>`DtKmhhPA(*+eEpRtp#4WL^m%!jl2OC$ z>vh~7t(Xa3_t%`nKh{mX5MWI$sp0kbDZCbTJbPL(}pjOSgtvtLLPMS|MY*Y(BSXH>Q zvT&#Q#0gLf6T=sYR`&_y&7ZX&NurF_^m}NPJg7_1JvH9C_%F=Q~Bzsy{VpH!JDZ^vBZTJc}UOijC%$HFGc^_7AS3``GC}ysO6Gd)NC*MyL?awLITMKjz1mrrx zTg&ryqPIzkKLeFoG5B8=;X2;SQ4zyW53Hvq)ww+aRSCUADX<~Nh}YteQ_y(eyk$;& z*NrevWQaCp^UQFT2CA;+G+ahm>c(d2Qgwm4QWn}A!exyARj+-~C9cF!kR>R%2ZqE) zIL3wh0BstWxNt(bH|XC=X7@0QISPnDXK{&vy;iK}4`!r>~7y-A{UN^|r zslIBXDRZsiOg!I9Ny2$KaS(a*K8$bCNjIQLhIY;ZwU2vr?R3E1wv6V1vBcK z3SP9K7jiVAIvNVr&^Ba_R?|4zj*m4=X!D2&%qLPew286AiW;W3$q#$VUZ;7TMPQ764!(xFSmKg=)KZHp-k$6>CG}&$`JfGgrju z-iR4cXXg2m9hRGSzHFZGTirP@H>rr^Ou z+n#yT)NE>PSc_D;ddF7-v@>yF??6zc1#;SjJCC7KUKmt>(<(tb1llzRP_QvREru?I zdZOC8K|#p@(HIq#K+q->;MT!AtNX0HsZN;tB#Oy??|{?~726YG2g9hP;eD2`WiJW1 z6lISAP|I)1=_iDDik?vnd|G}Z(^o(y^4$~Uy#hu$qJWObSQ|0?XOV}y1}dY^l^x@X zkM7P$4F$ij=S;!_pny{>g&4fa*xPQ%dW%@l{w zi5?zRMi)MZ!y)~Bd3d1x?RIWu*08$Qam!U^k(l{e9~y_e1=b>A@;BsU%b&! zHokImi(%%HhQ4{0?*zWA`Z7yB*mt`D^D7f3ODD#A#h=n@;yjJ_Nkt<5EAHXK;1pp^ zTc@z4BZz4Y!(K_v0I7JblNJwHoE_c;3qt@baI|jo!EzZ{wO!zPo+9Tit^TAm6sH#4lg_<6*c+n}DRpRfOd0O^x-(hl z#LZ?j;wHbs4%;1I+;;}1x<_5;4m79~)gi|i9PUklYiEkrtCN&4Kkghqb8`|3q)|CD zR)DpvhJY_cBMP-4=nB{g3CD^DRR=WFVTYRGfEw5o8|ZxPw2v=NkKUi!$M1gp@b=t( z|M#CxFJWr_S3W135px1{vZLf-8bT>SiJYl?UjrGBRw%RsWm7y`$^}ljlm3?o zdS$7xHZtBt;tsob%*t&VV$>%Tq6ja`qxtF{WI{8?i6g0dwzJT&msKuHlmWD3Zzl15 z%!CUmj>^i}uzg0x*^R+%lw0?(NlxKA(O-a2&WI_laYt*Of(ijIYtsKSjV$qN+`%=74&_e zh!9AV6fN3bY6($y0zAA;{P4cQOD+_TVF;=i!w`W9tvB48z%YaSnTzM9L59jav9o}V z59<1kWNrj1^RJl~mx>(F(38LPAy^TCIts%T1ab`=Tl|+FW5akKukisiVqjd4+*ckTuFpo5kj1Pf_tWa1%#3@7ErK|9P&yHwYT+g>&utov1u*A`@ldGgYzLc# zWWOJktlzU$aQ5Q@%s!to?>*l)rdf=~A5fvQe}PQ=CJdoyasPoEapF!LWLBAx#WY)l zA_!z+G1icX#4n`jdK&uKk|8`+z+RBhF#~jxwD2mw59*4L651(#V-dw;GFKFJ!d-ZQ0K~c4R=%WZi<$aE z57bMq>2a|>Rj^o4V#=FkPfS^A)1s!KHTBpS)rh_P_(o$-5un+G&f|oFH4Q$!TQ^{yzf$`mi9Utw=nbCBb`-ld875h@)goXEVK5 zS;WVhFEXuBsD8*GIqUQu@zGPh$=q0n)UsJ zJ_ImjqhE|ouhh9noxeNMcV<@F%{mEe_KWF>GA8J(BF6+O^#v5Wn4Koh^ww|#-f4(U ztZ;i#=c}g-{nfHt-vsp2hRK+%Aff@n$uA0dgh&-#L(o6)+s649J%#bGON$AHiDB}@ zF{m?0{zZsIzee^%8od&gDv;|^UIT37B3N*(-9fC7iDpPK2pvE5xssoi+-{Q120f6!`9-kw@8*4zKP z!^3V**#C#agZ|4G-G29=J9xJLe~AxhcHYvNyQ7hjpL(XTbLS;{Q_l+H`Tlefd&wN< zf|_$rD+=a+p2RQ{FUCul^~u?A1T6{^;)n=7jvnTAe8@V zTqA@LX1wmxXmF}M)rFaGEYUoa2p86pdWvh6w30@QybC(l-_Snj2**g6%$E+@^3#%Q z8as=X2(lp@?fr3~m0JxaiI#Lc4UlEC(O+DN5U^g?*8&0f`kIr0PTpv|diBa!4^n-C z>vM{hT6DusA7H17nKt5P|KxCZ=1s8KNbC=S%Z3`FdL%7#0+$?G-1o`RRd$TEp5 zMHi|~{ipi2Dy|@28QcLxQv z%}~xI_~u6AL&E1ceE)`}x`RRoW3-T6KB*B6gMm@K>4HFVp&4m=$LC7e8!jl~k7&+q zn^DcMuKDV7Y-l2C3EJJ}ex*s_SX#N>Kxb~!gXYe28pX}bq!P*^L6g_Jz#Nb8t_2_daKoDgy}^KR%sAXPZ}H5m|mWzYCG{ND#|kiezVFal{B zZ>{c0Pblf|YhjyzzmM5k~bGzre#_p`L{OkgMx9I3xnX+6bc~DO9#8_?60)fW@c=DaaP&Jtd z7+ng$ZP-tuEE%T`RG>_nPZeT5$`LCf**)AC^=Y)wTwkA^pPybBKfF6Thd$KWf@$2a zu;(_W+?ph+nmV^4QV^}5(A<2eCZcbXnGkqzk}ycb9*_KS%gtcHKy^|x;Yo+c`Qpe3 z?N2VAJ@R=JOzUrI&WdoWz_)d;XW=x%*@m9uVts+;7JPLQP7~uhsq<8O$pTJikPs*& zq`17gwxL&l^rmi*xQ%t{MJ6SVJPm!$fhS3#;ajgSPxgH8)`g+db9YyJ5nmAGkS( z?_K(l+y!>*f{MYXXWhp0mizyD|Ig$9k)D35hsMi;gH_{y0K;DF{|7Jy3~B#A>^+bF zFXI3Ar~NF6_dy-ocY`~F&z{(gjwFCwKb6C{EW(Qe!OV`F=`AQC!apy}(?m|XkZynI z>^4p0uQ2}xDu|@`fSz_}uf)~1wTqhrX`;LVox(15V?3OjNG7=6YCh#eQ<1&yQA5rl^(sNi4m%uIK$K#5)Y|N;7R3Jdk;#; zbU_I$-paM&=09yo)3(va*!)NHW9#al_-D6GznUGbfDUGV%Y+L*0;WBxm`c;QrKPau zahOG|p18Nd2f7!a^?FNJ9_9vgy%F_1PjTj9gSSOMnAG2l0W2I5%<6n0yzL6d3atT6 zEu~>9%>a{&DFB0|iiEg0mnT3`n6Y^u!(`1%*ID9SJMG%wnG#N-FbN4Gkzmaa16a&7 zV$^qLVdIpHWHH+G%^LszwPq{HG3ek6U;?Y*^3_doWk7Jk?`?PKcvQ{=Qdz~tg1^j{ zpRAcHsV#Bq3;$fAc#I6d78fCHz9-Xsr=ZD;yUR1<2wiv)<`I5_ zkQ?H)n&TaiAXrG_@*#mX<*Xp%GdIFggH%lo)tCdbOHBVG@R{Mh5OT1W-S#Q*Ti-f- zY=)PQ%P_D8YKHe@tAXd2;Z1sv+e5X#;5j=9;^w>{1EV^F89>na*myqndHy_qo=1.4 #django-celery #django-extensions #django-jsonfield + #django-polymorphic #django-split-settings #django-taggit #djangorestframework>=2.3.0,<2.4.0 @@ -25,3 +26,4 @@ Django>=1.4 # - ansible (via yum, pip or source checkout) # - psycopg2 (via "yum install python-psycopg2") # - python-ldap (via "yum install python-ldap") +# - python-zmq (for using the job callback receiver) diff --git a/requirements/prod_local.txt b/requirements/prod_local.txt index 6c22478521..7b0b1630ca 100644 --- a/requirements/prod_local.txt +++ b/requirements/prod_local.txt @@ -60,6 +60,7 @@ Django-1.5.5.tar.gz #django-celery-3.1.1.tar.gz #django-extensions-1.2.5.tar.gz #django-jsonfield-0.9.12.tar.gz + #django_polymorphic-0.5.3.tar.gz #django-split-settings-0.1.1.tar.gz #django-taggit-0.11.2.tar.gz #djangorestframework-2.3.10.tar.gz @@ -73,3 +74,4 @@ Django-1.5.5.tar.gz # - ansible (via yum, pip or source checkout) # - psycopg2 (via "yum install python-psycopg2") # - python-ldap (via "yum install python-ldap") +# - python-zmq (for using the job callback receiver) From 79e1588626c7cb56e2b765054d3f9f979ff0a75a Mon Sep 17 00:00:00 2001 From: Chris Church Date: Mon, 10 Mar 2014 17:29:09 -0400 Subject: [PATCH 2/7] AC-1040 Add 'type' attribute as serializer field, add 'types' attribute to options response. --- awx/api/generics.py | 1 + awx/api/serializers.py | 34 ++++++++++++++++++++++------------ 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/awx/api/generics.py b/awx/api/generics.py index c7575a9b5f..07daa25bdb 100644 --- a/awx/api/generics.py +++ b/awx/api/generics.py @@ -181,6 +181,7 @@ class GenericAPIView(generics.GenericAPIView, APIView): # appropriate metadata about the fields that should be supplied. serializer = self.get_serializer() actions['GET'] = serializer.metadata() + ret['types'] = [serializer.get_type(None)] # FIXME: Support multiple types? if actions: ret['actions'] = actions if getattr(self, 'search_fields', None): diff --git a/awx/api/serializers.py b/awx/api/serializers.py index d88a3e2a3d..7d803ce4b8 100644 --- a/awx/api/serializers.py +++ b/awx/api/serializers.py @@ -33,8 +33,8 @@ from awx.main.utils import update_scm_url, camelcase_to_underscore logger = logging.getLogger('awx.api.serializers') -BASE_FIELDS = ('id', 'url', 'related', 'summary_fields', 'created', 'modified', - 'name', 'description') +BASE_FIELDS = ('id', 'type', 'url', 'related', 'summary_fields', 'created', + 'modified', 'name', 'description') # Fields that should be summarized regardless of object type. DEFAULT_SUMMARY_FIELDS = ('name', 'description',) @@ -101,6 +101,7 @@ serializers.ChoiceField = ChoiceField class BaseSerializer(serializers.ModelSerializer): # add the URL and related resources + type = serializers.SerializerMethodField('get_type') url = serializers.SerializerMethodField('get_url') related = serializers.SerializerMethodField('get_related') summary_fields = serializers.SerializerMethodField('get_summary_fields') @@ -116,6 +117,9 @@ class BaseSerializer(serializers.ModelSerializer): for key, field in ret.items(): if key == 'id' and not getattr(field, 'help_text', None): field.help_text = 'Database ID for this %s.' % unicode(opts.verbose_name) + elif key == 'type': + field.help_text = 'Data type for this %s.' % unicode(opts.verbose_name) + field.type_label = 'string' elif key == 'url': field.help_text = 'URL for this %s.' % unicode(opts.verbose_name) field.type_label = 'string' @@ -133,6 +137,10 @@ class BaseSerializer(serializers.ModelSerializer): field.type_label = 'datetime' return ret + def get_type(self, obj): + opts = get_concrete_model(self.opts.model)._meta + return camelcase_to_underscore(opts.object_name) + def get_url(self, obj): if obj is None: return '' @@ -216,8 +224,9 @@ class UserSerializer(BaseSerializer): class Meta: model = User - fields = ('id', 'url', 'related', 'created', 'username', 'first_name', - 'last_name', 'email', 'is_superuser', 'password', 'ldap_dn') + fields = ('id', 'type', 'url', 'related', 'created', 'username', + 'first_name', 'last_name', 'email', 'is_superuser', + 'password', 'ldap_dn') def to_native(self, obj): ret = super(UserSerializer, self).to_native(obj) @@ -395,7 +404,7 @@ class ProjectUpdateSerializer(BaseTaskSerializer): class Meta: model = ProjectUpdate - fields = ('id', 'url', 'related', 'summary_fields', 'created', + fields = ('id', 'type', 'url', 'related', 'summary_fields', 'created', 'modified', 'project', 'status', 'failed', 'result_stdout', 'result_traceback', 'job_args', 'job_cwd', 'job_env') @@ -682,7 +691,7 @@ class InventorySourceSerializer(BaseSerializer): class Meta: model = InventorySource - fields = ('id', 'url', 'related', 'summary_fields', 'created', + fields = ('id', 'type', 'url', 'related', 'summary_fields', 'created', 'modified', 'inventory', 'group', 'source', 'source_path', 'source_vars', 'credential', 'source_regions', 'overwrite', 'overwrite_vars', 'update_on_launch', 'update_interval', @@ -772,7 +781,7 @@ class InventoryUpdateSerializer(BaseTaskSerializer): class Meta: model = InventoryUpdate - fields = ('id', 'url', 'related', 'summary_fields', 'created', + fields = ('id', 'type', 'url', 'related', 'summary_fields', 'created', 'modified', 'inventory_source', 'status', 'failed', 'result_stdout', 'result_traceback', 'job_args', 'job_cwd', 'job_env', 'license_error') @@ -979,7 +988,7 @@ class JobSerializer(BaseTaskSerializer): class Meta: model = Job - fields = ('id', 'url', 'related', 'summary_fields', 'created', + fields = ('id', 'type', 'url', 'related', 'summary_fields', 'created', 'modified', 'job_template', 'job_type', 'inventory', 'project', 'playbook', 'credential', 'cloud_credential', 'forks', 'limit', 'verbosity', 'extra_vars', @@ -1067,7 +1076,7 @@ class JobListSerializer(JobSerializer): class Meta: model = Job - fields = ('id', 'url', 'related', 'summary_fields', 'created', + fields = ('id', 'type', 'url', 'related', 'summary_fields', 'created', 'modified', 'job_template', 'job_type', 'inventory', 'project', 'playbook', 'credential', 'cloud_credential', 'forks', 'limit', 'verbosity', 'extra_vars', @@ -1080,7 +1089,7 @@ class JobHostSummarySerializer(BaseSerializer): class Meta: model = JobHostSummary - fields = ('id', 'url', 'job', 'host', 'created', 'modified', + fields = ('id', 'type', 'url', 'job', 'host', 'created', 'modified', 'summary_fields', 'related', 'changed', 'dark', 'failures', 'ok', 'processed', 'skipped', 'failed') @@ -1113,7 +1122,7 @@ class JobEventSerializer(BaseSerializer): class Meta: model = JobEvent - fields = ('id', 'url', 'created', 'modified', 'job', 'event', + fields = ('id', 'type', 'url', 'created', 'modified', 'job', 'event', 'event_display', 'event_data', 'event_level', 'failed', 'changed', 'host', 'related', 'summary_fields', 'parent', 'play', 'task') @@ -1153,7 +1162,8 @@ class ActivityStreamSerializer(BaseSerializer): class Meta: model = ActivityStream - fields = ('id', 'url', 'related', 'summary_fields', 'timestamp', 'operation', 'changes', 'object1', 'object2') + fields = ('id', 'type', 'url', 'related', 'summary_fields', + 'timestamp', 'operation', 'changes', 'object1', 'object2') def get_fields(self): ret = super(ActivityStreamSerializer, self).get_fields() From b970bf54fa69b0f8cdab98808d687c6fc36b6d90 Mon Sep 17 00:00:00 2001 From: Chris Church Date: Wed, 19 Mar 2014 16:37:01 -0400 Subject: [PATCH 3/7] AC-1040 Update jobs models and migrations (work in progress). --- awx/main/migrations/0034_v148_changes.py | 1321 ++++++++++++++++++++++ awx/main/migrations/0035_v148_changes.py | 785 +++++++++++++ awx/main/migrations/0036_v148_changes.py | 787 +++++++++++++ awx/main/migrations/0037_v148_changes.py | 475 ++++++++ awx/main/models/__init__.py | 77 +- awx/main/models/activity_stream.py | 77 +- awx/main/models/base.py | 444 ++++---- awx/main/models/inventory.py | 453 ++++++-- awx/main/models/jobs.py | 470 +++++--- awx/main/models/organization.py | 183 ++- awx/main/models/projects.py | 218 ++-- awx/main/models/schedules.py | 42 + awx/main/models/unified_jobs.py | 232 ++++ awx/settings/defaults.py | 4 + 14 files changed, 4985 insertions(+), 583 deletions(-) create mode 100644 awx/main/migrations/0034_v148_changes.py create mode 100644 awx/main/migrations/0035_v148_changes.py create mode 100644 awx/main/migrations/0036_v148_changes.py create mode 100644 awx/main/migrations/0037_v148_changes.py create mode 100644 awx/main/models/schedules.py create mode 100644 awx/main/models/unified_jobs.py diff --git a/awx/main/migrations/0034_v148_changes.py b/awx/main/migrations/0034_v148_changes.py new file mode 100644 index 0000000000..a9234cbbc5 --- /dev/null +++ b/awx/main/migrations/0034_v148_changes.py @@ -0,0 +1,1321 @@ +# -*- 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 'InventoryUpdateNew' + db.create_table(u'main_inventoryupdatenew', ( + (u'unifiedjob_ptr', self.gf('django.db.models.fields.related.OneToOneField')(to=orm['main.UnifiedJob'], unique=True, primary_key=True)), + ('source', self.gf('django.db.models.fields.CharField')(default='', max_length=32, blank=True)), + ('source_path', self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True)), + ('source_vars', self.gf('django.db.models.fields.TextField')(default='', blank=True)), + ('credential', self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name='inventoryupdatenews', null=True, blank=True, to=orm['main.Credential'])), + ('source_regions', self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True)), + ('overwrite', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('overwrite_vars', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('license_error', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('inventory_source', self.gf('django.db.models.fields.related.ForeignKey')(related_name='inventory_updates', to=orm['main.InventorySourceNew'])), + )) + db.send_create_signal('main', ['InventoryUpdateNew']) + + # Adding model 'JobNew' + db.create_table(u'main_jobnew', ( + (u'unifiedjob_ptr', self.gf('django.db.models.fields.related.OneToOneField')(to=orm['main.UnifiedJob'], unique=True, primary_key=True)), + ('job_type', self.gf('django.db.models.fields.CharField')(max_length=64)), + ('inventory', self.gf('django.db.models.fields.related.ForeignKey')(related_name='jobnews', null=True, on_delete=models.SET_NULL, to=orm['main.Inventory'])), + ('playbook', self.gf('django.db.models.fields.CharField')(default='', max_length=1024)), + ('credential', self.gf('django.db.models.fields.related.ForeignKey')(related_name='jobnews', on_delete=models.SET_NULL, default=None, to=orm['main.Credential'], blank=True, null=True)), + ('cloud_credential', self.gf('django.db.models.fields.related.ForeignKey')(related_name='jobnews_as_cloud_credential+', on_delete=models.SET_NULL, default=None, to=orm['main.Credential'], blank=True, null=True)), + ('forks', self.gf('django.db.models.fields.PositiveIntegerField')(default=0, blank=True)), + ('limit', self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True)), + ('verbosity', self.gf('django.db.models.fields.PositiveIntegerField')(default=0, blank=True)), + ('extra_vars', self.gf('django.db.models.fields.TextField')(default='', blank=True)), + ('job_tags', self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True)), + ('job_template', self.gf('django.db.models.fields.related.ForeignKey')(related_name='jobs', on_delete=models.SET_NULL, default=None, to=orm['main.JobTemplateNew'], blank=True, null=True)), + ('project', self.gf('django.db.models.fields.related.ForeignKey')(related_name='jobs', null=True, on_delete=models.SET_NULL, to=orm['main.ProjectNew'])), + )) + db.send_create_signal('main', ['JobNew']) + + # Adding model 'UnifiedJob' + db.create_table(u'main_unifiedjob', ( + (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('polymorphic_ctype', self.gf('django.db.models.fields.related.ForeignKey')(related_name='polymorphic_main.unifiedjob_set', null=True, to=orm['contenttypes.ContentType'])), + ('created', self.gf('django.db.models.fields.DateTimeField')(default=None)), + ('modified', self.gf('django.db.models.fields.DateTimeField')(default=None)), + ('description', self.gf('django.db.models.fields.TextField')(default='', blank=True)), + ('created_by', self.gf('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=orm['auth.User'])), + ('modified_by', self.gf('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=orm['auth.User'])), + ('active', self.gf('django.db.models.fields.BooleanField')(default=True)), + ('old_pk', self.gf('django.db.models.fields.PositiveIntegerField')(default=None, null=True)), + ('unified_job_template', self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name='unifiedjob_unified_jobs', null=True, to=orm['main.UnifiedJobTemplate'])), + ('launch_type', self.gf('django.db.models.fields.CharField')(default='manual', max_length=20)), + ('schedule', self.gf('django.db.models.fields.related.ForeignKey')(default=None, to=orm['main.Schedule'], null=True)), + ('cancel_flag', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('status', self.gf('django.db.models.fields.CharField')(default='new', max_length=20)), + ('failed', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('started', self.gf('django.db.models.fields.DateTimeField')(default=None, null=True)), + ('finished', self.gf('django.db.models.fields.DateTimeField')(default=None, null=True)), + ('elapsed', self.gf('django.db.models.fields.DecimalField')(max_digits=12, decimal_places=3)), + ('job_args', self.gf('django.db.models.fields.TextField')(default='', blank=True)), + ('job_cwd', self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True)), + ('job_env', self.gf('jsonfield.fields.JSONField')(default={}, blank=True)), + ('start_args', self.gf('django.db.models.fields.TextField')(default='', blank=True)), + ('result_stdout_text', self.gf('django.db.models.fields.TextField')(default='', blank=True)), + ('result_stdout_file', self.gf('django.db.models.fields.TextField')(default='', blank=True)), + ('result_traceback', self.gf('django.db.models.fields.TextField')(default='', blank=True)), + ('celery_task_id', self.gf('django.db.models.fields.CharField')(default='', max_length=100, blank=True)), + )) + db.send_create_signal('main', ['UnifiedJob']) + + # Adding M2M table for field depends_on on 'UnifiedJob' + m2m_table_name = db.shorten_name(u'main_unifiedjob_depends_on') + db.create_table(m2m_table_name, ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('from_unifiedjob', models.ForeignKey(orm['main.unifiedjob'], null=False)), + ('to_unifiedjob', models.ForeignKey(orm['main.unifiedjob'], null=False)) + )) + db.create_unique(m2m_table_name, ['from_unifiedjob_id', 'to_unifiedjob_id']) + + # Adding model 'Schedule' + db.create_table(u'main_schedule', ( + (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('created', self.gf('django.db.models.fields.DateTimeField')(default=None)), + ('modified', self.gf('django.db.models.fields.DateTimeField')(default=None)), + ('description', self.gf('django.db.models.fields.TextField')(default='', blank=True)), + ('created_by', self.gf('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=orm['auth.User'])), + ('modified_by', self.gf('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=orm['auth.User'])), + ('active', self.gf('django.db.models.fields.BooleanField')(default=True)), + ('name', self.gf('django.db.models.fields.CharField')(unique=True, max_length=512)), + ('job_template', self.gf('django.db.models.fields.related.ForeignKey')(related_name='schedules', to=orm['main.UnifiedJobTemplate'])), + ('dtstart', self.gf('django.db.models.fields.DateTimeField')()), + ('dtend', self.gf('django.db.models.fields.DateTimeField')(default=None, null=True)), + ('rrule', self.gf('django.db.models.fields.CharField')(max_length=255)), + )) + db.send_create_signal('main', ['Schedule']) + + # Adding model 'InventorySourceNew' + db.create_table(u'main_inventorysourcenew', ( + (u'unifiedjobtemplate_ptr', self.gf('django.db.models.fields.related.OneToOneField')(to=orm['main.UnifiedJobTemplate'], unique=True, primary_key=True)), + ('source', self.gf('django.db.models.fields.CharField')(default='', max_length=32, blank=True)), + ('source_path', self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True)), + ('source_vars', self.gf('django.db.models.fields.TextField')(default='', blank=True)), + ('credential', self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name='inventorysourcenews', null=True, blank=True, to=orm['main.Credential'])), + ('source_regions', self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True)), + ('overwrite', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('overwrite_vars', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('update_on_launch', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('update_cache_timeout', self.gf('django.db.models.fields.PositiveIntegerField')(default=0)), + ('inventory', self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name='new_inventory_sources', null=True, to=orm['main.Inventory'])), + ('group', self.gf('awx.main.fields.AutoOneToOneField')(related_name='new_inventory_source', null=True, default=None, to=orm['main.Group'], blank=True, unique=True)), + )) + db.send_create_signal('main', ['InventorySourceNew']) + + # Adding model 'JobTemplateNew' + db.create_table('main_jobtemplatenew', ( + (u'unifiedjobtemplate_ptr', self.gf('django.db.models.fields.related.OneToOneField')(to=orm['main.UnifiedJobTemplate'], unique=True, primary_key=True)), + ('job_type', self.gf('django.db.models.fields.CharField')(max_length=64)), + ('inventory', self.gf('django.db.models.fields.related.ForeignKey')(related_name='jobtemplatenews', null=True, on_delete=models.SET_NULL, to=orm['main.Inventory'])), + ('playbook', self.gf('django.db.models.fields.CharField')(default='', max_length=1024)), + ('credential', self.gf('django.db.models.fields.related.ForeignKey')(related_name='jobtemplatenews', on_delete=models.SET_NULL, default=None, to=orm['main.Credential'], blank=True, null=True)), + ('cloud_credential', self.gf('django.db.models.fields.related.ForeignKey')(related_name='jobtemplatenews_as_cloud_credential+', on_delete=models.SET_NULL, default=None, to=orm['main.Credential'], blank=True, null=True)), + ('forks', self.gf('django.db.models.fields.PositiveIntegerField')(default=0, blank=True)), + ('limit', self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True)), + ('verbosity', self.gf('django.db.models.fields.PositiveIntegerField')(default=0, blank=True)), + ('extra_vars', self.gf('django.db.models.fields.TextField')(default='', blank=True)), + ('job_tags', self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True)), + ('host_config_key', self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True)), + ('project', self.gf('django.db.models.fields.related.ForeignKey')(related_name='job_templates', null=True, on_delete=models.SET_NULL, to=orm['main.ProjectNew'])), + )) + db.send_create_signal('main', ['JobTemplateNew']) + + # Adding model 'ProjectNew' + db.create_table(u'main_projectnew', ( + (u'unifiedjobtemplate_ptr', self.gf('django.db.models.fields.related.OneToOneField')(to=orm['main.UnifiedJobTemplate'], unique=True, primary_key=True)), + ('local_path', self.gf('django.db.models.fields.CharField')(max_length=1024, blank=True)), + ('scm_type', self.gf('django.db.models.fields.CharField')(default='', max_length=8, blank=True)), + ('scm_url', self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True)), + ('scm_branch', self.gf('django.db.models.fields.CharField')(default='', max_length=256, blank=True)), + ('scm_clean', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('scm_delete_on_update', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('credential', self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name='projectnews', null=True, blank=True, to=orm['main.Credential'])), + ('scm_delete_on_next_update', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('scm_update_on_launch', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('scm_update_cache_timeout', self.gf('django.db.models.fields.PositiveIntegerField')(default=0)), + )) + db.send_create_signal('main', ['ProjectNew']) + + # Adding model 'ProjectUpdateNew' + db.create_table(u'main_projectupdatenew', ( + (u'unifiedjob_ptr', self.gf('django.db.models.fields.related.OneToOneField')(to=orm['main.UnifiedJob'], unique=True, primary_key=True)), + ('local_path', self.gf('django.db.models.fields.CharField')(max_length=1024, blank=True)), + ('scm_type', self.gf('django.db.models.fields.CharField')(default='', max_length=8, blank=True)), + ('scm_url', self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True)), + ('scm_branch', self.gf('django.db.models.fields.CharField')(default='', max_length=256, blank=True)), + ('scm_clean', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('scm_delete_on_update', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('credential', self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name='projectupdatenews', null=True, blank=True, to=orm['main.Credential'])), + ('project', self.gf('django.db.models.fields.related.ForeignKey')(related_name='project_updates', to=orm['main.ProjectNew'])), + )) + db.send_create_signal('main', ['ProjectUpdateNew']) + + # Adding model 'UnifiedJobTemplate' + db.create_table(u'main_unifiedjobtemplate', ( + (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('polymorphic_ctype', self.gf('django.db.models.fields.related.ForeignKey')(related_name='polymorphic_main.unifiedjobtemplate_set', null=True, to=orm['contenttypes.ContentType'])), + ('created', self.gf('django.db.models.fields.DateTimeField')(default=None)), + ('modified', self.gf('django.db.models.fields.DateTimeField')(default=None)), + ('description', self.gf('django.db.models.fields.TextField')(default='', blank=True)), + ('created_by', self.gf('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=orm['auth.User'])), + ('modified_by', self.gf('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=orm['auth.User'])), + ('active', self.gf('django.db.models.fields.BooleanField')(default=True)), + ('name', self.gf('django.db.models.fields.CharField')(max_length=512)), + ('old_pk', self.gf('django.db.models.fields.PositiveIntegerField')(default=None, null=True)), + ('current_job', self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name='unifiedjobtemplate_as_current_job+', null=True, to=orm['main.UnifiedJob'])), + ('last_job', self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name='unifiedjobtemplate_as_last_job+', null=True, to=orm['main.UnifiedJob'])), + ('last_job_failed', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('last_job_run', self.gf('django.db.models.fields.DateTimeField')(default=None, null=True)), + ('has_schedules', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('next_job_run', self.gf('django.db.models.fields.DateTimeField')(default=None, null=True)), + ('status', self.gf('django.db.models.fields.CharField')(default='ok', max_length=32)), + )) + db.send_create_signal('main', ['UnifiedJobTemplate']) + + # Adding unique constraint on 'UnifiedJobTemplate', fields ['polymorphic_ctype', 'name'] + db.create_unique(u'main_unifiedjobtemplate', ['polymorphic_ctype_id', 'name']) + + + # Changing field 'Profile.created' + db.alter_column(u'main_profile', 'created', self.gf('django.db.models.fields.DateTimeField')()) + + # Changing field 'Profile.modified' + db.alter_column(u'main_profile', 'modified', self.gf('django.db.models.fields.DateTimeField')()) + # Adding field 'ProjectUpdate.local_path' + db.add_column(u'main_projectupdate', 'local_path', + self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True), + keep_default=False) + + # Adding field 'ProjectUpdate.scm_type' + db.add_column(u'main_projectupdate', 'scm_type', + self.gf('django.db.models.fields.CharField')(default='', max_length=8, blank=True), + keep_default=False) + + # Adding field 'ProjectUpdate.scm_url' + db.add_column(u'main_projectupdate', 'scm_url', + self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True), + keep_default=False) + + # Adding field 'ProjectUpdate.scm_branch' + db.add_column(u'main_projectupdate', 'scm_branch', + self.gf('django.db.models.fields.CharField')(default='', max_length=256, blank=True), + keep_default=False) + + # Adding field 'ProjectUpdate.scm_clean' + db.add_column(u'main_projectupdate', 'scm_clean', + self.gf('django.db.models.fields.BooleanField')(default=False), + keep_default=False) + + # Adding field 'ProjectUpdate.scm_delete_on_update' + db.add_column(u'main_projectupdate', 'scm_delete_on_update', + self.gf('django.db.models.fields.BooleanField')(default=False), + keep_default=False) + + # Adding field 'ProjectUpdate.credential' + db.add_column(u'main_projectupdate', 'credential', + self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name='projectupdates', null=True, blank=True, to=orm['main.Credential']), + keep_default=False) + + + # Changing field 'ProjectUpdate.created' + db.alter_column(u'main_projectupdate', 'created', self.gf('django.db.models.fields.DateTimeField')()) + + # Changing field 'ProjectUpdate.modified' + db.alter_column(u'main_projectupdate', 'modified', self.gf('django.db.models.fields.DateTimeField')()) + # Adding M2M table for field new_inventory_sources on 'Group' + m2m_table_name = db.shorten_name(u'main_group_new_inventory_sources') + db.create_table(m2m_table_name, ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('group', models.ForeignKey(orm['main.group'], null=False)), + ('inventorysourcenew', models.ForeignKey(orm['main.inventorysourcenew'], null=False)) + )) + db.create_unique(m2m_table_name, ['group_id', 'inventorysourcenew_id']) + + + # Changing field 'Group.created' + db.alter_column(u'main_group', 'created', self.gf('django.db.models.fields.DateTimeField')()) + + # Changing field 'Group.modified' + db.alter_column(u'main_group', 'modified', self.gf('django.db.models.fields.DateTimeField')()) + + # Changing field 'Job.created' + db.alter_column(u'main_job', 'created', self.gf('django.db.models.fields.DateTimeField')()) + + # Changing field 'Job.modified' + db.alter_column(u'main_job', 'modified', self.gf('django.db.models.fields.DateTimeField')()) + + # Changing field 'Inventory.created' + db.alter_column(u'main_inventory', 'created', self.gf('django.db.models.fields.DateTimeField')()) + + # Changing field 'Inventory.modified' + db.alter_column(u'main_inventory', 'modified', self.gf('django.db.models.fields.DateTimeField')()) + # Adding field 'Host.new_last_job' + db.add_column(u'main_host', 'new_last_job', + self.gf('django.db.models.fields.related.ForeignKey')(related_name='hosts_as_last_job+', on_delete=models.SET_NULL, default=None, to=orm['main.JobNew'], blank=True, null=True), + keep_default=False) + + # Adding M2M table for field new_inventory_sources on 'Host' + m2m_table_name = db.shorten_name(u'main_host_new_inventory_sources') + db.create_table(m2m_table_name, ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('host', models.ForeignKey(orm['main.host'], null=False)), + ('inventorysourcenew', models.ForeignKey(orm['main.inventorysourcenew'], null=False)) + )) + db.create_unique(m2m_table_name, ['host_id', 'inventorysourcenew_id']) + + + # Changing field 'Host.created' + db.alter_column(u'main_host', 'created', self.gf('django.db.models.fields.DateTimeField')()) + + # Changing field 'Host.modified' + db.alter_column(u'main_host', 'modified', self.gf('django.db.models.fields.DateTimeField')()) + # Adding field 'JobHostSummary.new_job' + db.add_column(u'main_jobhostsummary', 'new_job', + self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name='new_job_host_summaries', null=True, to=orm['main.JobNew']), + keep_default=False) + + + # Changing field 'JobHostSummary.created' + db.alter_column(u'main_jobhostsummary', 'created', self.gf('django.db.models.fields.DateTimeField')()) + + # Changing field 'JobHostSummary.modified' + db.alter_column(u'main_jobhostsummary', 'modified', self.gf('django.db.models.fields.DateTimeField')()) + # Adding unique constraint on 'JobHostSummary', fields ['new_job', 'host'] + db.create_unique(u'main_jobhostsummary', ['new_job_id', 'host_id']) + + # Adding field 'InventoryUpdate.source' + db.add_column(u'main_inventoryupdate', 'source', + self.gf('django.db.models.fields.CharField')(default='', max_length=32, blank=True), + keep_default=False) + + # Adding field 'InventoryUpdate.source_path' + db.add_column(u'main_inventoryupdate', 'source_path', + self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True), + keep_default=False) + + # Adding field 'InventoryUpdate.source_vars' + db.add_column(u'main_inventoryupdate', 'source_vars', + self.gf('django.db.models.fields.TextField')(default='', blank=True), + keep_default=False) + + # Adding field 'InventoryUpdate.credential' + db.add_column(u'main_inventoryupdate', 'credential', + self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name='inventoryupdates', null=True, blank=True, to=orm['main.Credential']), + keep_default=False) + + # Adding field 'InventoryUpdate.source_regions' + db.add_column(u'main_inventoryupdate', 'source_regions', + self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True), + keep_default=False) + + # Adding field 'InventoryUpdate.overwrite' + db.add_column(u'main_inventoryupdate', 'overwrite', + self.gf('django.db.models.fields.BooleanField')(default=False), + keep_default=False) + + # Adding field 'InventoryUpdate.overwrite_vars' + db.add_column(u'main_inventoryupdate', 'overwrite_vars', + self.gf('django.db.models.fields.BooleanField')(default=False), + keep_default=False) + + + # Changing field 'InventoryUpdate.created' + db.alter_column(u'main_inventoryupdate', 'created', self.gf('django.db.models.fields.DateTimeField')()) + + # Changing field 'InventoryUpdate.modified' + db.alter_column(u'main_inventoryupdate', 'modified', self.gf('django.db.models.fields.DateTimeField')()) + + # Changing field 'Credential.created' + db.alter_column(u'main_credential', 'created', self.gf('django.db.models.fields.DateTimeField')()) + + # Changing field 'Credential.modified' + db.alter_column(u'main_credential', 'modified', self.gf('django.db.models.fields.DateTimeField')()) + + # Changing field 'JobTemplate.created' + db.alter_column(u'main_jobtemplate', 'created', self.gf('django.db.models.fields.DateTimeField')()) + + # Changing field 'JobTemplate.modified' + db.alter_column(u'main_jobtemplate', 'modified', self.gf('django.db.models.fields.DateTimeField')()) + # Adding M2M table for field unified_job_template on 'ActivityStream' + m2m_table_name = db.shorten_name(u'main_activitystream_unified_job_template') + db.create_table(m2m_table_name, ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('activitystream', models.ForeignKey(orm['main.activitystream'], null=False)), + ('unifiedjobtemplate', models.ForeignKey(orm['main.unifiedjobtemplate'], null=False)) + )) + db.create_unique(m2m_table_name, ['activitystream_id', 'unifiedjobtemplate_id']) + + # Adding M2M table for field unified_job on 'ActivityStream' + m2m_table_name = db.shorten_name(u'main_activitystream_unified_job') + db.create_table(m2m_table_name, ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('activitystream', models.ForeignKey(orm['main.activitystream'], null=False)), + ('unifiedjob', models.ForeignKey(orm['main.unifiedjob'], null=False)) + )) + db.create_unique(m2m_table_name, ['activitystream_id', 'unifiedjob_id']) + + # Adding M2M table for field new_inventory_source on 'ActivityStream' + m2m_table_name = db.shorten_name(u'main_activitystream_new_inventory_source') + db.create_table(m2m_table_name, ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('activitystream', models.ForeignKey(orm['main.activitystream'], null=False)), + ('inventorysourcenew', models.ForeignKey(orm['main.inventorysourcenew'], null=False)) + )) + db.create_unique(m2m_table_name, ['activitystream_id', 'inventorysourcenew_id']) + + # Adding M2M table for field new_inventory_update on 'ActivityStream' + m2m_table_name = db.shorten_name(u'main_activitystream_new_inventory_update') + db.create_table(m2m_table_name, ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('activitystream', models.ForeignKey(orm['main.activitystream'], null=False)), + ('inventoryupdatenew', models.ForeignKey(orm['main.inventoryupdatenew'], null=False)) + )) + db.create_unique(m2m_table_name, ['activitystream_id', 'inventoryupdatenew_id']) + + # Adding M2M table for field new_project on 'ActivityStream' + m2m_table_name = db.shorten_name(u'main_activitystream_new_project') + db.create_table(m2m_table_name, ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('activitystream', models.ForeignKey(orm['main.activitystream'], null=False)), + ('projectnew', models.ForeignKey(orm['main.projectnew'], null=False)) + )) + db.create_unique(m2m_table_name, ['activitystream_id', 'projectnew_id']) + + # Adding M2M table for field new_project_update on 'ActivityStream' + m2m_table_name = db.shorten_name(u'main_activitystream_new_project_update') + db.create_table(m2m_table_name, ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('activitystream', models.ForeignKey(orm['main.activitystream'], null=False)), + ('projectupdatenew', models.ForeignKey(orm['main.projectupdatenew'], null=False)) + )) + db.create_unique(m2m_table_name, ['activitystream_id', 'projectupdatenew_id']) + + # Adding M2M table for field new_job_template on 'ActivityStream' + m2m_table_name = db.shorten_name(u'main_activitystream_new_job_template') + db.create_table(m2m_table_name, ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('activitystream', models.ForeignKey(orm['main.activitystream'], null=False)), + ('jobtemplatenew', models.ForeignKey(orm['main.jobtemplatenew'], null=False)) + )) + db.create_unique(m2m_table_name, ['activitystream_id', 'jobtemplatenew_id']) + + # Adding M2M table for field new_job on 'ActivityStream' + m2m_table_name = db.shorten_name(u'main_activitystream_new_job') + db.create_table(m2m_table_name, ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('activitystream', models.ForeignKey(orm['main.activitystream'], null=False)), + ('jobnew', models.ForeignKey(orm['main.jobnew'], null=False)) + )) + db.create_unique(m2m_table_name, ['activitystream_id', 'jobnew_id']) + + # Adding M2M table for field new_projects on 'Team' + m2m_table_name = db.shorten_name(u'main_team_new_projects') + db.create_table(m2m_table_name, ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('team', models.ForeignKey(orm['main.team'], null=False)), + ('projectnew', models.ForeignKey(orm['main.projectnew'], null=False)) + )) + db.create_unique(m2m_table_name, ['team_id', 'projectnew_id']) + + + # Changing field 'Team.created' + db.alter_column(u'main_team', 'created', self.gf('django.db.models.fields.DateTimeField')()) + + # Changing field 'Team.modified' + db.alter_column(u'main_team', 'modified', self.gf('django.db.models.fields.DateTimeField')()) + # Adding field 'Project.scm_update_cache_timeout' + db.add_column(u'main_project', 'scm_update_cache_timeout', + self.gf('django.db.models.fields.PositiveIntegerField')(default=0), + keep_default=False) + + + # Changing field 'Project.created' + db.alter_column(u'main_project', 'created', self.gf('django.db.models.fields.DateTimeField')()) + + # Changing field 'Project.modified' + db.alter_column(u'main_project', 'modified', self.gf('django.db.models.fields.DateTimeField')()) + # Adding M2M table for field new_projects on 'Organization' + m2m_table_name = db.shorten_name(u'main_organization_new_projects') + db.create_table(m2m_table_name, ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('organization', models.ForeignKey(orm['main.organization'], null=False)), + ('projectnew', models.ForeignKey(orm['main.projectnew'], null=False)) + )) + db.create_unique(m2m_table_name, ['organization_id', 'projectnew_id']) + + + # Changing field 'Organization.created' + db.alter_column(u'main_organization', 'created', self.gf('django.db.models.fields.DateTimeField')()) + + # Changing field 'Organization.modified' + db.alter_column(u'main_organization', 'modified', self.gf('django.db.models.fields.DateTimeField')()) + # Adding field 'Permission.new_project' + db.add_column(u'main_permission', 'new_project', + self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='permissions', null=True, on_delete=models.SET_NULL, to=orm['main.ProjectNew']), + keep_default=False) + + + # Changing field 'Permission.created' + db.alter_column(u'main_permission', 'created', self.gf('django.db.models.fields.DateTimeField')()) + + # Changing field 'Permission.modified' + db.alter_column(u'main_permission', 'modified', self.gf('django.db.models.fields.DateTimeField')()) + # Deleting field 'InventorySource.update_interval' + db.delete_column(u'main_inventorysource', 'update_interval') + + # Adding field 'InventorySource.update_cache_timeout' + db.add_column(u'main_inventorysource', 'update_cache_timeout', + self.gf('django.db.models.fields.PositiveIntegerField')(default=0), + keep_default=False) + + + # Changing field 'InventorySource.created' + db.alter_column(u'main_inventorysource', 'created', self.gf('django.db.models.fields.DateTimeField')()) + + # Changing field 'InventorySource.modified' + db.alter_column(u'main_inventorysource', 'modified', self.gf('django.db.models.fields.DateTimeField')()) + # Adding field 'JobEvent.role' + db.add_column(u'main_jobevent', 'role', + self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True), + keep_default=False) + + # Adding field 'JobEvent.new_job' + db.add_column(u'main_jobevent', 'new_job', + self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name='new_job_events', null=True, to=orm['main.JobNew']), + keep_default=False) + + + def backwards(self, orm): + # Removing unique constraint on 'JobHostSummary', fields ['new_job', 'host'] + db.delete_unique(u'main_jobhostsummary', ['new_job_id', 'host_id']) + + # Removing unique constraint on 'UnifiedJobTemplate', fields ['polymorphic_ctype', 'name'] + db.delete_unique(u'main_unifiedjobtemplate', ['polymorphic_ctype_id', 'name']) + + # Deleting model 'InventoryUpdateNew' + db.delete_table(u'main_inventoryupdatenew') + + # Deleting model 'JobNew' + db.delete_table(u'main_jobnew') + + # Deleting model 'UnifiedJob' + db.delete_table(u'main_unifiedjob') + + # Removing M2M table for field depends_on on 'UnifiedJob' + db.delete_table(db.shorten_name(u'main_unifiedjob_depends_on')) + + # Deleting model 'Schedule' + db.delete_table(u'main_schedule') + + # Deleting model 'InventorySourceNew' + db.delete_table(u'main_inventorysourcenew') + + # Deleting model 'JobTemplateNew' + db.delete_table('main_jobtemplatenew') + + # Deleting model 'ProjectNew' + db.delete_table(u'main_projectnew') + + # Deleting model 'ProjectUpdateNew' + db.delete_table(u'main_projectupdatenew') + + # Deleting model 'UnifiedJobTemplate' + db.delete_table(u'main_unifiedjobtemplate') + + + # Changing field 'Profile.created' + db.alter_column(u'main_profile', 'created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True)) + + # Changing field 'Profile.modified' + db.alter_column(u'main_profile', 'modified', self.gf('django.db.models.fields.DateTimeField')(auto_now=True)) + # Deleting field 'ProjectUpdate.local_path' + db.delete_column(u'main_projectupdate', 'local_path') + + # Deleting field 'ProjectUpdate.scm_type' + db.delete_column(u'main_projectupdate', 'scm_type') + + # Deleting field 'ProjectUpdate.scm_url' + db.delete_column(u'main_projectupdate', 'scm_url') + + # Deleting field 'ProjectUpdate.scm_branch' + db.delete_column(u'main_projectupdate', 'scm_branch') + + # Deleting field 'ProjectUpdate.scm_clean' + db.delete_column(u'main_projectupdate', 'scm_clean') + + # Deleting field 'ProjectUpdate.scm_delete_on_update' + db.delete_column(u'main_projectupdate', 'scm_delete_on_update') + + # Deleting field 'ProjectUpdate.credential' + db.delete_column(u'main_projectupdate', 'credential_id') + + + # Changing field 'ProjectUpdate.created' + db.alter_column(u'main_projectupdate', 'created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True)) + + # Changing field 'ProjectUpdate.modified' + db.alter_column(u'main_projectupdate', 'modified', self.gf('django.db.models.fields.DateTimeField')(auto_now=True)) + # Removing M2M table for field new_inventory_sources on 'Group' + db.delete_table(db.shorten_name(u'main_group_new_inventory_sources')) + + + # Changing field 'Group.created' + db.alter_column(u'main_group', 'created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True)) + + # Changing field 'Group.modified' + db.alter_column(u'main_group', 'modified', self.gf('django.db.models.fields.DateTimeField')(auto_now=True)) + + # Changing field 'Job.created' + db.alter_column(u'main_job', 'created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True)) + + # Changing field 'Job.modified' + db.alter_column(u'main_job', 'modified', self.gf('django.db.models.fields.DateTimeField')(auto_now=True)) + + # Changing field 'Inventory.created' + db.alter_column(u'main_inventory', 'created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True)) + + # Changing field 'Inventory.modified' + db.alter_column(u'main_inventory', 'modified', self.gf('django.db.models.fields.DateTimeField')(auto_now=True)) + # Deleting field 'Host.new_last_job' + db.delete_column(u'main_host', 'new_last_job_id') + + # Removing M2M table for field new_inventory_sources on 'Host' + db.delete_table(db.shorten_name(u'main_host_new_inventory_sources')) + + + # Changing field 'Host.created' + db.alter_column(u'main_host', 'created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True)) + + # Changing field 'Host.modified' + db.alter_column(u'main_host', 'modified', self.gf('django.db.models.fields.DateTimeField')(auto_now=True)) + # Deleting field 'JobHostSummary.new_job' + db.delete_column(u'main_jobhostsummary', 'new_job_id') + + + # Changing field 'JobHostSummary.created' + db.alter_column(u'main_jobhostsummary', 'created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True)) + + # Changing field 'JobHostSummary.modified' + db.alter_column(u'main_jobhostsummary', 'modified', self.gf('django.db.models.fields.DateTimeField')(auto_now=True)) + # Deleting field 'InventoryUpdate.source' + db.delete_column(u'main_inventoryupdate', 'source') + + # Deleting field 'InventoryUpdate.source_path' + db.delete_column(u'main_inventoryupdate', 'source_path') + + # Deleting field 'InventoryUpdate.source_vars' + db.delete_column(u'main_inventoryupdate', 'source_vars') + + # Deleting field 'InventoryUpdate.credential' + db.delete_column(u'main_inventoryupdate', 'credential_id') + + # Deleting field 'InventoryUpdate.source_regions' + db.delete_column(u'main_inventoryupdate', 'source_regions') + + # Deleting field 'InventoryUpdate.overwrite' + db.delete_column(u'main_inventoryupdate', 'overwrite') + + # Deleting field 'InventoryUpdate.overwrite_vars' + db.delete_column(u'main_inventoryupdate', 'overwrite_vars') + + + # Changing field 'InventoryUpdate.created' + db.alter_column(u'main_inventoryupdate', 'created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True)) + + # Changing field 'InventoryUpdate.modified' + db.alter_column(u'main_inventoryupdate', 'modified', self.gf('django.db.models.fields.DateTimeField')(auto_now=True)) + + # Changing field 'Credential.created' + db.alter_column(u'main_credential', 'created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True)) + + # Changing field 'Credential.modified' + db.alter_column(u'main_credential', 'modified', self.gf('django.db.models.fields.DateTimeField')(auto_now=True)) + + # Changing field 'JobTemplate.created' + db.alter_column(u'main_jobtemplate', 'created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True)) + + # Changing field 'JobTemplate.modified' + db.alter_column(u'main_jobtemplate', 'modified', self.gf('django.db.models.fields.DateTimeField')(auto_now=True)) + # Removing M2M table for field unified_job_template on 'ActivityStream' + db.delete_table(db.shorten_name(u'main_activitystream_unified_job_template')) + + # Removing M2M table for field unified_job on 'ActivityStream' + db.delete_table(db.shorten_name(u'main_activitystream_unified_job')) + + # Removing M2M table for field new_inventory_source on 'ActivityStream' + db.delete_table(db.shorten_name(u'main_activitystream_new_inventory_source')) + + # Removing M2M table for field new_inventory_update on 'ActivityStream' + db.delete_table(db.shorten_name(u'main_activitystream_new_inventory_update')) + + # Removing M2M table for field new_project on 'ActivityStream' + db.delete_table(db.shorten_name(u'main_activitystream_new_project')) + + # Removing M2M table for field new_project_update on 'ActivityStream' + db.delete_table(db.shorten_name(u'main_activitystream_new_project_update')) + + # Removing M2M table for field new_job_template on 'ActivityStream' + db.delete_table(db.shorten_name(u'main_activitystream_new_job_template')) + + # Removing M2M table for field new_job on 'ActivityStream' + db.delete_table(db.shorten_name(u'main_activitystream_new_job')) + + # Removing M2M table for field new_projects on 'Team' + db.delete_table(db.shorten_name(u'main_team_new_projects')) + + + # Changing field 'Team.created' + db.alter_column(u'main_team', 'created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True)) + + # Changing field 'Team.modified' + db.alter_column(u'main_team', 'modified', self.gf('django.db.models.fields.DateTimeField')(auto_now=True)) + # Deleting field 'Project.scm_update_cache_timeout' + db.delete_column(u'main_project', 'scm_update_cache_timeout') + + + # Changing field 'Project.created' + db.alter_column(u'main_project', 'created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True)) + + # Changing field 'Project.modified' + db.alter_column(u'main_project', 'modified', self.gf('django.db.models.fields.DateTimeField')(auto_now=True)) + # Removing M2M table for field new_projects on 'Organization' + db.delete_table(db.shorten_name(u'main_organization_new_projects')) + + + # Changing field 'Organization.created' + db.alter_column(u'main_organization', 'created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True)) + + # Changing field 'Organization.modified' + db.alter_column(u'main_organization', 'modified', self.gf('django.db.models.fields.DateTimeField')(auto_now=True)) + # Deleting field 'Permission.new_project' + db.delete_column(u'main_permission', 'new_project_id') + + + # Changing field 'Permission.created' + db.alter_column(u'main_permission', 'created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True)) + + # Changing field 'Permission.modified' + db.alter_column(u'main_permission', 'modified', self.gf('django.db.models.fields.DateTimeField')(auto_now=True)) + # Adding field 'InventorySource.update_interval' + db.add_column(u'main_inventorysource', 'update_interval', + self.gf('django.db.models.fields.PositiveIntegerField')(default=0), + keep_default=False) + + # Deleting field 'InventorySource.update_cache_timeout' + db.delete_column(u'main_inventorysource', 'update_cache_timeout') + + + # Changing field 'InventorySource.created' + db.alter_column(u'main_inventorysource', 'created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True)) + + # Changing field 'InventorySource.modified' + db.alter_column(u'main_inventorysource', 'modified', self.gf('django.db.models.fields.DateTimeField')(auto_now=True)) + # Deleting field 'JobEvent.role' + db.delete_column(u'main_jobevent', 'role') + + # Deleting field 'JobEvent.new_job' + db.delete_column(u'main_jobevent', 'new_job_id') + + + 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', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), + 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', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), + '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'}), + 'new_inventory_source': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.InventorySourceNew']", 'symmetrical': 'False', 'blank': 'True'}), + 'new_inventory_update': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.InventoryUpdateNew']", 'symmetrical': 'False', 'blank': 'True'}), + 'new_job': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.JobNew']", 'symmetrical': 'False', 'blank': 'True'}), + 'new_job_template': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.JobTemplateNew']", 'symmetrical': 'False', 'blank': 'True'}), + 'new_project': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.ProjectNew']", 'symmetrical': 'False', 'blank': 'True'}), + 'new_project_update': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.ProjectUpdateNew']", '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'}), + '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': {'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'}), + 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'}), + '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'}), + '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'}) + }, + 'main.group': { + 'Meta': {'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', [], {'symmetrical': 'False', 'related_name': "'groups'", 'blank': 'True', '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'}), + 'new_inventory_sources': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'groups'", 'blank': 'True', 'to': "orm['main.InventorySourceNew']"}), + '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': {'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', [], {'symmetrical': 'False', 'related_name': "'hosts'", 'blank': 'True', 'to': "orm['main.InventorySource']"}), + 'last_job': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'hosts_as_last_job+'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.Job']", 'blank': 'True', 'null': 'True'}), + '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'}), + 'new_inventory_sources': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'hosts'", 'blank': 'True', 'to': "orm['main.InventorySourceNew']"}), + 'new_last_job': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'hosts_as_last_job+'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.JobNew']", 'blank': 'True', 'null': 'True'}), + 'variables': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}) + }, + 'main.inventory': { + 'Meta': {'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'}, + '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\': \'inventorysource\', \'app_label\': \'main\'}(class)s_created+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), + 'credential': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'inventorysources'", 'null': 'True', 'blank': 'True', 'to': "orm['main.Credential']"}), + 'current_update': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'inventory_source_as_current_update+'", 'null': 'True', 'to': "orm['main.InventoryUpdate']"}), + 'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'group': ('awx.main.fields.AutoOneToOneField', [], {'related_name': "'inventory_source'", 'null': 'True', 'default': 'None', 'to': "orm['main.Group']", 'blank': 'True', 'unique': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'inventory': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'inventory_sources'", 'null': 'True', 'to': "orm['main.Inventory']"}), + 'last_update': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'inventory_source_as_last_update+'", 'null': 'True', 'to': "orm['main.InventoryUpdate']"}), + 'last_update_failed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_updated': ('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\': \'inventorysource\', \'app_label\': \'main\'}(class)s_modified+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), + '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_vars': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'status': ('django.db.models.fields.CharField', [], {'default': "'none'", 'max_length': '32'}), + 'update_cache_timeout': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'update_on_launch': ('django.db.models.fields.BooleanField', [], {'default': 'False'}) + }, + 'main.inventorysourcenew': { + 'Meta': {'object_name': 'InventorySourceNew', '_ormbases': ['main.UnifiedJobTemplate']}, + 'credential': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'inventorysourcenews'", 'null': 'True', 'blank': 'True', 'to': "orm['main.Credential']"}), + 'group': ('awx.main.fields.AutoOneToOneField', [], {'related_name': "'new_inventory_source'", 'null': 'True', 'default': 'None', 'to': "orm['main.Group']", 'blank': 'True', 'unique': 'True'}), + 'inventory': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'new_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_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'}, + '_result_stdout': ('django.db.models.fields.TextField', [], {'default': "''", 'db_column': "'result_stdout'", 'blank': 'True'}), + '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\': \'inventoryupdate\', \'app_label\': \'main\'}(class)s_created+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), + 'credential': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'inventoryupdates'", 'null': 'True', 'blank': 'True', 'to': "orm['main.Credential']"}), + 'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'failed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'inventory_source': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'inventory_updates'", 'to': "orm['main.InventorySource']"}), + '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'}), + 'license_error': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'modified_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'inventoryupdate\', \'app_label\': \'main\'}(class)s_modified+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), + 'overwrite': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'overwrite_vars': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'result_stdout_file': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'result_traceback': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + '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_vars': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'status': ('django.db.models.fields.CharField', [], {'default': "'new'", 'max_length': '20'}) + }, + 'main.inventoryupdatenew': { + 'Meta': {'object_name': 'InventoryUpdateNew', '_ormbases': ['main.UnifiedJob']}, + 'credential': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'inventoryupdatenews'", 'null': 'True', 'blank': 'True', 'to': "orm['main.Credential']"}), + 'inventory_source': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'inventory_updates'", 'to': "orm['main.InventorySourceNew']"}), + '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_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': {'object_name': 'Job'}, + '_result_stdout': ('django.db.models.fields.TextField', [], {'default': "''", 'db_column': "'result_stdout'", 'blank': 'True'}), + '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'}), + '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'}), + 'created': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'created_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'job\', \'app_label\': \'main\'}(class)s_created+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), + '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'}), + 'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'extra_vars': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'failed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'forks': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0', 'blank': 'True'}), + 'hosts': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'jobs'", 'blank': 'True', 'through': "orm['main.JobHostSummary']", 'to': "orm['main.Host']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'inventory': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobs'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Inventory']"}), + '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_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'}), + 'launch_type': ('django.db.models.fields.CharField', [], {'default': "'manual'", 'max_length': '20'}), + 'limit': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), + 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'modified_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'job\', \'app_label\': \'main\'}(class)s_modified+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), + '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']"}), + 'result_stdout_file': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'result_traceback': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'status': ('django.db.models.fields.CharField', [], {'default': "'new'", 'max_length': '20'}), + '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'}), + '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', [], {'related_name': "'job_events_as_primary_host'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.Host']", 'blank': 'True', 'null': 'True'}), + 'hosts': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'job_events'", 'blank': 'True', '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'}), + 'new_job': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'new_job_events'", 'null': 'True', 'to': "orm['main.JobNew']"}), + 'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'children'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.JobEvent']", 'blank': 'True', 'null': 'True'}), + 'play': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), + 'role': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), + 'task': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}) + }, + 'main.jobhostsummary': { + 'Meta': {'ordering': "('-pk',)", 'unique_together': "[('job', 'host'), ('new_job', 'host')]", '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', [], {'related_name': "'job_host_summaries'", 'to': "orm['main.Host']"}), + 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'}), + 'new_job': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'new_job_host_summaries'", 'null': 'True', 'to': "orm['main.JobNew']"}), + '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.jobnew': { + 'Meta': {'object_name': 'JobNew', '_ormbases': ['main.UnifiedJob']}, + 'cloud_credential': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobnews_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': "'jobnews'", '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'}), + 'forks': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0', 'blank': 'True'}), + 'hosts': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'jobnews'", 'blank': 'True', 'through': "orm['main.JobHostSummary']", 'to': "orm['main.Host']"}), + 'inventory': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobnews'", '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.JobTemplateNew']", '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.ProjectNew']"}), + 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.jobtemplate': { + 'Meta': {'object_name': 'JobTemplate'}, + 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + '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'}), + 'created': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'created_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'jobtemplate\', \'app_label\': \'main\'}(class)s_created+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), + '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'}), + 'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'extra_vars': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'forks': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0', 'blank': 'True'}), + 'host_config_key': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': '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'}), + 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'modified_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'jobtemplate\', \'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'}), + 'playbook': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024'}), + 'project': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'job_templates'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Project']"}), + 'verbosity': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0', 'blank': 'True'}) + }, + 'main.jobtemplatenew': { + 'Meta': {'object_name': 'JobTemplateNew', '_ormbases': ['main.UnifiedJobTemplate']}, + 'cloud_credential': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobtemplatenews_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': "'jobtemplatenews'", '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'}), + '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': "'jobtemplatenews'", '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': "'job_templates'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.ProjectNew']"}), + 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': {'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'}), + 'new_projects': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'organizations'", 'blank': 'True', 'to': "orm['main.ProjectNew']"}), + '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'}), + 'new_project': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'permissions'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.ProjectNew']"}), + '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': {'object_name': 'Project'}, + '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\': \'project\', \'app_label\': \'main\'}(class)s_created+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), + 'credential': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'projects'", 'null': 'True', 'blank': 'True', 'to': "orm['main.Credential']"}), + 'current_update': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'project_as_current_update+'", 'null': 'True', 'to': "orm['main.ProjectUpdate']"}), + 'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_update': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'project_as_last_update+'", 'null': 'True', 'to': "orm['main.ProjectUpdate']"}), + 'last_update_failed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_updated': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}), + 'local_path': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'blank': 'True'}), + 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'modified_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'project\', \'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'}), + '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'}), + 'status': ('django.db.models.fields.CharField', [], {'default': "'ok'", 'max_length': '32', 'null': 'True'}) + }, + 'main.projectnew': { + 'Meta': {'object_name': 'ProjectNew', '_ormbases': ['main.UnifiedJobTemplate']}, + 'credential': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'projectnews'", 'null': 'True', 'blank': 'True', 'to': "orm['main.Credential']"}), + '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'}, + '_result_stdout': ('django.db.models.fields.TextField', [], {'default': "''", 'db_column': "'result_stdout'", 'blank': 'True'}), + '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\': \'projectupdate\', \'app_label\': \'main\'}(class)s_created+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), + 'credential': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'projectupdates'", 'null': 'True', 'blank': 'True', 'to': "orm['main.Credential']"}), + 'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'failed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 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'}), + 'local_path': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'blank': 'True'}), + 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'modified_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'projectupdate\', \'app_label\': \'main\'}(class)s_modified+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), + 'project': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'project_updates'", 'to': "orm['main.Project']"}), + 'result_stdout_file': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'result_traceback': ('django.db.models.fields.TextField', [], {'default': "''", '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_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'}), + 'status': ('django.db.models.fields.CharField', [], {'default': "'new'", 'max_length': '20'}) + }, + 'main.projectupdatenew': { + 'Meta': {'object_name': 'ProjectUpdateNew', '_ormbases': ['main.UnifiedJob']}, + 'credential': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'projectupdatenews'", 'null': 'True', 'blank': 'True', 'to': "orm['main.Credential']"}), + '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.ProjectNew']"}), + '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': {'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', [], {}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'job_template': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'schedules'", 'to': "orm['main.UnifiedJobTemplate']"}), + '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'}), + 'rrule': ('django.db.models.fields.CharField', [], {'max_length': '255'}) + }, + 'main.team': { + 'Meta': {'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'}), + 'new_projects': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'teams'", 'blank': 'True', 'to': "orm['main.ProjectNew']"}), + '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']"}), + 'depends_on': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'depends_on_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'}), + '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']"}), + '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'}), + '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', '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', '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', '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'}), + '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'}) + }, + u'taggit.tag': { + 'Meta': {'object_name': 'Tag'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'}), + 'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '100'}) + }, + u'taggit.taggeditem': { + 'Meta': {'object_name': 'TaggedItem'}, + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'taggit_taggeditem_tagged_items'", 'to': u"orm['contenttypes.ContentType']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'object_id': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'}), + 'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'taggit_taggeditem_items'", 'to': u"orm['taggit.Tag']"}) + } + } + + complete_apps = ['main'] \ No newline at end of file diff --git a/awx/main/migrations/0035_v148_changes.py b/awx/main/migrations/0035_v148_changes.py new file mode 100644 index 0000000000..9629ae38d0 --- /dev/null +++ b/awx/main/migrations/0035_v148_changes.py @@ -0,0 +1,785 @@ +# -*- coding: utf-8 -*- +from south.utils import datetime_utils as datetime +from south.db import db +from south.v2 import DataMigration +from django.db import models + +class Migration(DataMigration): + + def _get_dict_from_primordial_model(self, instance): + return { + 'description': instance.description, + 'created': instance.created, + 'modified': instance.modified, + 'created_by': instance.created_by, + 'modified_by': instance.modified_by, + 'active': instance.active, + 'old_pk': instance.pk, + } + + def _get_dict_from_common_model(self, instance): + d = self._get_dict_from_primordial_model(instance) + if hasattr(instance, 'name'): + d['name'] = instance.name + else: + d['name'] = u'%s-%s' % (instance._meta.verbose_name, instance.pk) + return d + + def _get_dict_from_common_task_model(self, instance): + d = self._get_dict_from_primordial_model(instance) + td = instance.modified - instance.created + elapsed = (td.microseconds + (td.seconds + td.days * 24 * 3600) * 10**6) / (10**6 * 1.0) + d.update({ + 'launch_type': getattr(instance, 'launch_type', 'manual'), + 'cancel_flag': instance.cancel_flag, + 'status': instance.status, + 'failed': instance.failed, + 'started': instance.created, + 'finished': instance.modified, + 'elapsed': elapsed, + 'job_args': instance.job_args, + 'job_env': instance.job_env, + 'result_stdout_text': instance._result_stdout, + 'result_stdout_file': instance.result_stdout_file, + 'result_traceback': instance.result_traceback, + 'celery_task_id': instance.celery_task_id, + }) + return d + + def forwards(self, orm): + "Write your forwards methods here." + + # Copy Project old to new. + new_ctype = orm['contenttypes.ContentType'].objects.get(app_label=orm.Project._meta.app_label, model=orm.Project._meta.module_name) + for project in orm.Project.objects.order_by('pk'): + d = self._get_dict_from_common_model(project) + d['polymorphic_ctype_id'] = new_ctype.pk + new_project, created = orm.ProjectNew.objects.get_or_create(old_pk=project.pk, defaults=d) + + # Copy ProjectUpdate old to new. + new_ctype = orm['contenttypes.ContentType'].objects.get(app_label=orm.ProjectUpdate._meta.app_label, model=orm.ProjectUpdate._meta.module_name) + for project_update in orm.ProjectUpdate.objects.order_by('pk'): + d = self._get_dict_from_common_task_model(project_update) + d['project_id'] = orm.ProjectNew.objects.get(old_pk=project_update.project_id).pk + d['polymorphic_ctype_id'] = new_ctype.pk + new_project_update, created = orm.ProjectUpdateNew.objects.get_or_create(old_pk=project_update.pk, defaults=d) + + # Update Project last run. + for project in orm.Project.objects.order_by('pk'): + new_project = orm.ProjectNew.objects.get(old_pk=project.pk) + if project.current_update: + new_project.current_job = orm.ProjectUpdateNew.objects.get(old_pk=project.current_update_id) + if project.last_update: + new_project.last_job = orm.ProjectUpdateNew.objects.get(old_pk=project.last_update_id) + new_project.save() + + # Update Organization projects. + for organization in orm.Organization.objects.order_by('pk'): + for project in organization.projects.order_by('pk'): + new_project = orm.ProjectNew.objects.get(old_pk=project.pk) + organization.new_projects.add(new_project) + + # Update Team projects. + for team in orm.Team.objects.order_by('pk'): + for project in team.projects.order_by('pk'): + new_project = orm.ProjectNew.objects.get(old_pk=project.pk) + team.new_projects.add(new_project) + + # Update Permission project. + for permission in orm.Permission.objects.order_by('pk'): + if not permission.project_id: + continue + new_project = orm.ProjectNew.objects.get(old_pk=permission.project_id) + permission.new_project = new_project + permission.save() + + # Copy InventorySource old to new. + new_ctype = orm['contenttypes.ContentType'].objects.get(app_label=orm.InventorySource._meta.app_label, model=orm.InventorySource._meta.module_name) + for inventory_source in orm.InventorySource.objects.order_by('pk'): + d = self._get_dict_from_common_model(inventory_source) + d['polymorphic_ctype_id'] = new_ctype.pk + new_inventory_source, created = orm.InventorySourceNew.objects.get_or_create(old_pk=inventory_source.pk, defaults=d) + + # Copy InventoryUpdate old to new. + new_ctype = orm['contenttypes.ContentType'].objects.get(app_label=orm.InventoryUpdate._meta.app_label, model=orm.InventoryUpdate._meta.module_name) + for inventory_update in orm.InventoryUpdate.objects.order_by('pk'): + d = self._get_dict_from_common_task_model(inventory_update) + d['inventory_source_id'] = orm.InventorySourceNew.objects.get(old_pk=inventory_update.inventory_source_id).pk + d['polymorphic_ctype_id'] = new_ctype.pk + new_inventory_update, created = orm.InventoryUpdateNew.objects.get_or_create(old_pk=inventory_update.pk, defaults=d) + + # Update InventorySource last run. + for inventory_source in orm.InventorySource.objects.order_by('pk'): + new_inventory_source = orm.InventorySourceNew.objects.get(old_pk=inventory_source.pk) + if inventory_source.current_update: + new_inventory_source.current_job = orm.InventoryUpdateNew.objects.get(old_pk=inventory_source.current_update_id) + if inventory_source.last_update: + new_inventory_source.last_job = orm.InventoryUpdateNew.objects.get(old_pk=inventory_source.last_update_id) + new_inventory_source.save() + + # Update Group inventory_sources. + for group in orm.Group.objects.order_by('pk'): + for inventory_source in group.inventory_sources.order_by('pk'): + new_inventory_source = orm.InventorySourceNew.objects.get(old_pk=inventory_source.pk) + group.new_inventory_sources.add(new_inventory_source) + + # Update Host inventory_sources. + for host in orm.Host.objects.order_by('pk'): + for inventory_source in host.inventory_sources.order_by('pk'): + new_inventory_source = orm.InventorySourceNew.objects.get(old_pk=inventory_source.pk) + host.new_inventory_sources.add(new_inventory_source) + + # Copy JobTemplate old to new. + new_ctype = orm['contenttypes.ContentType'].objects.get(app_label=orm.JobTemplate._meta.app_label, model=orm.JobTemplate._meta.module_name) + for job_template in orm.JobTemplate.objects.order_by('pk'): + d = self._get_dict_from_common_model(job_template) + if job_template.project: + d['project_id'] = orm.ProjectNew.objects.get(old_pk=job_template.project_id).pk + d['polymorphic_ctype_id'] = new_ctype.pk + new_job_template, created = orm.JobTemplateNew.objects.get_or_create(old_pk=job_template.pk, defaults=d) + + # Copy Job old to new. + new_ctype = orm['contenttypes.ContentType'].objects.get(app_label=orm.Job._meta.app_label, model=orm.Job._meta.module_name) + for job in orm.Job.objects.order_by('pk'): + d = self._get_dict_from_common_task_model(job) + if job.project: + d['project_id'] = orm.ProjectNew.objects.get(old_pk=job.project_id).pk + d['polymorphic_ctype_id'] = new_ctype.pk + new_job, created = orm.JobNew.objects.get_or_create(old_pk=job.pk, defaults=d) + + # Update JobHostSummary job. + for job_host_summary in orm.JobHostSummary.objects.order_by('pk'): + new_job = orm.JobNew.objects.get(old_pk=job_host_summary.job_id) + job_host_summary.new_job = new_job + job_host_summary.save() + + # Update JobEvent job. + for job_event in orm.JobEvent.objects.order_by('pk'): + new_job = orm.JobNew.objects.get(old_pk=job_event.job_id) + job_event.new_job = new_job + job_event.save() + + # Update Host last_job. + for host in orm.Host.objects.order_by('pk'): + if not host.last_job: + continue + new_job = orm.JobNew.objects.get(old_pk=host.last_job_id) + host.new_last_job = new_job + host.save() + + # Update ActivityStream + for a_s in orm.ActivityStream.objects.order_by('pk'): + for project in a_s.project.all(): + new_project = orm.ProjectNew.objects.get(old_pk=project.pk) + a_s.new_project.add(new_project) + for project_update in a_s.project_update.all(): + new_project_update = orm.ProjectUpdateNew.objects.get(old_pk=project_update.pk) + a_s.new_project_update.add(new_project_update) + for inventory_source in a_s.inventory_source.all(): + new_inventory_source = orm.InventorySourceNew.objects.get(old_pk=inventory_source.pk) + a_s.new_inventory_source.add(new_inventory_source) + for inventory_update in a_s.inventory_update.all(): + new_inventory_update = orm.InventoryUpdateNew.objects.get(old_pk=inventory_update.pk) + a_s.new_inventory_update.add(new_inventory_update) + for job_template in a_s.job_template.all(): + new_job_template = orm.JobTemplateNew.objects.get(old_pk=job_template.pk) + a_s.new_job_template.add(new_job_template) + for job in a_s.job.all(): + new_job = orm.JobNew.objects.get(old_pk=job.pk) + a_s.new_job.add(new_job) + + def backwards(self, orm): + "Write your backwards methods here." + + # FIXME: Would like to have this, but not required. + + 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', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), + 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', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), + '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'}), + 'new_inventory_source': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.InventorySourceNew']", 'symmetrical': 'False', 'blank': 'True'}), + 'new_inventory_update': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.InventoryUpdateNew']", 'symmetrical': 'False', 'blank': 'True'}), + 'new_job': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.JobNew']", 'symmetrical': 'False', 'blank': 'True'}), + 'new_job_template': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.JobTemplateNew']", 'symmetrical': 'False', 'blank': 'True'}), + 'new_project': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.ProjectNew']", 'symmetrical': 'False', 'blank': 'True'}), + 'new_project_update': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.ProjectUpdateNew']", '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'}), + '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': {'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'}), + 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'}), + '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'}), + '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'}) + }, + 'main.group': { + 'Meta': {'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', [], {'symmetrical': 'False', 'related_name': "'groups'", 'blank': 'True', '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'}), + 'new_inventory_sources': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'groups'", 'blank': 'True', 'to': "orm['main.InventorySourceNew']"}), + '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': {'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', [], {'symmetrical': 'False', 'related_name': "'hosts'", 'blank': 'True', 'to': "orm['main.InventorySource']"}), + 'last_job': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'hosts_as_last_job+'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.Job']", 'blank': 'True', 'null': 'True'}), + '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'}), + 'new_inventory_sources': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'hosts'", 'blank': 'True', 'to': "orm['main.InventorySourceNew']"}), + 'new_last_job': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'hosts_as_last_job+'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.JobNew']", 'blank': 'True', 'null': 'True'}), + 'variables': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}) + }, + 'main.inventory': { + 'Meta': {'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'}, + '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\': \'inventorysource\', \'app_label\': \'main\'}(class)s_created+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), + 'credential': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'inventorysources'", 'null': 'True', 'blank': 'True', 'to': "orm['main.Credential']"}), + 'current_update': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'inventory_source_as_current_update+'", 'null': 'True', 'to': "orm['main.InventoryUpdate']"}), + 'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'group': ('awx.main.fields.AutoOneToOneField', [], {'related_name': "'inventory_source'", 'null': 'True', 'default': 'None', 'to': "orm['main.Group']", 'blank': 'True', 'unique': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'inventory': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'inventory_sources'", 'null': 'True', 'to': "orm['main.Inventory']"}), + 'last_update': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'inventory_source_as_last_update+'", 'null': 'True', 'to': "orm['main.InventoryUpdate']"}), + 'last_update_failed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_updated': ('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\': \'inventorysource\', \'app_label\': \'main\'}(class)s_modified+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), + '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_vars': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'status': ('django.db.models.fields.CharField', [], {'default': "'none'", 'max_length': '32'}), + 'update_cache_timeout': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'update_on_launch': ('django.db.models.fields.BooleanField', [], {'default': 'False'}) + }, + 'main.inventorysourcenew': { + 'Meta': {'object_name': 'InventorySourceNew', '_ormbases': ['main.UnifiedJobTemplate']}, + 'credential': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'inventorysourcenews'", 'null': 'True', 'blank': 'True', 'to': "orm['main.Credential']"}), + 'group': ('awx.main.fields.AutoOneToOneField', [], {'related_name': "'new_inventory_source'", 'null': 'True', 'default': 'None', 'to': "orm['main.Group']", 'blank': 'True', 'unique': 'True'}), + 'inventory': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'new_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_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'}, + '_result_stdout': ('django.db.models.fields.TextField', [], {'default': "''", 'db_column': "'result_stdout'", 'blank': 'True'}), + '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\': \'inventoryupdate\', \'app_label\': \'main\'}(class)s_created+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), + 'credential': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'inventoryupdates'", 'null': 'True', 'blank': 'True', 'to': "orm['main.Credential']"}), + 'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'failed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'inventory_source': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'inventory_updates'", 'to': "orm['main.InventorySource']"}), + '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'}), + 'license_error': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'modified_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'inventoryupdate\', \'app_label\': \'main\'}(class)s_modified+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), + 'overwrite': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'overwrite_vars': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'result_stdout_file': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'result_traceback': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + '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_vars': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'status': ('django.db.models.fields.CharField', [], {'default': "'new'", 'max_length': '20'}) + }, + 'main.inventoryupdatenew': { + 'Meta': {'object_name': 'InventoryUpdateNew', '_ormbases': ['main.UnifiedJob']}, + 'credential': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'inventoryupdatenews'", 'null': 'True', 'blank': 'True', 'to': "orm['main.Credential']"}), + 'inventory_source': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'inventory_updates'", 'to': "orm['main.InventorySourceNew']"}), + '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_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': {'object_name': 'Job'}, + '_result_stdout': ('django.db.models.fields.TextField', [], {'default': "''", 'db_column': "'result_stdout'", 'blank': 'True'}), + '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'}), + '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'}), + 'created': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'created_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'job\', \'app_label\': \'main\'}(class)s_created+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), + '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'}), + 'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'extra_vars': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'failed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'forks': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0', 'blank': 'True'}), + 'hosts': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'jobs'", 'blank': 'True', 'through': "orm['main.JobHostSummary']", 'to': "orm['main.Host']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'inventory': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobs'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Inventory']"}), + '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_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'}), + 'launch_type': ('django.db.models.fields.CharField', [], {'default': "'manual'", 'max_length': '20'}), + 'limit': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), + 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'modified_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'job\', \'app_label\': \'main\'}(class)s_modified+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), + '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']"}), + 'result_stdout_file': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'result_traceback': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'status': ('django.db.models.fields.CharField', [], {'default': "'new'", 'max_length': '20'}), + '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'}), + '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', [], {'related_name': "'job_events_as_primary_host'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.Host']", 'blank': 'True', 'null': 'True'}), + 'hosts': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'job_events'", 'blank': 'True', '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'}), + 'new_job': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'new_job_events'", 'null': 'True', 'to': "orm['main.JobNew']"}), + 'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'children'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.JobEvent']", 'blank': 'True', 'null': 'True'}), + 'play': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), + 'role': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), + 'task': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}) + }, + 'main.jobhostsummary': { + 'Meta': {'ordering': "('-pk',)", 'unique_together': "[('job', 'host'), ('new_job', 'host')]", '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', [], {'related_name': "'job_host_summaries'", 'to': "orm['main.Host']"}), + 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'}), + 'new_job': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'new_job_host_summaries'", 'null': 'True', 'to': "orm['main.JobNew']"}), + '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.jobnew': { + 'Meta': {'object_name': 'JobNew', '_ormbases': ['main.UnifiedJob']}, + 'cloud_credential': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobnews_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': "'jobnews'", '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'}), + 'forks': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0', 'blank': 'True'}), + 'hosts': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'jobnews'", 'blank': 'True', 'through': "orm['main.JobHostSummary']", 'to': "orm['main.Host']"}), + 'inventory': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobnews'", '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.JobTemplateNew']", '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.ProjectNew']"}), + 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.jobtemplate': { + 'Meta': {'object_name': 'JobTemplate'}, + 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + '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'}), + 'created': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'created_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'jobtemplate\', \'app_label\': \'main\'}(class)s_created+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), + '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'}), + 'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'extra_vars': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'forks': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0', 'blank': 'True'}), + 'host_config_key': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': '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'}), + 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'modified_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'jobtemplate\', \'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'}), + 'playbook': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024'}), + 'project': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'job_templates'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Project']"}), + 'verbosity': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0', 'blank': 'True'}) + }, + 'main.jobtemplatenew': { + 'Meta': {'object_name': 'JobTemplateNew', '_ormbases': ['main.UnifiedJobTemplate']}, + 'cloud_credential': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobtemplatenews_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': "'jobtemplatenews'", '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'}), + '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': "'jobtemplatenews'", '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': "'job_templates'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.ProjectNew']"}), + 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': {'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'}), + 'new_projects': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'organizations'", 'blank': 'True', 'to': "orm['main.ProjectNew']"}), + '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'}), + 'new_project': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'permissions'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.ProjectNew']"}), + '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': {'object_name': 'Project'}, + '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\': \'project\', \'app_label\': \'main\'}(class)s_created+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), + 'credential': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'projects'", 'null': 'True', 'blank': 'True', 'to': "orm['main.Credential']"}), + 'current_update': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'project_as_current_update+'", 'null': 'True', 'to': "orm['main.ProjectUpdate']"}), + 'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_update': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'project_as_last_update+'", 'null': 'True', 'to': "orm['main.ProjectUpdate']"}), + 'last_update_failed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_updated': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}), + 'local_path': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'blank': 'True'}), + 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'modified_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'project\', \'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'}), + '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'}), + 'status': ('django.db.models.fields.CharField', [], {'default': "'ok'", 'max_length': '32', 'null': 'True'}) + }, + 'main.projectnew': { + 'Meta': {'object_name': 'ProjectNew', '_ormbases': ['main.UnifiedJobTemplate']}, + 'credential': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'projectnews'", 'null': 'True', 'blank': 'True', 'to': "orm['main.Credential']"}), + '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'}, + '_result_stdout': ('django.db.models.fields.TextField', [], {'default': "''", 'db_column': "'result_stdout'", 'blank': 'True'}), + '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\': \'projectupdate\', \'app_label\': \'main\'}(class)s_created+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), + 'credential': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'projectupdates'", 'null': 'True', 'blank': 'True', 'to': "orm['main.Credential']"}), + 'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'failed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 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'}), + 'local_path': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'blank': 'True'}), + 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'modified_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'projectupdate\', \'app_label\': \'main\'}(class)s_modified+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), + 'project': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'project_updates'", 'to': "orm['main.Project']"}), + 'result_stdout_file': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'result_traceback': ('django.db.models.fields.TextField', [], {'default': "''", '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_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'}), + 'status': ('django.db.models.fields.CharField', [], {'default': "'new'", 'max_length': '20'}) + }, + 'main.projectupdatenew': { + 'Meta': {'object_name': 'ProjectUpdateNew', '_ormbases': ['main.UnifiedJob']}, + 'credential': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'projectupdatenews'", 'null': 'True', 'blank': 'True', 'to': "orm['main.Credential']"}), + '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.ProjectNew']"}), + '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': {'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', [], {}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'job_template': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'schedules'", 'to': "orm['main.UnifiedJobTemplate']"}), + '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'}), + 'rrule': ('django.db.models.fields.CharField', [], {'max_length': '255'}) + }, + 'main.team': { + 'Meta': {'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'}), + 'new_projects': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'teams'", 'blank': 'True', 'to': "orm['main.ProjectNew']"}), + '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']"}), + 'depends_on': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'depends_on_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'}), + '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']"}), + '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'}), + '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', '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', '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', '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'}), + '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'}) + }, + u'taggit.tag': { + 'Meta': {'object_name': 'Tag'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'}), + 'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '100'}) + }, + u'taggit.taggeditem': { + 'Meta': {'object_name': 'TaggedItem'}, + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'taggit_taggeditem_tagged_items'", 'to': u"orm['contenttypes.ContentType']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'object_id': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'}), + 'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'taggit_taggeditem_items'", 'to': u"orm['taggit.Tag']"}) + } + } + + complete_apps = ['main'] + symmetrical = True diff --git a/awx/main/migrations/0036_v148_changes.py b/awx/main/migrations/0036_v148_changes.py new file mode 100644 index 0000000000..2947003bea --- /dev/null +++ b/awx/main/migrations/0036_v148_changes.py @@ -0,0 +1,787 @@ +# -*- 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): + # Removing unique constraint on 'JobHostSummary', fields ['job', 'host'] + db.delete_unique(u'main_jobhostsummary', ['job_id', 'host_id']) + + # Deleting model 'JobTemplate' + db.delete_table(u'main_jobtemplate') + + # Deleting model 'InventorySource' + db.delete_table(u'main_inventorysource') + + # Deleting model 'Project' + db.delete_table(u'main_project') + + # Deleting model 'ProjectUpdate' + db.delete_table(u'main_projectupdate') + + # Deleting model 'InventoryUpdate' + db.delete_table(u'main_inventoryupdate') + + # Deleting model 'Job' + db.delete_table(u'main_job') + + # Deleting field 'Host.last_job' + db.delete_column(u'main_host', 'last_job_id') + + # Removing M2M table for field inventory_sources on 'Host' + db.delete_table(db.shorten_name(u'main_host_inventory_sources')) + + # Removing M2M table for field projects on 'Organization' + db.delete_table(db.shorten_name(u'main_organization_projects')) + + # Removing M2M table for field projects on 'Team' + db.delete_table(db.shorten_name(u'main_team_projects')) + + # Deleting field 'Permission.project' + db.delete_column(u'main_permission', 'project_id') + + # Deleting field 'JobHostSummary.job' + db.delete_column(u'main_jobhostsummary', 'job_id') + + # Changing field 'JobHostSummary.new_job' + db.alter_column(u'main_jobhostsummary', 'new_job_id', self.gf('django.db.models.fields.related.ForeignKey')(default=None, to=orm['main.JobNew'])) + + # Removing M2M table for field inventory_sources on 'Group' + db.delete_table(db.shorten_name(u'main_group_inventory_sources')) + + # Deleting field 'JobEvent.job' + db.delete_column(u'main_jobevent', 'job_id') + + # Changing field 'JobEvent.new_job' + db.alter_column(u'main_jobevent', 'new_job_id', self.gf('django.db.models.fields.related.ForeignKey')(default=None, to=orm['main.JobNew'])) + + # Removing M2M table for field job_template on 'ActivityStream' + db.delete_table(db.shorten_name(u'main_activitystream_job_template')) + + # Removing M2M table for field inventory_update on 'ActivityStream' + db.delete_table(db.shorten_name(u'main_activitystream_inventory_update')) + + # Removing M2M table for field job on 'ActivityStream' + db.delete_table(db.shorten_name(u'main_activitystream_job')) + + # Removing M2M table for field project_update on 'ActivityStream' + db.delete_table(db.shorten_name(u'main_activitystream_project_update')) + + # Removing M2M table for field inventory_source on 'ActivityStream' + db.delete_table(db.shorten_name(u'main_activitystream_inventory_source')) + + # Removing M2M table for field project on 'ActivityStream' + db.delete_table(db.shorten_name(u'main_activitystream_project')) + + + def backwards(self, orm): + # Adding model 'JobTemplate' + db.create_table(u'main_jobtemplate', ( + ('credential', self.gf('django.db.models.fields.related.ForeignKey')(related_name='jobtemplates', on_delete=models.SET_NULL, default=None, to=orm['main.Credential'], blank=True, null=True)), + ('modified_by', self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name="{'class': 'jobtemplate', 'app_label': 'main'}(class)s_modified+", null=True, on_delete=models.SET_NULL, to=orm['auth.User'])), + ('description', self.gf('django.db.models.fields.TextField')(default='', blank=True)), + ('created', self.gf('django.db.models.fields.DateTimeField')(default=None)), + ('extra_vars', self.gf('django.db.models.fields.TextField')(default='', blank=True)), + ('verbosity', self.gf('django.db.models.fields.PositiveIntegerField')(default=0, blank=True)), + ('job_tags', self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True)), + ('job_type', self.gf('django.db.models.fields.CharField')(max_length=64)), + ('modified', self.gf('django.db.models.fields.DateTimeField')(default=None)), + ('created_by', self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name="{'class': 'jobtemplate', 'app_label': 'main'}(class)s_created+", null=True, on_delete=models.SET_NULL, to=orm['auth.User'])), + (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('project', self.gf('django.db.models.fields.related.ForeignKey')(related_name='job_templates', null=True, on_delete=models.SET_NULL, to=orm['main.Project'])), + ('host_config_key', self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True)), + ('limit', self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True)), + ('inventory', self.gf('django.db.models.fields.related.ForeignKey')(related_name='jobtemplates', null=True, on_delete=models.SET_NULL, to=orm['main.Inventory'])), + ('active', self.gf('django.db.models.fields.BooleanField')(default=True)), + ('forks', self.gf('django.db.models.fields.PositiveIntegerField')(default=0, blank=True)), + ('playbook', self.gf('django.db.models.fields.CharField')(default='', max_length=1024)), + ('cloud_credential', self.gf('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)), + ('name', self.gf('django.db.models.fields.CharField')(max_length=512, unique=True)), + )) + db.send_create_signal('main', ['JobTemplate']) + + # Adding model 'InventorySource' + db.create_table(u'main_inventorysource', ( + ('last_updated', self.gf('django.db.models.fields.DateTimeField')(default=None, null=True)), + ('source_regions', self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True)), + ('current_update', self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name='inventory_source_as_current_update+', null=True, to=orm['main.InventoryUpdate'])), + (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('overwrite', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('source_vars', self.gf('django.db.models.fields.TextField')(default='', blank=True)), + ('group', self.gf('awx.main.fields.AutoOneToOneField')(related_name='inventory_source', null=True, default=None, to=orm['main.Group'], blank=True, unique=True)), + ('last_update_failed', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('created_by', self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name="{'class': 'inventorysource', 'app_label': 'main'}(class)s_created+", null=True, on_delete=models.SET_NULL, to=orm['auth.User'])), + ('last_update', self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name='inventory_source_as_last_update+', null=True, to=orm['main.InventoryUpdate'])), + ('source', self.gf('django.db.models.fields.CharField')(default='', max_length=32, blank=True)), + ('inventory', self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name='inventory_sources', null=True, to=orm['main.Inventory'])), + ('update_cache_timeout', self.gf('django.db.models.fields.PositiveIntegerField')(default=0)), + ('status', self.gf('django.db.models.fields.CharField')(default='none', max_length=32)), + ('credential', self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name='inventorysources', null=True, to=orm['main.Credential'], blank=True)), + ('description', self.gf('django.db.models.fields.TextField')(default='', blank=True)), + ('overwrite_vars', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('active', self.gf('django.db.models.fields.BooleanField')(default=True)), + ('modified_by', self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name="{'class': 'inventorysource', 'app_label': 'main'}(class)s_modified+", null=True, on_delete=models.SET_NULL, to=orm['auth.User'])), + ('update_on_launch', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('created', self.gf('django.db.models.fields.DateTimeField')(default=None)), + ('source_path', self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True)), + ('modified', self.gf('django.db.models.fields.DateTimeField')(default=None)), + )) + db.send_create_signal('main', ['InventorySource']) + + # Adding model 'Project' + db.create_table(u'main_project', ( + ('scm_branch', self.gf('django.db.models.fields.CharField')(default='', max_length=256, blank=True)), + ('scm_update_cache_timeout', self.gf('django.db.models.fields.PositiveIntegerField')(default=0)), + ('scm_clean', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('scm_delete_on_update', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('current_update', self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name='project_as_current_update+', null=True, to=orm['main.ProjectUpdate'])), + ('last_updated', self.gf('django.db.models.fields.DateTimeField')(default=None, null=True)), + (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('modified_by', self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name="{'class': 'project', 'app_label': 'main'}(class)s_modified+", null=True, on_delete=models.SET_NULL, to=orm['auth.User'])), + ('last_update_failed', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('created_by', self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name="{'class': 'project', 'app_label': 'main'}(class)s_created+", null=True, on_delete=models.SET_NULL, to=orm['auth.User'])), + ('last_update', self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name='project_as_last_update+', null=True, to=orm['main.ProjectUpdate'])), + ('local_path', self.gf('django.db.models.fields.CharField')(max_length=1024, blank=True)), + ('scm_delete_on_next_update', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('status', self.gf('django.db.models.fields.CharField')(default='ok', max_length=32, null=True)), + ('credential', self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name='projects', null=True, to=orm['main.Credential'], blank=True)), + ('description', self.gf('django.db.models.fields.TextField')(default='', blank=True)), + ('scm_type', self.gf('django.db.models.fields.CharField')(default='', max_length=8, blank=True)), + ('scm_update_on_launch', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('active', self.gf('django.db.models.fields.BooleanField')(default=True)), + ('name', self.gf('django.db.models.fields.CharField')(max_length=512, unique=True)), + ('created', self.gf('django.db.models.fields.DateTimeField')(default=None)), + ('modified', self.gf('django.db.models.fields.DateTimeField')(default=None)), + ('scm_url', self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True)), + )) + db.send_create_signal('main', ['Project']) + + # Adding model 'ProjectUpdate' + db.create_table(u'main_projectupdate', ( + ('cancel_flag', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('scm_branch', self.gf('django.db.models.fields.CharField')(default='', max_length=256, blank=True)), + ('scm_clean', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('scm_delete_on_update', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('celery_task_id', self.gf('django.db.models.fields.CharField')(default='', max_length=100, blank=True)), + (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('modified_by', self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name="{'class': 'projectupdate', 'app_label': 'main'}(class)s_modified+", null=True, on_delete=models.SET_NULL, to=orm['auth.User'])), + ('job_cwd', self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True)), + ('created_by', self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name="{'class': 'projectupdate', 'app_label': 'main'}(class)s_created+", null=True, on_delete=models.SET_NULL, to=orm['auth.User'])), + ('failed', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('local_path', self.gf('django.db.models.fields.CharField')(max_length=1024, blank=True)), + ('status', self.gf('django.db.models.fields.CharField')(default='new', max_length=20)), + ('credential', self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name='projectupdates', null=True, to=orm['main.Credential'], blank=True)), + ('description', self.gf('django.db.models.fields.TextField')(default='', blank=True)), + ('result_traceback', self.gf('django.db.models.fields.TextField')(default='', blank=True)), + ('scm_type', self.gf('django.db.models.fields.CharField')(default='', max_length=8, blank=True)), + ('job_env', self.gf('jsonfield.fields.JSONField')(default={}, blank=True)), + ('active', self.gf('django.db.models.fields.BooleanField')(default=True)), + ('result_stdout_file', self.gf('django.db.models.fields.TextField')(default='', blank=True)), + ('created', self.gf('django.db.models.fields.DateTimeField')(default=None)), + ('job_args', self.gf('django.db.models.fields.TextField')(default='', blank=True)), + ('modified', self.gf('django.db.models.fields.DateTimeField')(default=None)), + ('scm_url', self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True)), + ('project', self.gf('django.db.models.fields.related.ForeignKey')(related_name='project_updates', to=orm['main.Project'])), + ('_result_stdout', self.gf('django.db.models.fields.TextField')(default='', db_column='result_stdout', blank=True)), + )) + db.send_create_signal('main', ['ProjectUpdate']) + + # Adding model 'InventoryUpdate' + db.create_table(u'main_inventoryupdate', ( + ('cancel_flag', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('source_regions', self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True)), + ('license_error', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('celery_task_id', self.gf('django.db.models.fields.CharField')(default='', max_length=100, blank=True)), + (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('overwrite', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('source_vars', self.gf('django.db.models.fields.TextField')(default='', blank=True)), + ('modified_by', self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name="{'class': 'inventoryupdate', 'app_label': 'main'}(class)s_modified+", null=True, on_delete=models.SET_NULL, to=orm['auth.User'])), + ('job_cwd', self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True)), + ('source', self.gf('django.db.models.fields.CharField')(default='', max_length=32, blank=True)), + ('created_by', self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name="{'class': 'inventoryupdate', 'app_label': 'main'}(class)s_created+", null=True, on_delete=models.SET_NULL, to=orm['auth.User'])), + ('failed', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('status', self.gf('django.db.models.fields.CharField')(default='new', max_length=20)), + ('credential', self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name='inventoryupdates', null=True, to=orm['main.Credential'], blank=True)), + ('description', self.gf('django.db.models.fields.TextField')(default='', blank=True)), + ('overwrite_vars', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('result_traceback', self.gf('django.db.models.fields.TextField')(default='', blank=True)), + ('job_env', self.gf('jsonfield.fields.JSONField')(default={}, blank=True)), + ('active', self.gf('django.db.models.fields.BooleanField')(default=True)), + ('result_stdout_file', self.gf('django.db.models.fields.TextField')(default='', blank=True)), + ('inventory_source', self.gf('django.db.models.fields.related.ForeignKey')(related_name='inventory_updates', to=orm['main.InventorySource'])), + ('created', self.gf('django.db.models.fields.DateTimeField')(default=None)), + ('job_args', self.gf('django.db.models.fields.TextField')(default='', blank=True)), + ('source_path', self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True)), + ('modified', self.gf('django.db.models.fields.DateTimeField')(default=None)), + ('_result_stdout', self.gf('django.db.models.fields.TextField')(default='', db_column='result_stdout', blank=True)), + )) + db.send_create_signal('main', ['InventoryUpdate']) + + # Adding model 'Job' + db.create_table(u'main_job', ( + ('cancel_flag', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('credential', self.gf('django.db.models.fields.related.ForeignKey')(related_name='jobs', on_delete=models.SET_NULL, default=None, to=orm['main.Credential'], blank=True, null=True)), + ('description', self.gf('django.db.models.fields.TextField')(default='', blank=True)), + ('result_traceback', self.gf('django.db.models.fields.TextField')(default='', blank=True)), + ('job_type', self.gf('django.db.models.fields.CharField')(max_length=64)), + ('job_tags', self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True)), + ('celery_task_id', self.gf('django.db.models.fields.CharField')(default='', max_length=100, blank=True)), + ('playbook', self.gf('django.db.models.fields.CharField')(default='', max_length=1024)), + ('job_env', self.gf('jsonfield.fields.JSONField')(default={}, blank=True)), + ('active', self.gf('django.db.models.fields.BooleanField')(default=True)), + ('result_stdout_file', self.gf('django.db.models.fields.TextField')(default='', blank=True)), + (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('status', self.gf('django.db.models.fields.CharField')(default='new', max_length=20)), + ('modified_by', self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name="{'class': 'job', 'app_label': 'main'}(class)s_modified+", null=True, on_delete=models.SET_NULL, to=orm['auth.User'])), + ('job_cwd', self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True)), + ('job_template', self.gf('django.db.models.fields.related.ForeignKey')(related_name='jobs', on_delete=models.SET_NULL, default=None, to=orm['main.JobTemplate'], blank=True, null=True)), + ('created', self.gf('django.db.models.fields.DateTimeField')(default=None)), + ('extra_vars', self.gf('django.db.models.fields.TextField')(default='', blank=True)), + ('verbosity', self.gf('django.db.models.fields.PositiveIntegerField')(default=0, blank=True)), + ('job_args', self.gf('django.db.models.fields.TextField')(default='', blank=True)), + ('modified', self.gf('django.db.models.fields.DateTimeField')(default=None)), + ('created_by', self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name="{'class': 'job', 'app_label': 'main'}(class)s_created+", null=True, on_delete=models.SET_NULL, to=orm['auth.User'])), + ('project', self.gf('django.db.models.fields.related.ForeignKey')(related_name='jobs', null=True, on_delete=models.SET_NULL, to=orm['main.Project'])), + ('failed', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('inventory', self.gf('django.db.models.fields.related.ForeignKey')(related_name='jobs', null=True, on_delete=models.SET_NULL, to=orm['main.Inventory'])), + ('_result_stdout', self.gf('django.db.models.fields.TextField')(default='', db_column='result_stdout', blank=True)), + ('limit', self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True)), + ('forks', self.gf('django.db.models.fields.PositiveIntegerField')(default=0, blank=True)), + ('cloud_credential', self.gf('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)), + ('launch_type', self.gf('django.db.models.fields.CharField')(default='manual', max_length=20)), + )) + db.send_create_signal('main', ['Job']) + + # Adding field 'Host.last_job' + db.add_column(u'main_host', 'last_job', + self.gf('django.db.models.fields.related.ForeignKey')(related_name='hosts_as_last_job+', on_delete=models.SET_NULL, default=None, to=orm['main.Job'], blank=True, null=True), + keep_default=False) + + # Adding M2M table for field inventory_sources on 'Host' + m2m_table_name = db.shorten_name(u'main_host_inventory_sources') + db.create_table(m2m_table_name, ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('host', models.ForeignKey(orm['main.host'], null=False)), + ('inventorysource', models.ForeignKey(orm['main.inventorysource'], null=False)) + )) + db.create_unique(m2m_table_name, ['host_id', 'inventorysource_id']) + + # Adding M2M table for field projects on 'Organization' + m2m_table_name = db.shorten_name(u'main_organization_projects') + db.create_table(m2m_table_name, ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('organization', models.ForeignKey(orm['main.organization'], null=False)), + ('project', models.ForeignKey(orm['main.project'], null=False)) + )) + db.create_unique(m2m_table_name, ['organization_id', 'project_id']) + + # Adding M2M table for field projects on 'Team' + m2m_table_name = db.shorten_name(u'main_team_projects') + db.create_table(m2m_table_name, ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('team', models.ForeignKey(orm['main.team'], null=False)), + ('project', models.ForeignKey(orm['main.project'], null=False)) + )) + db.create_unique(m2m_table_name, ['team_id', 'project_id']) + + # Adding field 'Permission.project' + db.add_column(u'main_permission', 'project', + self.gf('django.db.models.fields.related.ForeignKey')(related_name='permissions', null=True, to=orm['main.Project'], on_delete=models.SET_NULL, blank=True), + keep_default=False) + + # Adding field 'JobHostSummary.job' + db.add_column(u'main_jobhostsummary', 'job', + self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name='job_host_summaries', to=orm['main.Job']), + keep_default=False) + + + # Changing field 'JobHostSummary.new_job' + db.alter_column(u'main_jobhostsummary', 'new_job_id', self.gf('django.db.models.fields.related.ForeignKey')(null=True, to=orm['main.JobNew'])) + # Adding unique constraint on 'JobHostSummary', fields ['job', 'host'] + db.create_unique(u'main_jobhostsummary', ['job_id', 'host_id']) + + # Adding M2M table for field inventory_sources on 'Group' + m2m_table_name = db.shorten_name(u'main_group_inventory_sources') + db.create_table(m2m_table_name, ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('group', models.ForeignKey(orm['main.group'], null=False)), + ('inventorysource', models.ForeignKey(orm['main.inventorysource'], null=False)) + )) + db.create_unique(m2m_table_name, ['group_id', 'inventorysource_id']) + + # Adding field 'JobEvent.job' + db.add_column(u'main_jobevent', 'job', + self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name='job_events', to=orm['main.Job']), + keep_default=False) + + + # Changing field 'JobEvent.new_job' + db.alter_column(u'main_jobevent', 'new_job_id', self.gf('django.db.models.fields.related.ForeignKey')(null=True, to=orm['main.JobNew'])) + # Adding M2M table for field job_template on 'ActivityStream' + m2m_table_name = db.shorten_name(u'main_activitystream_job_template') + db.create_table(m2m_table_name, ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('activitystream', models.ForeignKey(orm['main.activitystream'], null=False)), + ('jobtemplate', models.ForeignKey(orm['main.jobtemplate'], null=False)) + )) + db.create_unique(m2m_table_name, ['activitystream_id', 'jobtemplate_id']) + + # Adding M2M table for field inventory_update on 'ActivityStream' + m2m_table_name = db.shorten_name(u'main_activitystream_inventory_update') + db.create_table(m2m_table_name, ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('activitystream', models.ForeignKey(orm['main.activitystream'], null=False)), + ('inventoryupdate', models.ForeignKey(orm['main.inventoryupdate'], null=False)) + )) + db.create_unique(m2m_table_name, ['activitystream_id', 'inventoryupdate_id']) + + # Adding M2M table for field job on 'ActivityStream' + m2m_table_name = db.shorten_name(u'main_activitystream_job') + db.create_table(m2m_table_name, ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('activitystream', models.ForeignKey(orm['main.activitystream'], null=False)), + ('job', models.ForeignKey(orm['main.job'], null=False)) + )) + db.create_unique(m2m_table_name, ['activitystream_id', 'job_id']) + + # Adding M2M table for field project_update on 'ActivityStream' + m2m_table_name = db.shorten_name(u'main_activitystream_project_update') + db.create_table(m2m_table_name, ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('activitystream', models.ForeignKey(orm['main.activitystream'], null=False)), + ('projectupdate', models.ForeignKey(orm['main.projectupdate'], null=False)) + )) + db.create_unique(m2m_table_name, ['activitystream_id', 'projectupdate_id']) + + # Adding M2M table for field inventory_source on 'ActivityStream' + m2m_table_name = db.shorten_name(u'main_activitystream_inventory_source') + db.create_table(m2m_table_name, ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('activitystream', models.ForeignKey(orm['main.activitystream'], null=False)), + ('inventorysource', models.ForeignKey(orm['main.inventorysource'], null=False)) + )) + db.create_unique(m2m_table_name, ['activitystream_id', 'inventorysource_id']) + + # Adding M2M table for field project on 'ActivityStream' + m2m_table_name = db.shorten_name(u'main_activitystream_project') + db.create_table(m2m_table_name, ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('activitystream', models.ForeignKey(orm['main.activitystream'], null=False)), + ('project', models.ForeignKey(orm['main.project'], null=False)) + )) + db.create_unique(m2m_table_name, ['activitystream_id', 'project_id']) + + + 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', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), + 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', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), + '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'}), + 'new_inventory_source': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.InventorySourceNew']", 'symmetrical': 'False', 'blank': 'True'}), + 'new_inventory_update': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.InventoryUpdateNew']", 'symmetrical': 'False', 'blank': 'True'}), + 'new_job': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.JobNew']", 'symmetrical': 'False', 'blank': 'True'}), + 'new_job_template': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.JobTemplateNew']", 'symmetrical': 'False', 'blank': 'True'}), + 'new_project': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.ProjectNew']", 'symmetrical': 'False', 'blank': 'True'}), + 'new_project_update': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.ProjectUpdateNew']", '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'}), + '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': {'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'}), + 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'}), + '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'}), + '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'}) + }, + 'main.group': { + 'Meta': {'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']"}), + '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'}), + 'new_inventory_sources': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'groups'", 'blank': 'True', 'to': "orm['main.InventorySourceNew']"}), + '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': {'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']"}), + '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'}), + 'new_inventory_sources': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'hosts'", 'blank': 'True', 'to': "orm['main.InventorySourceNew']"}), + 'new_last_job': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'hosts_as_last_job+'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.JobNew']", 'blank': 'True', 'null': 'True'}), + 'variables': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}) + }, + 'main.inventory': { + 'Meta': {'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.inventorysourcenew': { + 'Meta': {'object_name': 'InventorySourceNew', '_ormbases': ['main.UnifiedJobTemplate']}, + 'credential': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'inventorysourcenews'", 'null': 'True', 'blank': 'True', 'to': "orm['main.Credential']"}), + 'group': ('awx.main.fields.AutoOneToOneField', [], {'related_name': "'new_inventory_source'", 'null': 'True', 'default': 'None', 'to': "orm['main.Group']", 'blank': 'True', 'unique': 'True'}), + 'inventory': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'new_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_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.inventoryupdatenew': { + 'Meta': {'object_name': 'InventoryUpdateNew', '_ormbases': ['main.UnifiedJob']}, + 'credential': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'inventoryupdatenews'", 'null': 'True', 'blank': 'True', 'to': "orm['main.Credential']"}), + 'inventory_source': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'inventory_updates'", 'to': "orm['main.InventorySourceNew']"}), + '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_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.jobevent': { + 'Meta': {'ordering': "('pk',)", 'object_name': 'JobEvent'}, + 'changed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + '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', [], {'related_name': "'job_events_as_primary_host'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.Host']", 'blank': 'True', 'null': 'True'}), + 'hosts': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'job_events'", 'blank': 'True', 'to': "orm['main.Host']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'new_job': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'new_job_events'", 'to': "orm['main.JobNew']"}), + 'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'children'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.JobEvent']", 'blank': 'True', 'null': 'True'}), + 'play': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), + 'role': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), + 'task': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}) + }, + 'main.jobhostsummary': { + 'Meta': {'ordering': "('-pk',)", 'unique_together': "[('new_job', 'host')]", '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', [], {'related_name': "'job_host_summaries'", 'to': "orm['main.Host']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'new_job': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'new_job_host_summaries'", 'to': "orm['main.JobNew']"}), + '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.jobnew': { + 'Meta': {'object_name': 'JobNew', '_ormbases': ['main.UnifiedJob']}, + 'cloud_credential': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobnews_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': "'jobnews'", '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'}), + 'forks': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0', 'blank': 'True'}), + 'hosts': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'jobnews'", 'blank': 'True', 'through': "orm['main.JobHostSummary']", 'to': "orm['main.Host']"}), + 'inventory': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobnews'", '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.JobTemplateNew']", '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.ProjectNew']"}), + 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.jobtemplatenew': { + 'Meta': {'object_name': 'JobTemplateNew', '_ormbases': ['main.UnifiedJobTemplate']}, + 'cloud_credential': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobtemplatenews_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': "'jobtemplatenews'", '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'}), + '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': "'jobtemplatenews'", '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': "'job_templates'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.ProjectNew']"}), + 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': {'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'}), + 'new_projects': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'organizations'", 'blank': 'True', 'to': "orm['main.ProjectNew']"}), + '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'}), + 'new_project': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'permissions'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.ProjectNew']"}), + 'permission_type': ('django.db.models.fields.CharField', [], {'max_length': '64'}), + '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.projectnew': { + 'Meta': {'object_name': 'ProjectNew', '_ormbases': ['main.UnifiedJobTemplate']}, + 'credential': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'projectnews'", 'null': 'True', 'blank': 'True', 'to': "orm['main.Credential']"}), + '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.projectupdatenew': { + 'Meta': {'object_name': 'ProjectUpdateNew', '_ormbases': ['main.UnifiedJob']}, + 'credential': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'projectupdatenews'", 'null': 'True', 'blank': 'True', 'to': "orm['main.Credential']"}), + '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.ProjectNew']"}), + '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': {'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', [], {}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'job_template': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'schedules'", 'to': "orm['main.UnifiedJobTemplate']"}), + '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'}), + 'rrule': ('django.db.models.fields.CharField', [], {'max_length': '255'}) + }, + 'main.team': { + 'Meta': {'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'}), + 'new_projects': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'teams'", 'blank': 'True', 'to': "orm['main.ProjectNew']"}), + 'organization': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'teams'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Organization']"}), + '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']"}), + 'depends_on': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'depends_on_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'}), + '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']"}), + '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'}), + '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', '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', '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', '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'}), + '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'}) + }, + u'taggit.tag': { + 'Meta': {'object_name': 'Tag'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'}), + 'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '100'}) + }, + u'taggit.taggeditem': { + 'Meta': {'object_name': 'TaggedItem'}, + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'taggit_taggeditem_tagged_items'", 'to': u"orm['contenttypes.ContentType']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'object_id': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'}), + 'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'taggit_taggeditem_items'", 'to': u"orm['taggit.Tag']"}) + } + } + + complete_apps = ['main'] \ No newline at end of file diff --git a/awx/main/migrations/0037_v148_changes.py b/awx/main/migrations/0037_v148_changes.py new file mode 100644 index 0000000000..40cb63e232 --- /dev/null +++ b/awx/main/migrations/0037_v148_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): + ''' + Rename tables to be consistent with model names. + ''' + + def forwards(self, orm): + db.rename_table(u'main_projectnew', 'main_project') + db.rename_table(u'main_projectupdatenew', 'main_projectupdate') + db.rename_table(u'main_inventorysourcenew', 'main_inventorysource') + db.rename_table(u'main_inventoryupdatenew', 'main_inventoryupdate') + db.rename_table(u'main_jobtemplatenew', 'main_jobtemplate') + db.rename_table(u'main_jobnew', 'main_job') + + db.rename_table(db.shorten_name(u'main_team_new_projects'), db.shorten_name(u'main_team_projects')) + db.rename_table(db.shorten_name(u'main_organization_new_projects'), db.shorten_name(u'main_organization_projects')) + db.rename_column(u'main_permission', 'new_project_id', 'project_id') + + db.rename_column(u'main_host', 'new_last_job_id', 'last_job_id') + db.rename_table(db.shorten_name(u'main_host_new_inventory_sources'), db.shorten_name(u'main_host_inventory_sources')) + db.rename_table(db.shorten_name(u'main_group_new_inventory_sources'), db.shorten_name(u'main_group_inventory_sources')) + + db.rename_column(u'main_jobhostsummary', 'new_job_id', 'job_id') + db.rename_column(u'main_jobevent', 'new_job_id', 'job_id') + + db.rename_table(db.shorten_name(u'main_activitystream_new_project'), db.shorten_name(u'main_activitystream_project')) + db.rename_table(db.shorten_name(u'main_activitystream_new_project_update'), db.shorten_name(u'main_activitystream_project_update')) + db.rename_table(db.shorten_name(u'main_activitystream_new_inventory_source'), db.shorten_name(u'main_activitystream_inventory_source')) + db.rename_table(db.shorten_name(u'main_activitystream_new_inventory_update'), db.shorten_name(u'main_activitystream_inventory_update')) + db.rename_table(db.shorten_name(u'main_activitystream_new_job_template'), db.shorten_name(u'main_activitystream_job_template')) + db.rename_table(db.shorten_name(u'main_activitystream_new_job'), db.shorten_name(u'main_activitystream_job')) + + def backwards(self, orm): + db.rename_table(db.shorten_name(u'main_activitystream_job'), db.shorten_name(u'main_activitystream_new_job')) + db.rename_table(db.shorten_name(u'main_activitystream_job_template'), db.shorten_name(u'main_activitystream_new_job_template')) + db.rename_table(db.shorten_name(u'main_activitystream_inventory_update'), db.shorten_name(u'main_activitystream_new_inventory_update')) + db.rename_table(db.shorten_name(u'main_activitystream_inventory_source'), db.shorten_name(u'main_activitystream_new_inventory_source')) + db.rename_table(db.shorten_name(u'main_activitystream_project_update'), db.shorten_name(u'main_activitystream_new_project_update')) + db.rename_table(db.shorten_name(u'main_activitystream_project'), db.shorten_name(u'main_activitystream_new_project')) + + db.rename_column(u'main_jobevent', 'job_id', 'new_job_id') + db.rename_column(u'main_jobhostsummary', 'job_id', 'new_job_id') + + + db.rename_table(db.shorten_name(u'main_group_inventory_sources'), db.shorten_name(u'main_group_new_inventory_sources')) + db.rename_table(db.shorten_name(u'main_host_inventory_sources'), db.shorten_name(u'main_host_new_inventory_sources')) + db.rename_column(u'main_host', 'last_job_id', 'new_last_job_id') + + db.rename_column(u'main_permission', 'project_id', 'new_project_id') + db.rename_table(db.shorten_name(u'main_organization_projects'), db.shorten_name(u'main_organization_new_projects')) + db.rename_table(db.shorten_name(u'main_team_projects'), db.shorten_name(u'main_team_new_projects')) + + db.rename_table(u'main_job', 'main_jobnew') + db.rename_table(u'main_jobtemplate', 'main_jobtemplatenew') + db.rename_table(u'main_inventoryupdate', 'main_inventoryupdatenew') + db.rename_table(u'main_inventorysource', 'main_inventorysourcenew') + db.rename_table(u'main_projectupdate', 'main_projectupdatenew') + db.rename_table(u'main_project', 'main_projectnew') + + + 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', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), + 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', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), + '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'}), + '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': {'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'}), + 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'}), + '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'}), + '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'}) + }, + 'main.group': { + 'Meta': {'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', [], {'symmetrical': 'False', 'related_name': "'groups'", 'blank': 'True', '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': {'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', [], {'symmetrical': 'False', 'related_name': "'hosts'", 'blank': 'True', 'to': "orm['main.InventorySource']"}), + 'last_job': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'hosts_as_last_job+'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.Job']", 'blank': 'True', 'null': 'True'}), + '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': {'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', [], {'default': 'None', 'related_name': "'inventorysources'", 'null': 'True', 'blank': 'True', 'to': "orm['main.Credential']"}), + 'group': ('awx.main.fields.AutoOneToOneField', [], {'related_name': "'inventory_source'", 'null': 'True', 'default': 'None', 'to': "orm['main.Group']", 'blank': 'True', 'unique': 'True'}), + '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_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', [], {'default': 'None', 'related_name': "'inventoryupdates'", 'null': 'True', 'blank': 'True', 'to': "orm['main.Credential']"}), + '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_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': {'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'}), + 'forks': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0', 'blank': 'True'}), + 'hosts': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'jobs'", 'blank': 'True', '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']"}), + 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'}), + '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', [], {'related_name': "'job_events_as_primary_host'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.Host']", 'blank': 'True', 'null': 'True'}), + 'hosts': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'job_events'", 'blank': 'True', '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', [], {'related_name': "'children'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.JobEvent']", 'blank': 'True', 'null': 'True'}), + 'play': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), + 'role': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), + 'task': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}) + }, + 'main.jobhostsummary': { + 'Meta': {'ordering': "('-pk',)", 'unique_together': "[('job', 'host')]", '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', [], {'related_name': "'job_host_summaries'", 'to': "orm['main.Host']"}), + 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': {'object_name': 'JobTemplate', '_ormbases': ['main.UnifiedJobTemplate']}, + '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'}), + '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': "'job_templates'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Project']"}), + 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': {'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': {'object_name': 'Project', '_ormbases': ['main.UnifiedJobTemplate']}, + 'credential': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'projects'", 'null': 'True', 'blank': 'True', 'to': "orm['main.Credential']"}), + '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', [], {'default': 'None', 'related_name': "'projectupdates'", 'null': 'True', 'blank': 'True', 'to': "orm['main.Credential']"}), + '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': {'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', [], {}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'job_template': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'schedules'", 'to': "orm['main.UnifiedJobTemplate']"}), + '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'}), + 'rrule': ('django.db.models.fields.CharField', [], {'max_length': '255'}) + }, + 'main.team': { + 'Meta': {'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']"}), + 'depends_on': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'depends_on_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'}), + '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']"}), + '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'}), + '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', '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', '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', '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'}), + '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'}) + }, + u'taggit.tag': { + 'Meta': {'object_name': 'Tag'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'}), + 'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '100'}) + }, + u'taggit.taggeditem': { + 'Meta': {'object_name': 'TaggedItem'}, + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'taggit_taggeditem_tagged_items'", 'to': u"orm['contenttypes.ContentType']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'object_id': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'}), + 'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'taggit_taggeditem_items'", 'to': u"orm['taggit.Tag']"}) + } + } + + complete_apps = ['main'] \ No newline at end of file diff --git a/awx/main/models/__init__.py b/awx/main/models/__init__.py index 21c5b96948..f5f73c82eb 100644 --- a/awx/main/models/__init__.py +++ b/awx/main/models/__init__.py @@ -1,48 +1,55 @@ # Copyright (c) 2014 AnsibleWorks, Inc. # All Rights Reserved. +# Django +from django.conf import settings + +# AWX from awx.main.models.base import * +from awx.main.models.unified_jobs import * from awx.main.models.organization import * from awx.main.models.projects import * 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 * -# Monkeypatch Django serializer to ignore django-taggit fields (which break -# the dumpdata command; see https://github.com/alex/django-taggit/issues/155). -from django.core.serializers.python import Serializer as _PythonSerializer -_original_handle_m2m_field = _PythonSerializer.handle_m2m_field -def _new_handle_m2m_field(self, obj, field): - try: - field.rel.through._meta - except AttributeError: - return - return _original_handle_m2m_field(self, obj, field) -_PythonSerializer.handle_m2m_field = _new_handle_m2m_field +if getattr(settings, 'UNIFIED_JOBS_STEP') in (0, 2): + # Monkeypatch Django serializer to ignore django-taggit fields (which break + # the dumpdata command; see https://github.com/alex/django-taggit/issues/155). + from django.core.serializers.python import Serializer as _PythonSerializer + _original_handle_m2m_field = _PythonSerializer.handle_m2m_field + def _new_handle_m2m_field(self, obj, field): + try: + field.rel.through._meta + except AttributeError: + return + return _original_handle_m2m_field(self, obj, field) + _PythonSerializer.handle_m2m_field = _new_handle_m2m_field -# Add custom methods to User model for permissions checks. -from django.contrib.auth.models import User -from awx.main.access import * -User.add_to_class('get_queryset', get_user_queryset) -User.add_to_class('can_access', check_user_access) + # Add custom methods to User model for permissions checks. + from django.contrib.auth.models import User + from awx.main.access import * + User.add_to_class('get_queryset', get_user_queryset) + User.add_to_class('can_access', check_user_access) -# Import signal handlers only after models have been defined. -import awx.main.signals + # Import signal handlers only after models have been defined. + import awx.main.signals -from awx.main.registrar import activity_stream_registrar -activity_stream_registrar.connect(Organization) -activity_stream_registrar.connect(Inventory) -activity_stream_registrar.connect(Host) -activity_stream_registrar.connect(Group) -activity_stream_registrar.connect(InventorySource) -#activity_stream_registrar.connect(InventoryUpdate) -activity_stream_registrar.connect(Credential) -activity_stream_registrar.connect(Team) -activity_stream_registrar.connect(Project) -#activity_stream_registrar.connect(ProjectUpdate) -activity_stream_registrar.connect(Permission) -activity_stream_registrar.connect(JobTemplate) -activity_stream_registrar.connect(Job) -# activity_stream_registrar.connect(JobHostSummary) -# activity_stream_registrar.connect(JobEvent) -#activity_stream_registrar.connect(Profile) + from awx.main.registrar import activity_stream_registrar + activity_stream_registrar.connect(Organization) + activity_stream_registrar.connect(Inventory) + activity_stream_registrar.connect(Host) + activity_stream_registrar.connect(Group) + activity_stream_registrar.connect(InventorySource) + #activity_stream_registrar.connect(InventoryUpdate) + activity_stream_registrar.connect(Credential) + activity_stream_registrar.connect(Team) + activity_stream_registrar.connect(Project) + #activity_stream_registrar.connect(ProjectUpdate) + activity_stream_registrar.connect(Permission) + activity_stream_registrar.connect(JobTemplate) + activity_stream_registrar.connect(Job) + # activity_stream_registrar.connect(JobHostSummary) + # activity_stream_registrar.connect(JobEvent) + #activity_stream_registrar.connect(Profile) diff --git a/awx/main/models/activity_stream.py b/awx/main/models/activity_stream.py index a41f14f0d1..d25b2220fc 100644 --- a/awx/main/models/activity_stream.py +++ b/awx/main/models/activity_stream.py @@ -1,7 +1,8 @@ # Copyright (c) 2014 AnsibleWorks, Inc. # All Rights Reserved. - +# Django +from django.conf import settings from django.db import models from django.core.urlresolvers import reverse from django.utils.translation import ugettext_lazy as _ @@ -9,12 +10,13 @@ from django.utils.translation import ugettext_lazy as _ __all__ = ['ActivityStream'] -class ActivityStream(models.Model): +class ActivityStreamBase(models.Model): ''' Model used to describe activity stream (audit) events ''' class Meta: + abstract = True app_label = 'main' OPERATION_CHOICES = [ @@ -39,15 +41,15 @@ class ActivityStream(models.Model): inventory = models.ManyToManyField("Inventory", blank=True) host = models.ManyToManyField("Host", blank=True) group = models.ManyToManyField("Group", blank=True) - inventory_source = models.ManyToManyField("InventorySource", blank=True) - inventory_update = models.ManyToManyField("InventoryUpdate", blank=True) + #inventory_source = models.ManyToManyField("InventorySource", blank=True) + #inventory_update = models.ManyToManyField("InventoryUpdate", blank=True) credential = models.ManyToManyField("Credential", blank=True) team = models.ManyToManyField("Team", blank=True) - project = models.ManyToManyField("Project", blank=True) - project_update = models.ManyToManyField("ProjectUpdate", blank=True) + #project = models.ManyToManyField("Project", blank=True) + #project_update = models.ManyToManyField("ProjectUpdate", blank=True) permission = models.ManyToManyField("Permission", blank=True) - job_template = models.ManyToManyField("JobTemplate", blank=True) - job = models.ManyToManyField("Job", blank=True) + #job_template = models.ManyToManyField("JobTemplate", blank=True) + #job = models.ManyToManyField("Job", blank=True) def get_absolute_url(self): return reverse('api:activity_stream_detail', args=(self.pk,)) @@ -62,3 +64,62 @@ class ActivityStream(models.Model): raise kwargs.pop('update_fields') super(ActivityStream, self).save(*args, **kwargs) + + +if getattr(settings, 'UNIFIED_JOBS_STEP') == 0: + + class ActivityStream(ActivityStreamBase): + + class Meta: + app_label = 'main' + + inventory_source = models.ManyToManyField("InventorySource", blank=True) + inventory_update = models.ManyToManyField("InventoryUpdate", blank=True) + project = models.ManyToManyField("Project", blank=True) + project_update = models.ManyToManyField("ProjectUpdate", blank=True) + job_template = models.ManyToManyField("JobTemplate", blank=True) + job = models.ManyToManyField("Job", blank=True) + + unified_job_template = models.ManyToManyField("UnifiedJobTemplate", blank=True, related_name='activity_stream_as_unified_job_template+') + unified_job = models.ManyToManyField("UnifiedJob", blank=True, related_name='activity_stream_as_unified_job+') + + new_inventory_source = models.ManyToManyField("InventorySourceNew", blank=True) + new_inventory_update = models.ManyToManyField("InventoryUpdateNew", blank=True) + new_project = models.ManyToManyField("ProjectNew", blank=True) + new_project_update = models.ManyToManyField("ProjectUpdateNew", blank=True) + new_job_template = models.ManyToManyField("JobTemplateNew", blank=True) + new_job = models.ManyToManyField("JobNew", blank=True) + +if getattr(settings, 'UNIFIED_JOBS_STEP') == 1: + + class ActivityStream(ActivityStreamBase): + + class Meta: + app_label = 'main' + + unified_job_template = models.ManyToManyField("UnifiedJobTemplate", blank=True, related_name='activity_stream_as_unified_job_template+') + unified_job = models.ManyToManyField("UnifiedJob", blank=True, related_name='activity_stream_as_unified_job+') + + new_inventory_source = models.ManyToManyField("InventorySourceNew", blank=True) + new_inventory_update = models.ManyToManyField("InventoryUpdateNew", blank=True) + new_project = models.ManyToManyField("ProjectNew", blank=True) + new_project_update = models.ManyToManyField("ProjectUpdateNew", blank=True) + new_job_template = models.ManyToManyField("JobTemplateNew", blank=True) + new_job = models.ManyToManyField("JobNew", blank=True) + +if getattr(settings, 'UNIFIED_JOBS_STEP') == 2: + + class ActivityStream(ActivityStreamBase): + + class Meta: + app_label = 'main' + + unified_job_template = models.ManyToManyField("UnifiedJobTemplate", blank=True, related_name='activity_stream_as_unified_job_template+') + unified_job = models.ManyToManyField("UnifiedJob", blank=True, related_name='activity_stream_as_unified_job+') + + inventory_source = models.ManyToManyField("InventorySource", blank=True) + inventory_update = models.ManyToManyField("InventoryUpdate", blank=True) + project = models.ManyToManyField("Project", blank=True) + project_update = models.ManyToManyField("ProjectUpdate", blank=True) + job_template = models.ManyToManyField("JobTemplate", blank=True) + job = models.ManyToManyField("Job", blank=True) diff --git a/awx/main/models/base.py b/awx/main/models/base.py index 45cabc5a83..5b680c1a81 100644 --- a/awx/main/models/base.py +++ b/awx/main/models/base.py @@ -15,19 +15,23 @@ from django.conf import settings from django.db import models from django.db import transaction from django.core.exceptions import ValidationError +from django.contrib.contenttypes.models import ContentType from django.utils.translation import ugettext_lazy as _ from django.utils.timezone import now # Django-JSONField from jsonfield import JSONField +# Django-Polymorphic +from polymorphic import PolymorphicModel + # Django-Taggit from taggit.managers import TaggableManager # Django-Celery from djcelery.models import TaskMeta -__all__ = ['VarsDictProperty', 'BaseModel', 'PrimordialModel', 'CommonModel', +__all__ = ['VarsDictProperty', 'BaseModel', 'CreatedModifiedModel', 'PrimordialModel', 'CommonModel', 'CommonModelNameNotUnique', 'CommonTask', 'PERM_INVENTORY_ADMIN', 'PERM_INVENTORY_READ', 'PERM_INVENTORY_WRITE', 'PERM_INVENTORY_DEPLOY', 'PERM_INVENTORY_CHECK', 'JOB_TYPE_CHOICES', @@ -150,7 +154,37 @@ class BaseModel(models.Model): super(BaseModel, self).save(*args, **kwargs) -class PrimordialModel(BaseModel): +class CreatedModifiedModel(BaseModel): + + class Meta: + abstract = True + + created = models.DateTimeField( + #auto_now_add=True, # FIXME: Disabled temporarily for data migration. + default=None, + editable=False, + ) + modified = models.DateTimeField( + #auto_now=True, # FIXME: Disabled temporarily for data migration. + #default=now, + default=None, + editable=False, + ) + + def save(self, *args, **kwargs): + update_fields = kwargs.get('update_fields', []) + # Manually perform auto_now_add and auto_now logic (for unified jobs migration). + if not self.pk and not self.created: + self.created = now() + if 'created' not in update_fields: + update_fields.append('created') + if 'modified' not in update_fields or not self.modified: + self.modified = now() # FIXME: Moved temporarily for unified jobs migration. + update_fields.append('modified') + super(CreatedModifiedModel, self).save(*args, **kwargs) + + +class PrimordialModel(CreatedModifiedModel): ''' common model for all object types that have these standard fields must use a subclass CommonModel or CommonModelNameNotUnique though @@ -164,13 +198,6 @@ class PrimordialModel(BaseModel): blank=True, default='', ) - created = models.DateTimeField( - auto_now_add=True, - ) - modified = models.DateTimeField( - auto_now=True, - default=now, - ) created_by = models.ForeignKey( 'auth.User', related_name='%s(class)s_created+', @@ -198,8 +225,9 @@ class PrimordialModel(BaseModel): '''Use instead of delete to rename and mark inactive.''' update_fields = update_fields or [] if self.active: + dtnow = now() if 'name' in self._meta.get_all_field_names(): - self.name = "_deleted_%s_%s" % (now().isoformat(), self.name) + self.name = "_deleted_%s_%s" % (dtnow.isoformat(), self.name) if 'name' not in update_fields: update_fields.append('name') self.active = False @@ -238,215 +266,223 @@ class CommonModelNameNotUnique(PrimordialModel): ) -class CommonTask(PrimordialModel): - ''' - Common fields for models run by the task engine. - ''' +if getattr(settings, 'UNIFIED_JOBS_STEP') == 0: - class Meta: - app_label = 'main' - abstract = True + class CommonTask(PrimordialModel): + ''' + Common fields for models run by the task engine. + ''' - cancel_flag = models.BooleanField( - blank=True, - default=False, - editable=False, - ) - status = models.CharField( - max_length=20, - choices=TASK_STATUS_CHOICES, - default='new', - editable=False, - ) - failed = models.BooleanField( - default=False, - editable=False, - ) - job_args = models.TextField( - blank=True, - default='', - editable=False, - ) - job_cwd = models.CharField( - max_length=1024, - blank=True, - default='', - editable=False, - ) - job_env = JSONField( - blank=True, - default={}, - editable=False, - ) - _result_stdout = models.TextField( - blank=True, - default='', - editable=False, - db_column="result_stdout", - ) - result_stdout_file = models.TextField( - blank=True, - default='', - editable=False, - ) - result_traceback = models.TextField( - blank=True, - default='', - editable=False, - ) - celery_task_id = models.CharField( - max_length=100, - blank=True, - default='', - editable=False, - ) + class Meta: + app_label = 'main' + abstract = True - def __unicode__(self): - return u'%s-%s-%s' % (self.created, self.id, self.status) + cancel_flag = models.BooleanField( + blank=True, + default=False, + editable=False, + ) + status = models.CharField( + max_length=20, + choices=TASK_STATUS_CHOICES, + default='new', + editable=False, + ) + failed = models.BooleanField( + default=False, + editable=False, + ) + job_args = models.TextField( + blank=True, + default='', + editable=False, + ) + job_cwd = models.CharField( + max_length=1024, + blank=True, + default='', + editable=False, + ) + job_env = JSONField( + blank=True, + default={}, + editable=False, + ) + _result_stdout = models.TextField( + blank=True, + default='', + editable=False, + db_column="result_stdout", + ) + result_stdout_file = models.TextField( + blank=True, + default='', + editable=False, + ) + result_traceback = models.TextField( + blank=True, + default='', + editable=False, + ) + celery_task_id = models.CharField( + max_length=100, + blank=True, + default='', + editable=False, + ) - def _get_parent_instance(self): - return None + def __unicode__(self): + return u'%s-%s-%s' % (self.created, self.id, self.status) - def _update_parent_instance(self): - parent_instance = self._get_parent_instance() - if parent_instance: - if self.status in ('pending', 'waiting', 'running'): - if parent_instance.current_update != self: - parent_instance.current_update = self - parent_instance.save(update_fields=['current_update']) - elif self.status in ('successful', 'failed', 'error', 'canceled'): - if parent_instance.current_update == self: - parent_instance.current_update = None - parent_instance.last_update = self - parent_instance.last_update_failed = self.failed - parent_instance.save(update_fields=['current_update', - 'last_update', - 'last_update_failed']) + def _get_parent_instance(self): + return None - def save(self, *args, **kwargs): - # Get status before save... - status_before = self.status or 'new' - if self.pk: - self_before = self.__class__.objects.get(pk=self.pk) - if self_before.status != self.status: - status_before = self_before.status - self.failed = bool(self.status in ('failed', 'error', 'canceled')) - super(CommonTask, self).save(*args, **kwargs) - # If status changed, update parent instance.... - if self.status != status_before: - self._update_parent_instance() + def _update_parent_instance(self): + parent_instance = self._get_parent_instance() + if parent_instance: + if self.status in ('pending', 'waiting', 'running'): + if parent_instance.current_update != self: + parent_instance.current_update = self + parent_instance.save(update_fields=['current_update']) + elif self.status in ('successful', 'failed', 'error', 'canceled'): + if parent_instance.current_update == self: + parent_instance.current_update = None + parent_instance.last_update = self + parent_instance.last_update_failed = self.failed + parent_instance.save(update_fields=['current_update', + 'last_update', + 'last_update_failed']) - def delete(self): - if self.result_stdout_file != "": + def save(self, *args, **kwargs): + # Get status before save... + status_before = self.status or 'new' + if self.pk: + self_before = self.__class__.objects.get(pk=self.pk) + if self_before.status != self.status: + status_before = self_before.status + self.failed = bool(self.status in ('failed', 'error', 'canceled')) + super(CommonTask, self).save(*args, **kwargs) + # If status changed, update parent instance.... + if self.status != status_before: + self._update_parent_instance() + + def delete(self): + if self.result_stdout_file != "": + try: + os.remove(self.result_stdout_file) + except Exception, e: + pass + super(CommonTask, self).delete() + + @property + def result_stdout(self): + if self.result_stdout_file != "": + if not os.path.exists(self.result_stdout_file): + return "stdout capture is missing" + stdout_fd = open(self.result_stdout_file, "r") + output = stdout_fd.read() + stdout_fd.close() + return output + return self._result_stdout + + @property + def celery_task(self): try: - os.remove(self.result_stdout_file) - except Exception, e: + if self.celery_task_id: + return TaskMeta.objects.get(task_id=self.celery_task_id) + except TaskMeta.DoesNotExist: pass - super(CommonTask, self).delete() - @property - def result_stdout(self): - if self.result_stdout_file != "": - if not os.path.exists(self.result_stdout_file): - return "stdout capture is missing" - stdout_fd = open(self.result_stdout_file, "r") - output = stdout_fd.read() - stdout_fd.close() - return output - return self._result_stdout + @property + def can_start(self): + return bool(self.status == 'new') - @property - def celery_task(self): - try: - if self.celery_task_id: - return TaskMeta.objects.get(task_id=self.celery_task_id) - except TaskMeta.DoesNotExist: - pass + def _get_task_class(self): + raise NotImplementedError - @property - def can_start(self): - return bool(self.status == 'new') + def _get_passwords_needed_to_start(self): + return [] - def _get_task_class(self): - raise NotImplementedError + def start_signature(self, **kwargs): + from awx.main.tasks import handle_work_error - def _get_passwords_needed_to_start(self): - return [] + task_class = self._get_task_class() + if not self.can_start: + return False + needed = self._get_passwords_needed_to_start() + opts = dict([(field, kwargs.get(field, '')) for field in needed]) + if not all(opts.values()): + return False + self.status = 'pending' + self.save(update_fields=['status']) + transaction.commit() + task_actual = task_class().si(self.pk, **opts) + return task_actual - def start_signature(self, **kwargs): - from awx.main.tasks import handle_work_error - - task_class = self._get_task_class() - if not self.can_start: - return False - needed = self._get_passwords_needed_to_start() - opts = dict([(field, kwargs.get(field, '')) for field in needed]) - if not all(opts.values()): - return False - self.status = 'pending' - self.save(update_fields=['status']) - transaction.commit() - task_actual = task_class().si(self.pk, **opts) - return task_actual - - def start(self, **kwargs): - task_actual = self.start_signature(**kwargs) - # TODO: Callback for status - task_result = task_actual.delay() - # Reload instance from database so we don't clobber results from task - # (mainly from tests when using Django 1.4.x). - instance = self.__class__.objects.get(pk=self.pk) - # The TaskMeta instance in the database isn't created until the worker - # starts processing the task, so we can only store the task ID here. - instance.celery_task_id = task_result.task_id - instance.save(update_fields=['celery_task_id']) - return True - - @property - def can_cancel(self): - return bool(self.status in ('pending', 'waiting', 'running')) - - def _force_cancel(self): - # Update the status to 'canceled' if we can detect that the job - # really isn't running (i.e. celery has crashed or forcefully - # killed the worker). - task_statuses = ('STARTED', 'SUCCESS', 'FAILED', 'RETRY', 'REVOKED') - try: - taskmeta = self.celery_task - if not taskmeta or taskmeta.status not in task_statuses: - return - from celery import current_app - i = current_app.control.inspect() - for v in (i.active() or {}).values(): - if taskmeta.task_id in [x['id'] for x in v]: - return - for v in (i.reserved() or {}).values(): - if taskmeta.task_id in [x['id'] for x in v]: - return - for v in (i.revoked() or {}).values(): - if taskmeta.task_id in [x['id'] for x in v]: - return - for v in (i.scheduled() or {}).values(): - if taskmeta.task_id in [x['id'] for x in v]: - return + def start(self, **kwargs): + task_actual = self.start_signature(**kwargs) + # TODO: Callback for status + task_result = task_actual.delay() + # Reload instance from database so we don't clobber results from task + # (mainly from tests when using Django 1.4.x). instance = self.__class__.objects.get(pk=self.pk) - if instance.can_cancel: - instance.status = 'canceled' - update_fields = ['status'] - if not instance.result_traceback: - instance.result_traceback = 'Forced cancel' - update_fields.append('result_traceback') - instance.save(update_fields=update_fields) - except: # FIXME: Log this exception! - if settings.DEBUG: - raise + # The TaskMeta instance in the database isn't created until the worker + # starts processing the task, so we can only store the task ID here. + instance.celery_task_id = task_result.task_id + instance.save(update_fields=['celery_task_id']) + return True - def cancel(self): - if self.can_cancel: - if not self.cancel_flag: - self.cancel_flag = True - self.save(update_fields=['cancel_flag']) - if settings.BROKER_URL.startswith('amqp://'): - self._force_cancel() - return self.cancel_flag + @property + def can_cancel(self): + return bool(self.status in ('pending', 'waiting', 'running')) + def _force_cancel(self): + # Update the status to 'canceled' if we can detect that the job + # really isn't running (i.e. celery has crashed or forcefully + # killed the worker). + task_statuses = ('STARTED', 'SUCCESS', 'FAILED', 'RETRY', 'REVOKED') + try: + taskmeta = self.celery_task + if not taskmeta or taskmeta.status not in task_statuses: + return + from celery import current_app + i = current_app.control.inspect() + for v in (i.active() or {}).values(): + if taskmeta.task_id in [x['id'] for x in v]: + return + for v in (i.reserved() or {}).values(): + if taskmeta.task_id in [x['id'] for x in v]: + return + for v in (i.revoked() or {}).values(): + if taskmeta.task_id in [x['id'] for x in v]: + return + for v in (i.scheduled() or {}).values(): + if taskmeta.task_id in [x['id'] for x in v]: + return + instance = self.__class__.objects.get(pk=self.pk) + if instance.can_cancel: + instance.status = 'canceled' + update_fields = ['status'] + if not instance.result_traceback: + instance.result_traceback = 'Forced cancel' + update_fields.append('result_traceback') + instance.save(update_fields=update_fields) + except: # FIXME: Log this exception! + if settings.DEBUG: + raise + + def cancel(self): + if self.can_cancel: + if not self.cancel_flag: + self.cancel_flag = True + self.save(update_fields=['cancel_flag']) + if settings.BROKER_URL.startswith('amqp://'): + self._force_cancel() + return self.cancel_flag + +else: + + class CommonTask(PrimordialModel): + + class Meta: + abstract = True diff --git a/awx/main/models/inventory.py b/awx/main/models/inventory.py index 4a9a2c2355..ed82395829 100644 --- a/awx/main/models/inventory.py +++ b/awx/main/models/inventory.py @@ -28,6 +28,7 @@ from django.utils.timezone import now, make_aware, get_default_timezone # AWX from awx.main.fields import AutoOneToOneField from awx.main.models.base import * +from awx.main.models.unified_jobs import * __all__ = ['Inventory', 'Host', 'Group', 'InventorySource', 'InventoryUpdate'] @@ -153,12 +154,13 @@ class Inventory(CommonModel): return self.groups.exclude(parents__pk__in=group_pks).distinct() -class Host(CommonModelNameNotUnique): +class HostBase(CommonModelNameNotUnique): ''' A managed node ''' class Meta: + abstract = True app_label = 'main' unique_together = (("name", "inventory"),) # FIXME: Add ('instance_id', 'inventory') after migration. @@ -180,15 +182,15 @@ class Host(CommonModelNameNotUnique): default='', help_text=_('Host variables in JSON or YAML format.'), ) - last_job = models.ForeignKey( - 'Job', - related_name='hosts_as_last_job+', - blank=True, - null=True, - default=None, - editable=False, - on_delete=models.SET_NULL, - ) + #last_job = models.ForeignKey( + # 'Job', + # related_name='hosts_as_last_job+', + # blank=True, + # null=True, + # default=None, + # editable=False, + # on_delete=models.SET_NULL, + #) last_job_host_summary = models.ForeignKey( 'JobHostSummary', related_name='hosts_as_last_job_summary+', @@ -208,13 +210,13 @@ class Host(CommonModelNameNotUnique): editable=False, help_text=_('Flag indicating whether this host was created/updated from any external inventory sources.'), ) - inventory_sources = models.ManyToManyField( - 'InventorySource', - related_name='hosts', - blank=True, - editable=False, - help_text=_('Inventory source(s) that created or modified this host.'), - ) + #inventory_sources = models.ManyToManyField( + # 'InventorySource', + # related_name='hosts', + # blank=True, + # editable=False, + # help_text=_('Inventory source(s) that created or modified this host.'), + #) def __unicode__(self): return self.name @@ -276,13 +278,106 @@ class Host(CommonModelNameNotUnique): # Use .job_events.all() to get events affecting this host. -class Group(CommonModelNameNotUnique): +if getattr(settings, 'UNIFIED_JOBS_STEP') == 0: + + class Host(HostBase): + + class Meta: + app_label = 'main' + unique_together = (("name", "inventory"),) + + last_job = models.ForeignKey( + 'Job', + related_name='hosts_as_last_job+', + blank=True, + null=True, + default=None, + editable=False, + on_delete=models.SET_NULL, + ) + new_last_job = models.ForeignKey( + 'JobNew', + related_name='hosts_as_last_job+', + blank=True, + null=True, + default=None, + editable=False, + on_delete=models.SET_NULL, + ) + inventory_sources = models.ManyToManyField( + 'InventorySource', + related_name='hosts', + blank=True, + editable=False, + help_text=_('Inventory source(s) that created or modified this host.'), + ) + new_inventory_sources = models.ManyToManyField( + 'InventorySourceNew', + related_name='hosts', + blank=True, + editable=False, + help_text=_('Inventory source(s) that created or modified this host.'), + ) + +if getattr(settings, 'UNIFIED_JOBS_STEP') == 1: + + class Host(HostBase): + + class Meta: + app_label = 'main' + unique_together = (("name", "inventory"),) + + new_last_job = models.ForeignKey( + 'JobNew', + related_name='hosts_as_last_job+', + blank=True, + null=True, + default=None, + editable=False, + on_delete=models.SET_NULL, + ) + new_inventory_sources = models.ManyToManyField( + 'InventorySourceNew', + related_name='hosts', + blank=True, + editable=False, + help_text=_('Inventory source(s) that created or modified this host.'), + ) + +if getattr(settings, 'UNIFIED_JOBS_STEP') == 2: + + class Host(HostBase): + + class Meta: + app_label = 'main' + unique_together = (("name", "inventory"),) + + last_job = models.ForeignKey( + 'Job', + related_name='hosts_as_last_job+', + blank=True, + null=True, + default=None, + editable=False, + on_delete=models.SET_NULL, + ) + inventory_sources = models.ManyToManyField( + 'InventorySource', + related_name='hosts', + blank=True, + editable=False, + help_text=_('Inventory source(s) that created or modified this host.'), + ) + + +class GroupBase(CommonModelNameNotUnique): ''' A group containing managed hosts. A group or host may belong to multiple groups. ''' class Meta: + abstract = True app_label = 'main' unique_together = (("name", "inventory"),) @@ -338,13 +433,13 @@ class Group(CommonModelNameNotUnique): editable=False, help_text=_('Flag indicating whether this group was created/updated from any external inventory sources.'), ) - inventory_sources = models.ManyToManyField( - 'InventorySource', - related_name='groups', - blank=True, - editable=False, - help_text=_('Inventory source(s) that created or modified this group.'), - ) + #inventory_sources = models.ManyToManyField( + # 'InventorySource', + # related_name='groups', + # blank=True, + # editable=False, + # help_text=_('Inventory source(s) that created or modified this group.'), + #) def __unicode__(self): return self.name @@ -464,7 +559,68 @@ class Group(CommonModelNameNotUnique): from awx.main.models.jobs import JobEvent return JobEvent.objects.filter(host__in=self.all_hosts) -class InventorySource(PrimordialModel): + +if getattr(settings, 'UNIFIED_JOBS_STEP') == 0: + + class Group(GroupBase): + + class Meta: + app_label = 'main' + unique_together = (("name", "inventory"),) + + inventory_sources = models.ManyToManyField( + 'InventorySource', + related_name='groups', + blank=True, + editable=False, + help_text=_('Inventory source(s) that created or modified this group.'), + ) + + new_inventory_sources = models.ManyToManyField( + 'InventorySourceNew', + related_name='groups', + blank=True, + editable=False, + help_text=_('Inventory source(s) that created or modified this group.'), + ) + +if getattr(settings, 'UNIFIED_JOBS_STEP') == 1: + + class Group(GroupBase): + + class Meta: + app_label = 'main' + unique_together = (("name", "inventory"),) + + new_inventory_sources = models.ManyToManyField( + 'InventorySourceNew', + related_name='groups', + blank=True, + editable=False, + help_text=_('Inventory source(s) that created or modified this group.'), + ) + +if getattr(settings, 'UNIFIED_JOBS_STEP') == 2: + + class Group(GroupBase): + + class Meta: + app_label = 'main' + unique_together = (("name", "inventory"),) + + inventory_sources = models.ManyToManyField( + 'InventorySource', + related_name='groups', + blank=True, + editable=False, + help_text=_('Inventory source(s) that created or modified this group.'), + ) + + +class InventorySourceOptions(BaseModel): + ''' + Common fields for InventorySource and InventoryUpdate. + ''' SOURCE_CHOICES = [ ('file', _('Local File, Directory or Script')), @@ -472,32 +628,9 @@ class InventorySource(PrimordialModel): ('ec2', _('Amazon EC2')), ] - INVENTORY_SOURCE_STATUS_CHOICES = [ - ('none', _('No External Source')), - ('never updated', _('Never Updated')), - ('updating', _('Updating')), - ('failed', _('Failed')), - ('successful', _('Successful')), - ] - class Meta: - app_label = 'main' + abstract = True - inventory = models.ForeignKey( - 'Inventory', - related_name='inventory_sources', - null=True, - default=None, - editable=False, - ) - group = AutoOneToOneField( - 'Group', - related_name='inventory_source', - blank=True, - null=True, - default=None, - editable=False, - ) source = models.CharField( max_length=32, choices=SOURCE_CHOICES, @@ -517,10 +650,11 @@ class InventorySource(PrimordialModel): ) credential = models.ForeignKey( 'Credential', - related_name='inventory_sources', + related_name='%(class)ss', null=True, default=None, blank=True, + #on_delete=models.SET_NULL, # FIXME ) source_regions = models.CharField( max_length=1024, @@ -535,41 +669,19 @@ class InventorySource(PrimordialModel): default=False, help_text=_('Overwrite local variables from remote inventory source.'), ) + + +class InventorySourceBase(InventorySourceOptions): + + class Meta: + abstract = True + app_label = 'main' + update_on_launch = models.BooleanField( default=False, ) - update_interval = models.PositiveIntegerField( + update_cache_timeout = models.PositiveIntegerField( default=0, - help_text=_('If nonzero, inventory source will be updated every N minutes.'), - ) - current_update = models.ForeignKey( - 'InventoryUpdate', - null=True, - default=None, - editable=False, - related_name='inventory_source_as_current_update+', - ) - last_update = models.ForeignKey( - 'InventoryUpdate', - null=True, - default=None, - editable=False, - related_name='inventory_source_as_last_update+', - ) - last_update_failed = models.BooleanField( - default=False, - editable=False, - ) - last_updated = models.DateTimeField( - null=True, - default=None, - editable=False, - ) - status = models.CharField( - max_length=32, - choices=INVENTORY_SOURCE_STATUS_CHOICES, - default='none', - editable=False, ) @classmethod @@ -698,13 +810,13 @@ class InventorySource(PrimordialModel): def update_signature(self, **kwargs): if self.can_update: - inventory_update = self.inventory_updates.create() + inventory_update = self.inventory_updates.create() # FIXME: Copy inventory source fields to update inventory_update_sig = inventory_update.start_signature() return (inventory_update, inventory_update_sig) def update(self, **kwargs): if self.can_update: - inventory_update = self.inventory_updates.create() + inventory_update = self.inventory_updates.create() # FIXME: Copy inventory source fields to update inventory_update.start() return inventory_update @@ -712,20 +824,129 @@ class InventorySource(PrimordialModel): return reverse('api:inventory_source_detail', args=(self.pk,)) -class InventoryUpdate(CommonTask): +if getattr(settings, 'UNIFIED_JOBS_STEP') == 0: + + class InventorySource(PrimordialModel, InventorySourceBase): + + INVENTORY_SOURCE_STATUS_CHOICES = [ + ('none', _('No External Source')), + ('never updated', _('Never Updated')), + ('updating', _('Updating')), + ('failed', _('Failed')), + ('successful', _('Successful')), + ] + + class Meta: + app_label = 'main' + + inventory = models.ForeignKey( + 'Inventory', + related_name='inventory_sources', + null=True, + default=None, + editable=False, + ) + group = AutoOneToOneField( + 'Group', + related_name='inventory_source', + blank=True, + null=True, + default=None, + editable=False, + ) + current_update = models.ForeignKey( + 'InventoryUpdate', + null=True, + default=None, + editable=False, + related_name='inventory_source_as_current_update+', + ) + last_update = models.ForeignKey( + 'InventoryUpdate', + null=True, + default=None, + editable=False, + related_name='inventory_source_as_last_update+', + ) + last_update_failed = models.BooleanField( + default=False, + editable=False, + ) + last_updated = models.DateTimeField( + null=True, + default=None, + editable=False, + ) + status = models.CharField( + max_length=32, + choices=INVENTORY_SOURCE_STATUS_CHOICES, + default='none', + editable=False, + ) + +if getattr(settings, 'UNIFIED_JOBS_STEP') in (0, 1): + + class InventorySourceNew(UnifiedJobTemplate, InventorySourceBase): + + class Meta: + app_label = 'main' + + inventory = models.ForeignKey( + 'Inventory', + related_name='new_inventory_sources', + null=True, + default=None, + editable=False, + ) + group = AutoOneToOneField( + 'Group', + related_name='new_inventory_source', + blank=True, + null=True, + default=None, + editable=False, + ) + +if getattr(settings, 'UNIFIED_JOBS_STEP') == 1: + + class InventorySource(InventorySourceNew): + + class Meta: + proxy = True + +if getattr(settings, 'UNIFIED_JOBS_STEP') == 2: + + class InventorySource(UnifiedJobTemplate, InventorySourceBase): + + class Meta: + app_label = 'main' + + inventory = models.ForeignKey( + 'Inventory', + related_name='inventory_sources', + null=True, + default=None, + editable=False, + ) + group = AutoOneToOneField( + 'Group', + related_name='inventory_source', + blank=True, + null=True, + default=None, + editable=False, + ) + + +class InventoryUpdateBase(InventorySourceOptions): ''' Internal job for tracking inventory updates from external sources. ''' class Meta: app_label = 'main' + abstract = True - inventory_source = models.ForeignKey( - 'InventorySource', - related_name='inventory_updates', - on_delete=models.CASCADE, - editable=False, - ) license_error = models.BooleanField( default=False, editable=False, @@ -749,3 +970,53 @@ class InventoryUpdate(CommonTask): def _get_task_class(self): from awx.main.tasks import RunInventoryUpdate return RunInventoryUpdate + + +if getattr(settings, 'UNIFIED_JOBS_STEP') == 0: + + class InventoryUpdate(CommonTask, InventoryUpdateBase): + + class Meta: + app_label = 'main' + + inventory_source = models.ForeignKey( + 'InventorySource', + related_name='inventory_updates', + on_delete=models.CASCADE, + editable=False, + ) + +if getattr(settings, 'UNIFIED_JOBS_STEP') in (0, 1): + + class InventoryUpdateNew(UnifiedJob, InventoryUpdateBase): + + class Meta: + app_label = 'main' + + inventory_source = models.ForeignKey( + 'InventorySourceNew', + related_name='inventory_updates', + on_delete=models.CASCADE, + editable=False, + ) + +if getattr(settings, 'UNIFIED_JOBS_STEP') == 1: + + class InventoryUpdate(InventoryUpdateNew): + + class Meta: + proxy = True + +if getattr(settings, 'UNIFIED_JOBS_STEP') == 2: + + class InventoryUpdate(UnifiedJob, InventoryUpdateBase): + + class Meta: + app_label = 'main' + + inventory_source = models.ForeignKey( + 'InventorySource', + related_name='inventory_updates', + on_delete=models.CASCADE, + editable=False, + ) diff --git a/awx/main/models/jobs.py b/awx/main/models/jobs.py index 36fb326588..45350dbd7f 100644 --- a/awx/main/models/jobs.py +++ b/awx/main/models/jobs.py @@ -31,6 +31,7 @@ from jsonfield import JSONField # AWX from awx.main.models.base import * +from awx.main.models.unified_jobs import * # Celery from celery import chain @@ -39,15 +40,12 @@ logger = logging.getLogger('awx.main.models.jobs') __all__ = ['JobTemplate', 'Job', 'JobHostSummary', 'JobEvent'] - -class JobTemplate(CommonModel): +class JobOptions(BaseModel): ''' - A job template is a reusable job definition for applying a project (with - playbook) to an inventory source with a given credential. ''' - + class Meta: - app_label = 'main' + abstract = True job_type = models.CharField( max_length=64, @@ -55,23 +53,23 @@ class JobTemplate(CommonModel): ) inventory = models.ForeignKey( 'Inventory', - related_name='job_templates', - null=True, - on_delete=models.SET_NULL, - ) - project = models.ForeignKey( - 'Project', - related_name='job_templates', + related_name='%(class)ss', null=True, on_delete=models.SET_NULL, ) + #project = models.ForeignKey( + # 'Project', + # related_name='%(class)ss', + # null=True, + # on_delete=models.SET_NULL, + #) playbook = models.CharField( max_length=1024, default='', ) credential = models.ForeignKey( 'Credential', - related_name='job_templates', + related_name='%(class)ss', blank=True, null=True, default=None, @@ -79,7 +77,7 @@ class JobTemplate(CommonModel): ) cloud_credential = models.ForeignKey( 'Credential', - related_name='job_templates_as_cloud_credential+', + related_name='%(class)ss_as_cloud_credential+', blank=True, null=True, default=None, @@ -107,11 +105,8 @@ class JobTemplate(CommonModel): blank=True, default='', ) - host_config_key = models.CharField( - max_length=1024, - blank=True, - default='', - ) + + extra_vars_dict = VarsDictProperty('extra_vars', True) def clean_credential(self): cred = self.credential @@ -126,6 +121,24 @@ class JobTemplate(CommonModel): '"rax"') return cred + +class JobTemplateBase(JobOptions): + ''' + A job template is a reusable job definition for applying a project (with + playbook) to an inventory source with a given credential. + ''' + + class Meta: + abstract = True + app_label = 'main' + + host_config_key = models.CharField( + max_length=1024, + blank=True, + default='', + ) + + def create_job(self, **kwargs): ''' Create a new job based on this template. @@ -165,117 +178,80 @@ class JobTemplate(CommonModel): needed.append(pw) return bool(self.credential and not len(needed)) -class Job(CommonTask): + +if getattr(settings, 'UNIFIED_JOBS_STEP') == 0: + + class JobTemplate(CommonModel, JobTemplateBase): + + class Meta: + app_label = 'main' + + project = models.ForeignKey( + 'Project', + related_name='job_templates', + null=True, + on_delete=models.SET_NULL, + ) + +if getattr(settings, 'UNIFIED_JOBS_STEP') in (0, 1): + + class JobTemplateNew(UnifiedJobTemplate, JobTemplateBase): + + class Meta: + app_label = 'main' + db_table = 'main_jobtemplatenew' + + project = models.ForeignKey( + 'ProjectNew', + related_name='job_templates', + null=True, + on_delete=models.SET_NULL, + ) + +if getattr(settings, 'UNIFIED_JOBS_STEP') == 1: + + class JobTemplate(JobTemplateNew): + + class Meta: + proxy = True + +if getattr(settings, 'UNIFIED_JOBS_STEP') == 2: + + class JobTemplate(UnifiedJobTemplate, JobTemplateBase): + + class Meta: + app_label = 'main' + + project = models.ForeignKey( + 'Project', + related_name='job_templates', + null=True, + on_delete=models.SET_NULL, + ) + + +class JobBase(JobOptions): ''' A job applies a project (with playbook) to an inventory source with a given credential. It represents a single invocation of ansible-playbook with the given parameters. ''' - LAUNCH_TYPE_CHOICES = [ - ('manual', _('Manual')), - ('callback', _('Callback')), - ('scheduled', _('Scheduled')), - ] - class Meta: + abstract = True app_label = 'main' - job_template = models.ForeignKey( - 'JobTemplate', - related_name='jobs', - blank=True, - null=True, - default=None, - on_delete=models.SET_NULL, - ) - job_type = models.CharField( - max_length=64, - choices=JOB_TYPE_CHOICES, - ) - inventory = models.ForeignKey( - 'Inventory', - related_name='jobs', - null=True, - on_delete=models.SET_NULL, - ) - credential = models.ForeignKey( - 'Credential', - related_name='jobs', - null=True, - on_delete=models.SET_NULL, - ) - cloud_credential = models.ForeignKey( - 'Credential', - related_name='jobs_as_cloud_credential+', - blank=True, - null=True, - default=None, - on_delete=models.SET_NULL, - ) - project = models.ForeignKey( - 'Project', - related_name='jobs', - null=True, - on_delete=models.SET_NULL, - ) - playbook = models.CharField( - max_length=1024, - ) - forks = models.PositiveIntegerField( - blank=True, - default=0, - ) - limit = models.CharField( - max_length=1024, - blank=True, - default='', - ) - verbosity = models.PositiveIntegerField( - blank=True, - default=0, - ) - extra_vars = models.TextField( - blank=True, - default='', - ) - job_tags = models.CharField( - max_length=1024, - blank=True, - default='', - ) - launch_type = models.CharField( - max_length=20, - choices=LAUNCH_TYPE_CHOICES, - default='manual', - editable=False, - ) hosts = models.ManyToManyField( 'Host', - related_name='jobs', + related_name='%(class)ss', blank=True, editable=False, through='JobHostSummary', ) - def clean_credential(self): - cred = self.credential - if cred and cred.kind != 'ssh': - raise ValidationError('Credential kind must be "ssh"') - return cred - - def clean_cloud_credential(self): - cred = self.cloud_credential - if cred and cred.kind not in ('aws', 'rax'): - raise ValidationError('Cloud credential kind must be "aws" or ' - '"rax"') - return cred - def get_absolute_url(self): return reverse('api:job_detail', args=(self.pk,)) - extra_vars_dict = VarsDictProperty('extra_vars', True) - @property def task_auth_token(self): '''Return temporary auth token used for task requests via API.''' @@ -395,36 +371,116 @@ class Job(CommonTask): res = chain(run_tasks)() return True -class JobHostSummary(BaseModel): + +if getattr(settings, 'UNIFIED_JOBS_STEP') == 0: + + class Job(CommonTask, JobBase): + + LAUNCH_TYPE_CHOICES = [ + ('manual', _('Manual')), + ('callback', _('Callback')), + ('scheduled', _('Scheduled')), + ] + + class Meta: + app_label = 'main' + + job_template = models.ForeignKey( + 'JobTemplate', + related_name='jobs', + blank=True, + null=True, + default=None, + on_delete=models.SET_NULL, + ) + project = models.ForeignKey( + 'Project', + related_name='jobs', + null=True, + on_delete=models.SET_NULL, + ) + launch_type = models.CharField( + max_length=20, + choices=LAUNCH_TYPE_CHOICES, + default='manual', + editable=False, + ) + +if getattr(settings, 'UNIFIED_JOBS_STEP') in (0, 1): + + class JobNew(UnifiedJob, JobBase): + + class Meta: + app_label = 'main' + + job_template = models.ForeignKey( + 'JobTemplateNew', + related_name='jobs', + blank=True, + null=True, + default=None, + on_delete=models.SET_NULL, + ) + project = models.ForeignKey( + 'ProjectNew', + related_name='jobs', + null=True, + on_delete=models.SET_NULL, + ) + +if getattr(settings, 'UNIFIED_JOBS_STEP') == 1: + + class Job(JobNew): + + class Meta: + proxy = True + +if getattr(settings, 'UNIFIED_JOBS_STEP') == 2: + + class Job(UnifiedJob, JobBase): + + class Meta: + app_label = 'main' + + job_template = models.ForeignKey( + 'JobTemplate', + related_name='jobs', + blank=True, + null=True, + default=None, + on_delete=models.SET_NULL, + ) + project = models.ForeignKey( + 'Project', + related_name='jobs', + null=True, + on_delete=models.SET_NULL, + ) + + +class JobHostSummaryBase(CreatedModifiedModel): ''' Per-host statistics for each job. ''' class Meta: + abstract = True app_label = 'main' unique_together = [('job', 'host')] verbose_name_plural = _('job host summaries') ordering = ('-pk',) - job = models.ForeignKey( - 'Job', - related_name='job_host_summaries', - on_delete=models.CASCADE, - editable=False, - ) + #job = models.ForeignKey( + # 'Job', + # related_name='job_host_summaries', + # on_delete=models.CASCADE, + # editable=False, + #) host = models.ForeignKey('Host', related_name='job_host_summaries', on_delete=models.CASCADE, editable=False, ) - created = models.DateTimeField( - auto_now_add=True, - default=now, - ) - modified = models.DateTimeField( - auto_now=True, - default=now, - ) changed = models.PositiveIntegerField(default=0, editable=False) dark = models.PositiveIntegerField(default=0, editable=False) @@ -463,7 +519,68 @@ class JobHostSummary(BaseModel): self.host.save(update_fields=update_fields) #self.host.update_computed_fields() -class JobEvent(BaseModel): + +if getattr(settings, 'UNIFIED_JOBS_STEP') == 0: + + class JobHostSummary(JobHostSummaryBase): + + class Meta: + app_label = 'main' + unique_together = [('job', 'host'), ('new_job', 'host')] + verbose_name_plural = _('job host summaries') + ordering = ('-pk',) + + job = models.ForeignKey( + 'Job', + related_name='job_host_summaries', + on_delete=models.CASCADE, + editable=False, + ) + new_job = models.ForeignKey( + 'JobNew', + related_name='new_job_host_summaries', + on_delete=models.CASCADE, + null=True, + default=None, + editable=False, + ) + +if getattr(settings, 'UNIFIED_JOBS_STEP') == 1: + + class JobHostSummary(JobHostSummaryBase): + + class Meta: + app_label = 'main' + unique_together = [('new_job', 'host')] + verbose_name_plural = _('job host summaries') + ordering = ('-pk',) + + new_job = models.ForeignKey( + 'JobNew', + related_name='new_job_host_summaries', + on_delete=models.CASCADE, + editable=False, + ) + +if getattr(settings, 'UNIFIED_JOBS_STEP') == 2: + + class JobHostSummary(JobHostSummaryBase): + + class Meta: + app_label = 'main' + unique_together = [('job', 'host')] + verbose_name_plural = _('job host summaries') + ordering = ('-pk',) + + job = models.ForeignKey( + 'Job', + related_name='job_host_summaries', + on_delete=models.CASCADE, + editable=False, + ) + + +class JobEventBase(CreatedModifiedModel): ''' An event/message logged from the callback when running a job. ''' @@ -472,14 +589,14 @@ class JobEvent(BaseModel): # - playbook_on_start (once for each playbook file) # - playbook_on_vars_prompt (for each play, but before play starts, we # currently don't handle responding to these prompts) - # - playbook_on_play_start + # - playbook_on_play_start (once for each play) # - playbook_on_import_for_host # - playbook_on_not_import_for_host # - playbook_on_no_hosts_matched # - playbook_on_no_hosts_remaining # - playbook_on_setup # - runner_on* - # - playbook_on_task_start + # - playbook_on_task_start (once for each task within a play) # - runner_on_failed # - runner_on_ok # - runner_on_error @@ -490,7 +607,7 @@ class JobEvent(BaseModel): # - runner_on_async_ok # - runner_on_async_failed # - runner_on_file_diff - # - playbook_on_notify + # - playbook_on_notify (once for each notification from the play) # - playbook_on_stats EVENT_TYPES = [ @@ -526,25 +643,16 @@ class JobEvent(BaseModel): LEVEL_FOR_EVENT = dict([(x[1], x[0]) for x in EVENT_TYPES]) class Meta: + abstract = True app_label = 'main' ordering = ('pk',) - job = models.ForeignKey( - 'Job', - related_name='job_events', - on_delete=models.CASCADE, - editable=False, - ) - created = models.DateTimeField( - #auto_now_add=True, - editable=False, - default=None, - ) - modified = models.DateTimeField( - #auto_now=True, - editable=False, - default=None, - ) + #job = models.ForeignKey( + # 'Job', + # related_name='job_events', + # on_delete=models.CASCADE, + # editable=False, + #) event = models.CharField( max_length=100, choices=EVENT_CHOICES, @@ -582,6 +690,12 @@ class JobEvent(BaseModel): default='', editable=False, ) + role = models.CharField( # FIXME: Determine from callback or task name. + max_length=1024, + blank=True, + default='', + editable=False, + ) task = models.CharField( max_length=1024, blank=True, @@ -742,15 +856,6 @@ class JobEvent(BaseModel): self.parent = self._find_parent() if 'parent' not in update_fields: update_fields.append('parent') - # Manually perform auto_now_add and auto_now logic (to allow overriding - # created timestamp for queued job events). - if not self.pk and not self.created: - self.created = now() - if 'created' not in update_fields: - update_fields.append('created') - self.modified = now() - if 'modified' not in update_fields: - update_fields.append('modified') super(JobEvent, self).save(*args, **kwargs) if post_process and not from_parent_update: self.update_parent_failed_and_changed() @@ -828,3 +933,56 @@ class JobEvent(BaseModel): host_summary.save(update_fields=update_fields) job.inventory.update_computed_fields() + +if getattr(settings, 'UNIFIED_JOBS_STEP') == 0: + + class JobEvent(JobEventBase): + + class Meta: + app_label = 'main' + ordering = ('pk',) + + job = models.ForeignKey( + 'Job', + related_name='job_events', + on_delete=models.CASCADE, + editable=False, + ) + new_job = models.ForeignKey( + 'JobNew', + related_name='new_job_events', + on_delete=models.CASCADE, + null=True, + default=None, + editable=False, + ) + +if getattr(settings, 'UNIFIED_JOBS_STEP') == 1: + + class JobEvent(JobEventBase): + + class Meta: + app_label = 'main' + ordering = ('pk',) + + new_job = models.ForeignKey( + 'JobNew', + related_name='new_job_events', + on_delete=models.CASCADE, + editable=False, + ) + +if getattr(settings, 'UNIFIED_JOBS_STEP') == 2: + + class JobEvent(JobEventBase): + + class Meta: + app_label = 'main' + ordering = ('pk',) + + job = models.ForeignKey( + 'Job', + related_name='job_events', + on_delete=models.CASCADE, + editable=False, + ) diff --git a/awx/main/models/organization.py b/awx/main/models/organization.py index eb7c4ddc6f..764187160f 100644 --- a/awx/main/models/organization.py +++ b/awx/main/models/organization.py @@ -37,12 +37,13 @@ __all__ = ['Organization', 'Team', 'Permission', 'Credential', 'Profile', 'AuthToken'] -class Organization(CommonModel): +class OrganizationBase(CommonModel): ''' An organization is the basic unit of multi-tenancy divisions ''' class Meta: + abstract = True app_label = 'main' users = models.ManyToManyField( @@ -55,11 +56,6 @@ class Organization(CommonModel): blank=True, related_name='admin_of_organizations', ) - projects = models.ManyToManyField( - 'Project', - blank=True, - related_name='organizations', - ) def get_absolute_url(self): return reverse('api:organization_detail', args=(self.pk,)) @@ -68,20 +64,61 @@ class Organization(CommonModel): return self.name -class Team(CommonModelNameNotUnique): +if getattr(settings, 'UNIFIED_JOBS_STEP') == 0: + + class Organization(OrganizationBase): + + class Meta: + app_label = 'main' + + projects = models.ManyToManyField( + 'Project', + blank=True, + related_name='organizations', + ) + new_projects = models.ManyToManyField( + 'ProjectNew', + blank=True, + related_name='organizations', + ) + +if getattr(settings, 'UNIFIED_JOBS_STEP') == 1: + + class Organization(OrganizationBase): + + class Meta: + app_label = 'main' + + new_projects = models.ManyToManyField( + 'ProjectNew', + blank=True, + related_name='organizations', + ) + +if getattr(settings, 'UNIFIED_JOBS_STEP') == 2: + + class Organization(OrganizationBase): + + class Meta: + app_label = 'main' + + projects = models.ManyToManyField( + 'Project', + blank=True, + related_name='organizations', + ) + + +class TeamBase(CommonModelNameNotUnique): ''' A team is a group of users that work on common projects. ''' class Meta: + abstract = True app_label = 'main' unique_together = [('organization', 'name')] - projects = models.ManyToManyField( - 'Project', - blank=True, - related_name='teams', - ) users = models.ManyToManyField( 'auth.User', blank=True, @@ -99,12 +136,61 @@ class Team(CommonModelNameNotUnique): return reverse('api:team_detail', args=(self.pk,)) -class Permission(CommonModelNameNotUnique): +if getattr(settings, 'UNIFIED_JOBS_STEP') == 0: + + class Team(TeamBase): + + class Meta: + app_label = 'main' + unique_together = [('organization', 'name')] + + projects = models.ManyToManyField( + 'Project', + blank=True, + related_name='teams', + ) + new_projects = models.ManyToManyField( + 'ProjectNew', + blank=True, + related_name='teams', + ) + +if getattr(settings, 'UNIFIED_JOBS_STEP') == 1: + + class Team(TeamBase): + + class Meta: + app_label = 'main' + unique_together = [('organization', 'name')] + + new_projects = models.ManyToManyField( + 'ProjectNew', + blank=True, + related_name='teams', + ) + +if getattr(settings, 'UNIFIED_JOBS_STEP') == 2: + + class Team(TeamBase): + + class Meta: + app_label = 'main' + unique_together = [('organization', 'name')] + + projects = models.ManyToManyField( + 'Project', + blank=True, + related_name='teams', + ) + + +class PermissionBase(CommonModelNameNotUnique): ''' A permission allows a user, project, or team to be able to use an inventory source. ''' class Meta: + abstract = True app_label = 'main' # permissions are granted to either a user or a team: @@ -112,7 +198,7 @@ class Permission(CommonModelNameNotUnique): team = models.ForeignKey('Team', null=True, on_delete=models.SET_NULL, blank=True, related_name='permissions') # to be used against a project or inventory (or a project and inventory in conjunction): - project = models.ForeignKey('Project', null=True, on_delete=models.SET_NULL, blank=True, related_name='permissions') + #project = models.ForeignKey('Project', null=True, on_delete=models.SET_NULL, blank=True, related_name='permissions') inventory = models.ForeignKey('Inventory', null=True, on_delete=models.SET_NULL, related_name='permissions') # permission system explanation: @@ -143,6 +229,59 @@ class Permission(CommonModelNameNotUnique): return reverse('api:permission_detail', args=(self.pk,)) +if getattr(settings, 'UNIFIED_JOBS_STEP') == 0: + + class Permission(PermissionBase): + + class Meta: + app_label = 'main' + + project = models.ForeignKey( + 'Project', + null=True, + on_delete=models.SET_NULL, + blank=True, + related_name='permissions', + ) + new_project = models.ForeignKey( + 'ProjectNew', + null=True, + on_delete=models.SET_NULL, + blank=True, + related_name='permissions', + ) + +if getattr(settings, 'UNIFIED_JOBS_STEP') == 1: + + class Permission(PermissionBase): + + class Meta: + app_label = 'main' + + new_project = models.ForeignKey( + 'ProjectNew', + null=True, + on_delete=models.SET_NULL, + blank=True, + related_name='permissions', + ) + +if getattr(settings, 'UNIFIED_JOBS_STEP') == 2: + + class Permission(PermissionBase): + + class Meta: + app_label = 'main' + + project = models.ForeignKey( + 'Project', + null=True, + on_delete=models.SET_NULL, + blank=True, + related_name='permissions', + ) + + class Credential(CommonModelNameNotUnique): ''' A credential contains information about how to talk to a remote resource @@ -370,7 +509,8 @@ class Credential(CommonModelNameNotUnique): update_fields.append(field) self.save(update_fields=update_fields) -class Profile(BaseModel): + +class Profile(CreatedModifiedModel): ''' Profile model related to User object. Currently stores LDAP DN for users loaded from LDAP. @@ -379,12 +519,6 @@ class Profile(BaseModel): class Meta: app_label = 'main' - created = models.DateTimeField( - auto_now_add=True, - ) - modified = models.DateTimeField( - auto_now=True, - ) user = AutoOneToOneField( 'auth.User', related_name='profile', @@ -395,6 +529,7 @@ class Profile(BaseModel): default='', ) + class AuthToken(BaseModel): ''' Custom authentication tokens per user with expiration and request-specific @@ -459,10 +594,12 @@ def user_mark_inactive(user, save=True): '''Use instead of delete to rename and mark users inactive.''' if user.is_active: # Set timestamp to datetime.isoformat() but without the time zone - # offse to stay withint the 30 character username limit. - deleted_ts = now().strftime('%Y-%m-%dT%H:%M:%S.%f') + # offset to stay withint the 30 character username limit. + dtnow = now() + deleted_ts = dtnow.strftime('%Y-%m-%dT%H:%M:%S.%f') user.username = '_d_%s' % deleted_ts user.is_active = False if save: user.save() + User.add_to_class('mark_inactive', user_mark_inactive) diff --git a/awx/main/models/projects.py b/awx/main/models/projects.py index 4f36f00405..3c366c828a 100644 --- a/awx/main/models/projects.py +++ b/awx/main/models/projects.py @@ -29,25 +29,13 @@ from django.utils.timezone import now, make_aware, get_default_timezone # AWX from awx.lib.compat import slugify from awx.main.models.base import * +from awx.main.models.unified_jobs import * from awx.main.utils import update_scm_url __all__ = ['Project', 'ProjectUpdate'] +class ProjectOptions(models.Model): -class Project(CommonModel): - ''' - A project represents a playbook git repo that can access a set of inventories - ''' - - PROJECT_STATUS_CHOICES = [ - ('ok', 'OK'), - ('missing', 'Missing'), - ('never updated', 'Never Updated'), - ('updating', 'Updating'), - ('failed', 'Failed'), - ('successful', 'Successful'), - ] - SCM_TYPE_CHOICES = [ ('', _('Manual')), ('git', _('Git')), @@ -56,10 +44,7 @@ class Project(CommonModel): ] class Meta: - app_label = 'main' - - # this is not part of the project, but managed with perms - # inventories = models.ManyToManyField('Inventory', blank=True, related_name='projects') + abstract = True # Project files must be available on the server in folders directly # beneath the path specified by settings.PROJECTS_ROOT. There is no way @@ -111,50 +96,13 @@ class Project(CommonModel): scm_delete_on_update = models.BooleanField( default=False, ) - scm_delete_on_next_update = models.BooleanField( - default=False, - editable=False, - ) - scm_update_on_launch = models.BooleanField( - default=False, - ) credential = models.ForeignKey( 'Credential', - related_name='projects', + related_name='%(class)ss', blank=True, null=True, default=None, ) - current_update = models.ForeignKey( - 'ProjectUpdate', - null=True, - default=None, - editable=False, - related_name='project_as_current_update+', - ) - last_update = models.ForeignKey( - 'ProjectUpdate', - null=True, - default=None, - editable=False, - related_name='project_as_last_update+', - ) - last_update_failed = models.BooleanField( - default=False, - editable=False, - ) - last_updated = models.DateTimeField( - null=True, - default=None, - editable=False, - ) - status = models.CharField( - max_length=32, - choices=PROJECT_STATUS_CHOICES, - default='ok', - editable=False, - null=True, # FIXME: Remove - ) def clean_scm_type(self): return self.scm_type or '' @@ -199,6 +147,30 @@ class Project(CommonModel): pass return cred + +class ProjectBase(ProjectOptions): + ''' + A project represents a playbook git repo that can access a set of inventories + ''' + + class Meta: + app_label = 'main' + abstract = True + + # this is not part of the project, but managed with perms + # inventories = models.ManyToManyField('Inventory', blank=True, related_name='projects') + + scm_delete_on_next_update = models.BooleanField( + default=False, + editable=False, + ) + scm_update_on_launch = models.BooleanField( + default=False, + ) + scm_update_cache_timeout = models.PositiveIntegerField( + default=0, + ) + def save(self, *args, **kwargs): new_instance = not bool(self.pk) # If update_fields has been specified, add our field names to it, @@ -284,13 +256,13 @@ class Project(CommonModel): def update_signature(self, **kwargs): if self.can_update: - project_update = self.project_updates.create() + project_update = self.project_updates.create() # FIXME: Copy options to ProjectUpdate project_update_sig = project_update.start_signature() return (project_update, project_update_sig) def update(self, **kwargs): if self.can_update: - project_update = self.project_updates.create() + project_update = self.project_updates.create() # FIXME: Copy options to ProjectUpdate project_update.start() return project_update @@ -337,20 +309,84 @@ class Project(CommonModel): results.append(playbook) return results -class ProjectUpdate(CommonTask): + +if getattr(settings, 'UNIFIED_JOBS_STEP') == 0: + + class Project(CommonModel, ProjectBase): + + PROJECT_STATUS_CHOICES = [ + ('ok', 'OK'), + ('missing', 'Missing'), + ('never updated', 'Never Updated'), + ('updating', 'Updating'), + ('failed', 'Failed'), + ('successful', 'Successful'), + ] + + class Meta: + app_label = 'main' + + current_update = models.ForeignKey( + 'ProjectUpdate', + null=True, + default=None, + editable=False, + related_name='project_as_current_update+', + ) + last_update = models.ForeignKey( + 'ProjectUpdate', + null=True, + default=None, + editable=False, + related_name='project_as_last_update+', + ) + last_update_failed = models.BooleanField( + default=False, + editable=False, + ) + last_updated = models.DateTimeField( + null=True, + default=None, + editable=False, + ) + status = models.CharField( + max_length=32, + choices=PROJECT_STATUS_CHOICES, + default='ok', + editable=False, + null=True, # FIXME: Remove + ) + +if getattr(settings, 'UNIFIED_JOBS_STEP') in (0, 1): + + class ProjectNew(UnifiedJobTemplate, ProjectBase): + + class Meta: + app_label = 'main' + +if getattr(settings, 'UNIFIED_JOBS_STEP') == 1: + + class Project(ProjectNew): + + class Meta: + proxy = True + +if getattr(settings, 'UNIFIED_JOBS_STEP') == 2: + + class Project(UnifiedJobTemplate, ProjectBase): + + class Meta: + app_label = 'main' + + +class ProjectUpdateBase(ProjectOptions): ''' Internal job for tracking project updates from SCM. ''' class Meta: app_label = 'main' - - project = models.ForeignKey( - 'Project', - related_name='project_updates', - on_delete=models.CASCADE, - editable=False, - ) + abstract = True def get_absolute_url(self): return reverse('api:project_update_detail', args=(self.pk,)) @@ -380,3 +416,53 @@ class ProjectUpdate(CommonTask): 'last_update', 'last_update_failed', 'scm_delete_on_next_update']) + + +if getattr(settings, 'UNIFIED_JOBS_STEP') == 0: + + class ProjectUpdate(CommonTask, ProjectUpdateBase): + + class Meta: + app_label = 'main' + + project = models.ForeignKey( + 'Project', + related_name='project_updates', + on_delete=models.CASCADE, + editable=False, + ) + +if getattr(settings, 'UNIFIED_JOBS_STEP') in (0, 1): + + class ProjectUpdateNew(UnifiedJob, ProjectUpdateBase): + + class Meta: + app_label = 'main' + + project = models.ForeignKey( + 'ProjectNew', + related_name='project_updates', + on_delete=models.CASCADE, + editable=False, + ) + +if getattr(settings, 'UNIFIED_JOBS_STEP') == 1: + + class ProjectUpdate(ProjectUpdateNew): + + class Meta: + proxy = True + +if getattr(settings, 'UNIFIED_JOBS_STEP') == 2: + + class ProjectUpdate(UnifiedJob, ProjectUpdateBase): + + class Meta: + app_label = 'main' + + project = models.ForeignKey( + 'Project', + related_name='project_updates', + on_delete=models.CASCADE, + editable=False, + ) diff --git a/awx/main/models/schedules.py b/awx/main/models/schedules.py new file mode 100644 index 0000000000..44a9a969fa --- /dev/null +++ b/awx/main/models/schedules.py @@ -0,0 +1,42 @@ +# Copyright (c) 2014 AnsibleWorks, Inc. +# All Rights Reserved. + +import logging + +# Django +from django.db import models + +# AWX +from awx.main.models.base import * + + +logger = logging.getLogger('awx.main.models.schedule') + +__all__ = ['Schedule'] + +class ScheduleManager(models.Manager): + pass + +class Schedule(CommonModel): + + class Meta: + app_label = 'main' + + objects = ScheduleManager() + + job_template = models.ForeignKey( + 'UnifiedJobTemplate', + related_name='schedules', + on_delete=models.CASCADE, + ) + dtstart = models.DateTimeField( + + ) + dtend = models.DateTimeField( + null=True, + default=None, + editable=False + ) + rrule = models.CharField( + max_length=255, + ) diff --git a/awx/main/models/unified_jobs.py b/awx/main/models/unified_jobs.py new file mode 100644 index 0000000000..9673910e31 --- /dev/null +++ b/awx/main/models/unified_jobs.py @@ -0,0 +1,232 @@ +# Copyright (c) 2014 AnsibleWorks, Inc. +# All Rights Reserved. + +# Python +import json +import logging +import shlex +import os +import os.path + +# PyYAML +import yaml + +# Django +from django.conf import settings +from django.db import models +from django.db import transaction +from django.core.exceptions import ValidationError +from django.contrib.contenttypes.models import ContentType +from django.utils.translation import ugettext_lazy as _ +from django.utils.timezone import now + +# Django-JSONField +from jsonfield import JSONField + +# Django-Polymorphic +from polymorphic import PolymorphicModel + +# Django-Celery +from djcelery.models import TaskMeta + +# AWX +from awx.main.models.base import * + +logger = logging.getLogger('awx.main.models.unified_jobs') + + +class UnifiedJobTemplate(PolymorphicModel, CommonModelNameNotUnique): + ''' + Concrete base class for unified job templates. + ''' + + STATUS_CHOICES = [ + # from Project + ('ok', 'OK'), + ('missing', 'Missing'), + ('never updated', 'Never Updated'), + ('running', 'Running'), + ('failed', 'Failed'), + ('successful', 'Successful'), + # from InventorySource + ('none', _('No External Source')), + ('never updated', _('Never Updated')), + ('updating', _('Updating')), + #('failed', _('Failed')), + #('successful', _('Successful')), + ] + + + class Meta: + app_label = 'main' + unique_together = [('polymorphic_ctype', 'name')] + + old_pk = models.PositiveIntegerField( + null=True, + default=None, + editable=False, + ) + current_job = models.ForeignKey( # alias for current_update + 'UnifiedJob', + null=True, + default=None, + editable=False, + related_name='%(class)s_as_current_job+', + ) + last_job = models.ForeignKey( # alias for last_update + 'UnifiedJob', + null=True, + default=None, + editable=False, + related_name='%(class)s_as_last_job+', + ) + last_job_failed = models.BooleanField( # alias for last_update_failed + default=False, + editable=False, + ) + last_job_run = models.DateTimeField( # alias for last_updated + null=True, + default=None, + editable=False, + ) + has_schedules = models.BooleanField( + default=False, + editable=False, + ) + #on_missed_schedule = models.CharField( + # max_length=32, + # choices=[], + #) + next_job_run = models.DateTimeField( # FIXME: Calculate from schedule. + null=True, + default=None, + editable=False, + ) + status = models.CharField( + max_length=32, + choices=STATUS_CHOICES, + default='ok', + editable=False, + ) + + # FIXME: Include code common to Project/InventorySource/JobTemplate + + +class UnifiedJob(PolymorphicModel, PrimordialModel): + ''' + Concrete base class for unified job run by the task engine. + ''' + + LAUNCH_TYPE_CHOICES = [ + ('manual', _('Manual')), + ('callback', _('Callback')), + ('scheduled', _('Scheduled')), + ('dependency', _('Dependency')), + ] + + class Meta: + app_label = 'main' + + old_pk = models.PositiveIntegerField( + null=True, + default=None, + editable=False, + ) + unified_job_template = models.ForeignKey( + 'UnifiedJobTemplate', + null=True, # Some jobs can be run without a template. + default=None, + editable=False, + related_name='%(class)s_unified_jobs', + ) + launch_type = models.CharField( + max_length=20, + choices=LAUNCH_TYPE_CHOICES, + default='manual', + editable=False, + ) + schedule = models.ForeignKey( + 'Schedule', + null=True, + default=None, + editable=False, + ) + depends_on = models.ManyToManyField( + 'self', + editable=False, + related_name='%(class)s_blocked_by+', + ) + + cancel_flag = models.BooleanField( + blank=True, + default=False, + editable=False, + ) + status = models.CharField( + max_length=20, + choices=TASK_STATUS_CHOICES, + default='new', + editable=False, + ) + failed = models.BooleanField( + default=False, + editable=False, + ) + started = models.DateTimeField( + null=True, + default=None, + editable=False, + ) + finished = models.DateTimeField( + null=True, + default=None, + editable=False, + ) + elapsed = models.DecimalField( + max_digits=12, + decimal_places=3, + editable=False, + ) + job_args = models.TextField( + blank=True, + default='', + editable=False, + ) + job_cwd = models.CharField( + max_length=1024, + blank=True, + default='', + editable=False, + ) + job_env = JSONField( + blank=True, + default={}, + editable=False, + ) + start_args = models.TextField( + blank=True, + default='', + editable=False, + ) + result_stdout_text = models.TextField( + blank=True, + default='', + editable=False, + ) + result_stdout_file = models.TextField( # FilePathfield? + blank=True, + default='', + editable=False, + ) + result_traceback = models.TextField( + blank=True, + default='', + editable=False, + ) + celery_task_id = models.CharField( + max_length=100, + blank=True, + default='', + editable=False, + ) + # FIXME: Add methods from CommonTask. diff --git a/awx/settings/defaults.py b/awx/settings/defaults.py index e83e465561..0b1f3693c1 100644 --- a/awx/settings/defaults.py +++ b/awx/settings/defaults.py @@ -134,6 +134,7 @@ INSTALLED_APPS = ( 'django_extensions', 'djcelery', 'kombu.transport.django', + 'polymorphic', 'taggit', 'awx.main', 'awx.api', @@ -303,6 +304,9 @@ AWX_TASK_ENV = {} # Flag to enable/disable updating hosts M2M when saving job events. CAPTURE_JOB_EVENT_HOSTS = False +# Flag to indicate which version of unified jobs model to use. +UNIFIED_JOBS_STEP = 2 + # Not possible to get list of regions without authenticating, so use this list # instead (based on docs from: # http://docs.rackspace.com/loadbalancers/api/v1.0/clb-devguide/content/Service_Access_Endpoints-d1e517.html) From 54c533d410a3fde021c498f4618d471a2ee3b190 Mon Sep 17 00:00:00 2001 From: Chris Church Date: Thu, 20 Mar 2014 19:16:58 -0400 Subject: [PATCH 4/7] AC-1040 Unified jobs updates to get unit tests to pass (hopefully). --- awx/api/serializers.py | 43 ++-- awx/api/views.py | 2 +- awx/main/access.py | 2 +- awx/main/fields.py | 1 + awx/main/migrations/0035_v148_changes.py | 104 ++++++++- awx/main/migrations/0037_v148_changes.py | 23 +- awx/main/models/activity_stream.py | 4 +- awx/main/models/inventory.py | 104 ++++----- awx/main/models/jobs.py | 24 ++- awx/main/models/projects.py | 96 ++++----- awx/main/models/schedules.py | 3 + awx/main/models/unified_jobs.py | 256 ++++++++++++++++++++++- awx/main/tests/base.py | 11 +- awx/main/tests/jobs.py | 2 +- awx/main/tests/projects.py | 4 +- awx/settings/local_settings.py.example | 6 +- 16 files changed, 519 insertions(+), 166 deletions(-) diff --git a/awx/api/serializers.py b/awx/api/serializers.py index 7d803ce4b8..f5383d94b8 100644 --- a/awx/api/serializers.py +++ b/awx/api/serializers.py @@ -339,7 +339,8 @@ class ProjectSerializer(BaseSerializer): 'scm_branch', 'scm_clean', 'scm_delete_on_update', 'scm_delete_on_next_update', 'scm_update_on_launch', 'credential', - 'last_update_failed', 'status', 'last_updated') + #'last_update_failed', 'status', 'last_updated') + 'last_job_failed', 'status', 'last_job_run') def get_related(self, obj): if obj is None: @@ -356,12 +357,17 @@ class ProjectSerializer(BaseSerializer): if obj.credential and obj.credential.active: res['credential'] = reverse('api:credential_detail', args=(obj.credential.pk,)) - if obj.current_update: - res['current_update'] = reverse('api:project_update_detail', - args=(obj.current_update.pk,)) - if obj.last_update: - res['last_update'] = reverse('api:project_update_detail', - args=(obj.last_update.pk,)) + #if obj.current_update: + # res['current_update'] = reverse('api:project_update_detail', + #if obj.last_update: + # res['last_update'] = reverse('api:project_update_detail', + # args=(obj.last_update.pk,)) + if obj.current_job: + res['current_job'] = reverse('api:project_update_detail', + args=(obj.current_job.pk,)) + if obj.last_job: + res['last_job'] = reverse('api:project_update_detail', + args=(obj.last_job.pk,)) return res def validate_local_path(self, attrs, source): @@ -694,8 +700,9 @@ class InventorySourceSerializer(BaseSerializer): fields = ('id', 'type', 'url', 'related', 'summary_fields', 'created', 'modified', 'inventory', 'group', 'source', 'source_path', 'source_vars', 'credential', 'source_regions', 'overwrite', - 'overwrite_vars', 'update_on_launch', 'update_interval', - 'last_update_failed', 'status', 'last_updated') + 'overwrite_vars', 'update_on_launch', #'update_interval', + #'last_update_failed', 'status', 'last_updated') + 'last_job_failed', 'status', 'last_job_run') read_only_fields = ('inventory', 'group') def get_related(self, obj): @@ -716,12 +723,18 @@ class InventorySourceSerializer(BaseSerializer): if obj.credential and obj.credential.active: res['credential'] = reverse('api:credential_detail', args=(obj.credential.pk,)) - if obj.current_update: - res['current_update'] = reverse('api:inventory_update_detail', - args=(obj.current_update.pk,)) - if obj.last_update: - res['last_update'] = reverse('api:inventory_update_detail', - args=(obj.last_update.pk,)) + #if obj.current_update: + # res['current_update'] = reverse('api:inventory_update_detail', + # args=(obj.current_update.pk,)) + #if obj.last_update: + # res['last_update'] = reverse('api:inventory_update_detail', + # args=(obj.last_update.pk,)) + if obj.current_job: + res['current_job'] = reverse('api:inventory_update_detail', + args=(obj.current_job.pk,)) + if obj.last_job: + res['last_job'] = reverse('api:inventory_update_detail', + args=(obj.last_job.pk,)) return res def get_summary_fields(self, obj): diff --git a/awx/api/views.py b/awx/api/views.py index 61f6a3edf4..d9f86d5717 100644 --- a/awx/api/views.py +++ b/awx/api/views.py @@ -389,7 +389,7 @@ class ProjectList(ListCreateAPIView): projects_qs = Project.objects.filter(active=True) projects_qs = projects_qs.select_related('current_update', 'last_updated') for project in projects_qs: - project.set_status_and_last_updated() + project._set_status_and_last_job_run() return super(ProjectList, self).get(request, *args, **kwargs) class ProjectDetail(RetrieveUpdateDestroyAPIView): diff --git a/awx/main/access.py b/awx/main/access.py index f799b7ada7..495f9d9af5 100644 --- a/awx/main/access.py +++ b/awx/main/access.py @@ -396,7 +396,7 @@ class GroupAccess(BaseAccess): def get_queryset(self): qs = self.model.objects.filter(active=True).distinct() - qs = qs.select_related('created_by', 'inventory', 'inventory_source') + qs = qs.select_related('created_by', 'inventory')#, 'inventory_source') qs = qs.prefetch_related('parents', 'children') inventories_qs = self.user.get_queryset(Inventory) return qs.filter(inventory__in=inventories_qs) diff --git a/awx/main/fields.py b/awx/main/fields.py index 5c4b07d1e3..683d89ee72 100644 --- a/awx/main/fields.py +++ b/awx/main/fields.py @@ -23,6 +23,7 @@ class AutoSingleRelatedObjectDescriptor(SingleRelatedObjectDescriptor): except self.related.model.DoesNotExist: obj = self.related.model(**{self.related.field.name: instance}) if self.related.field.rel.parent_link: + raise NotImplementedError('not supported with polymorphic!') for f in instance._meta.local_fields: setattr(obj, f.name, getattr(instance, f.name)) obj.save() diff --git a/awx/main/migrations/0035_v148_changes.py b/awx/main/migrations/0035_v148_changes.py index 9629ae38d0..b60eac4783 100644 --- a/awx/main/migrations/0035_v148_changes.py +++ b/awx/main/migrations/0035_v148_changes.py @@ -53,15 +53,36 @@ class Migration(DataMigration): new_ctype = orm['contenttypes.ContentType'].objects.get(app_label=orm.Project._meta.app_label, model=orm.Project._meta.module_name) for project in orm.Project.objects.order_by('pk'): d = self._get_dict_from_common_model(project) - d['polymorphic_ctype_id'] = new_ctype.pk + d.update({ + 'polymorphic_ctype_id': new_ctype.pk, + 'local_path': project.local_path, + 'scm_type': project.scm_type, + 'scm_url': project.scm_url, + 'scm_branch': project.scm_branch, + 'scm_clean': project.scm_clean, + 'scm_delete_on_update': project.scm_delete_on_update, + 'credential_id': project.credential_id, + 'scm_delete_on_next_update': project.scm_delete_on_next_update, + 'scm_update_on_launch': project.scm_update_on_launch, + }) new_project, created = orm.ProjectNew.objects.get_or_create(old_pk=project.pk, defaults=d) # Copy ProjectUpdate old to new. new_ctype = orm['contenttypes.ContentType'].objects.get(app_label=orm.ProjectUpdate._meta.app_label, model=orm.ProjectUpdate._meta.module_name) for project_update in orm.ProjectUpdate.objects.order_by('pk'): + project = project_update.project d = self._get_dict_from_common_task_model(project_update) - d['project_id'] = orm.ProjectNew.objects.get(old_pk=project_update.project_id).pk - d['polymorphic_ctype_id'] = new_ctype.pk + d.update({ + 'polymorphic_ctype_id': new_ctype.pk, + 'project_id': orm.ProjectNew.objects.get(old_pk=project_update.project_id).pk, + 'local_path': project.local_path, + 'scm_type': project.scm_type, + 'scm_url': project.scm_url, + 'scm_branch': project.scm_branch, + 'scm_clean': project.scm_clean, + 'scm_delete_on_update': project.scm_delete_on_update, + 'credential_id': project.credential_id, + }) new_project_update, created = orm.ProjectUpdateNew.objects.get_or_create(old_pk=project_update.pk, defaults=d) # Update Project last run. @@ -71,6 +92,9 @@ class Migration(DataMigration): new_project.current_job = orm.ProjectUpdateNew.objects.get(old_pk=project.current_update_id) if project.last_update: new_project.last_job = orm.ProjectUpdateNew.objects.get(old_pk=project.last_update_id) + new_project.last_job_failed = project.last_update_failed + new_project.last_job_run = project.last_updated + new_project.status = project.status new_project.save() # Update Organization projects. @@ -97,15 +121,38 @@ class Migration(DataMigration): new_ctype = orm['contenttypes.ContentType'].objects.get(app_label=orm.InventorySource._meta.app_label, model=orm.InventorySource._meta.module_name) for inventory_source in orm.InventorySource.objects.order_by('pk'): d = self._get_dict_from_common_model(inventory_source) - d['polymorphic_ctype_id'] = new_ctype.pk + d.update({ + 'polymorphic_ctype_id': new_ctype.pk, + 'source': inventory_source.source, + 'source_path': inventory_source.source_path, + 'source_vars': inventory_source.source_vars, + 'credential_id': inventory_source.credential_id, + 'source_regions': inventory_source.source_regions, + 'overwrite': inventory_source.overwrite, + 'overwrite_vars': inventory_source.overwrite_vars, + 'update_on_launch': inventory_source.update_on_launch, + 'inventory_id': inventory_source.inventory_id, + 'group_id': inventory_source.group_id, + }) new_inventory_source, created = orm.InventorySourceNew.objects.get_or_create(old_pk=inventory_source.pk, defaults=d) # Copy InventoryUpdate old to new. new_ctype = orm['contenttypes.ContentType'].objects.get(app_label=orm.InventoryUpdate._meta.app_label, model=orm.InventoryUpdate._meta.module_name) for inventory_update in orm.InventoryUpdate.objects.order_by('pk'): + inventory_source = inventory_update.inventory_source d = self._get_dict_from_common_task_model(inventory_update) - d['inventory_source_id'] = orm.InventorySourceNew.objects.get(old_pk=inventory_update.inventory_source_id).pk - d['polymorphic_ctype_id'] = new_ctype.pk + d.update({ + 'polymorphic_ctype_id': new_ctype.pk, + 'source': inventory_source.source, + 'source_path': inventory_source.source_path, + 'source_vars': inventory_source.source_vars, + 'credential_id': inventory_source.credential_id, + 'source_regions': inventory_source.source_regions, + 'overwrite': inventory_source.overwrite, + 'overwrite_vars': inventory_source.overwrite_vars, + 'inventory_source_id': orm.InventorySourceNew.objects.get(old_pk=inventory_update.inventory_source_id).pk, + 'license_error': inventory_update.license_error, + }) new_inventory_update, created = orm.InventoryUpdateNew.objects.get_or_create(old_pk=inventory_update.pk, defaults=d) # Update InventorySource last run. @@ -115,6 +162,9 @@ class Migration(DataMigration): new_inventory_source.current_job = orm.InventoryUpdateNew.objects.get(old_pk=inventory_source.current_update_id) if inventory_source.last_update: new_inventory_source.last_job = orm.InventoryUpdateNew.objects.get(old_pk=inventory_source.last_update_id) + new_inventory_source.last_job_failed = inventory_source.last_update_failed + new_inventory_source.last_job_run = inventory_source.last_updated + new_inventory_source.status = inventory_source.status new_inventory_source.save() # Update Group inventory_sources. @@ -133,20 +183,57 @@ class Migration(DataMigration): new_ctype = orm['contenttypes.ContentType'].objects.get(app_label=orm.JobTemplate._meta.app_label, model=orm.JobTemplate._meta.module_name) for job_template in orm.JobTemplate.objects.order_by('pk'): d = self._get_dict_from_common_model(job_template) + d.update({ + 'polymorphic_ctype_id': new_ctype.pk, + 'job_type': job_template.job_type, + 'inventory_id': job_template.inventory_id, + 'playbook': job_template.playbook, + 'credential_id': job_template.credential_id, + 'cloud_credential_id': job_template.cloud_credential_id, + 'forks': job_template.forks, + 'limit': job_template.limit, + 'extra_vars': job_template.extra_vars, + 'job_tags': job_template.job_tags, + 'host_config_key': job_template.host_config_key, + }) if job_template.project: d['project_id'] = orm.ProjectNew.objects.get(old_pk=job_template.project_id).pk - d['polymorphic_ctype_id'] = new_ctype.pk new_job_template, created = orm.JobTemplateNew.objects.get_or_create(old_pk=job_template.pk, defaults=d) # Copy Job old to new. new_ctype = orm['contenttypes.ContentType'].objects.get(app_label=orm.Job._meta.app_label, model=orm.Job._meta.module_name) for job in orm.Job.objects.order_by('pk'): d = self._get_dict_from_common_task_model(job) + d.update({ + 'polymorphic_ctype_id': new_ctype.pk, + 'job_type': job_template.job_type, + 'inventory_id': job_template.inventory_id, + 'playbook': job_template.playbook, + 'credential_id': job_template.credential_id, + 'cloud_credential_id': job_template.cloud_credential_id, + 'forks': job_template.forks, + 'limit': job_template.limit, + 'extra_vars': job_template.extra_vars, + 'job_tags': job_template.job_tags, + }) if job.project: d['project_id'] = orm.ProjectNew.objects.get(old_pk=job.project_id).pk - d['polymorphic_ctype_id'] = new_ctype.pk + if job.job_template: + d['job_template_id'] = orm.JobTemplateNew.objects.get(old_pk=job.job_template_id).pk new_job, created = orm.JobNew.objects.get_or_create(old_pk=job.pk, defaults=d) + # Update JobTemplate last run. + for new_job_template in orm.JobTemplateNew.objects.order_by('pk'): + try: + new_last_job = new_job_template.jobs.order_by('-pk')[0] + new_job_template.last_job = new_last_job + new_job_template.last_job_failed = new_last_job.failed + new_job_template.last_job_run = new_last_job.finished + new_job_template.status = 'failed' if new_last_job.failed else 'successful' + except IndexError: + new_job_template.status = 'never updated' + new_inventory_source.save() + # Update JobHostSummary job. for job_host_summary in orm.JobHostSummary.objects.order_by('pk'): new_job = orm.JobNew.objects.get(old_pk=job_host_summary.job_id) @@ -192,6 +279,7 @@ class Migration(DataMigration): "Write your backwards methods here." # FIXME: Would like to have this, but not required. + raise NotImplementedError() models = { u'auth.group': { diff --git a/awx/main/migrations/0037_v148_changes.py b/awx/main/migrations/0037_v148_changes.py index 40cb63e232..fb8a90b956 100644 --- a/awx/main/migrations/0037_v148_changes.py +++ b/awx/main/migrations/0037_v148_changes.py @@ -7,7 +7,7 @@ from django.db import models class Migration(SchemaMigration): ''' - Rename tables to be consistent with model names. + Rename tables/columns to be consistent with model/field names. ''' def forwards(self, orm): @@ -19,41 +19,60 @@ class Migration(SchemaMigration): db.rename_table(u'main_jobnew', 'main_job') db.rename_table(db.shorten_name(u'main_team_new_projects'), db.shorten_name(u'main_team_projects')) + db.rename_column(db.shorten_name(u'main_team_projects'), 'projectnew_id', 'project_id') db.rename_table(db.shorten_name(u'main_organization_new_projects'), db.shorten_name(u'main_organization_projects')) + db.rename_column(db.shorten_name(u'main_organization_projects'), 'projectnew_id', 'project_id') db.rename_column(u'main_permission', 'new_project_id', 'project_id') db.rename_column(u'main_host', 'new_last_job_id', 'last_job_id') db.rename_table(db.shorten_name(u'main_host_new_inventory_sources'), db.shorten_name(u'main_host_inventory_sources')) + db.rename_column(db.shorten_name(u'main_host_inventory_sources'), 'inventorysourcenew_id', 'inventorysource_id') db.rename_table(db.shorten_name(u'main_group_new_inventory_sources'), db.shorten_name(u'main_group_inventory_sources')) + db.rename_column(db.shorten_name(u'main_group_inventory_sources'), 'inventorysourcenew_id', 'inventorysource_id') db.rename_column(u'main_jobhostsummary', 'new_job_id', 'job_id') db.rename_column(u'main_jobevent', 'new_job_id', 'job_id') db.rename_table(db.shorten_name(u'main_activitystream_new_project'), db.shorten_name(u'main_activitystream_project')) + db.rename_column(db.shorten_name(u'main_activitystream_project'), 'projectnew_id', 'project_id') db.rename_table(db.shorten_name(u'main_activitystream_new_project_update'), db.shorten_name(u'main_activitystream_project_update')) + db.rename_column(db.shorten_name(u'main_activitystream_project_update'), 'projectupdatenew_id', 'projectupdate_id') db.rename_table(db.shorten_name(u'main_activitystream_new_inventory_source'), db.shorten_name(u'main_activitystream_inventory_source')) + db.rename_column(db.shorten_name(u'main_activitystream_inventory_source'), 'inventorysourcenew_id', 'inventorysource_id') db.rename_table(db.shorten_name(u'main_activitystream_new_inventory_update'), db.shorten_name(u'main_activitystream_inventory_update')) + db.rename_column(db.shorten_name(u'main_activitystream_inventory_update'), 'inventoryupdatenew_id', 'inventoryupdate_id') db.rename_table(db.shorten_name(u'main_activitystream_new_job_template'), db.shorten_name(u'main_activitystream_job_template')) + db.rename_column(db.shorten_name(u'main_activitystream_job_template'), 'jobtemplatenew_id', 'jobtemplate_id') db.rename_table(db.shorten_name(u'main_activitystream_new_job'), db.shorten_name(u'main_activitystream_job')) + db.rename_column(db.shorten_name(u'main_activitystream_job'), 'jobnew_id', 'job_id') def backwards(self, orm): + db.rename_column(db.shorten_name(u'main_activitystream_job'), 'job_id', 'jobnew_id') db.rename_table(db.shorten_name(u'main_activitystream_job'), db.shorten_name(u'main_activitystream_new_job')) + db.rename_column(db.shorten_name(u'main_activitystream_job_template'), 'jobtemplate_id', 'jobtemplatenew_id') db.rename_table(db.shorten_name(u'main_activitystream_job_template'), db.shorten_name(u'main_activitystream_new_job_template')) + db.rename_column(db.shorten_name(u'main_activitystream_inventory_update'), 'inventoryupdate_id', 'inventoryupdatenew_id') db.rename_table(db.shorten_name(u'main_activitystream_inventory_update'), db.shorten_name(u'main_activitystream_new_inventory_update')) + db.rename_column(db.shorten_name(u'main_activitystream_inventory_source'), 'inventorysource_id', 'inventorysourcenew_id') db.rename_table(db.shorten_name(u'main_activitystream_inventory_source'), db.shorten_name(u'main_activitystream_new_inventory_source')) + db.rename_column(db.shorten_name(u'main_activitystream_project_update'), 'projectupdate_id', 'projectupdatenew_id') db.rename_table(db.shorten_name(u'main_activitystream_project_update'), db.shorten_name(u'main_activitystream_new_project_update')) + db.rename_column(db.shorten_name(u'main_activitystream_project'), 'project_id', 'projectnew_id') db.rename_table(db.shorten_name(u'main_activitystream_project'), db.shorten_name(u'main_activitystream_new_project')) db.rename_column(u'main_jobevent', 'job_id', 'new_job_id') db.rename_column(u'main_jobhostsummary', 'job_id', 'new_job_id') - + db.rename_column(db.shorten_name(u'main_group_inventory_sources'), 'inventorysource_id', 'inventorysourcenew_id') db.rename_table(db.shorten_name(u'main_group_inventory_sources'), db.shorten_name(u'main_group_new_inventory_sources')) + db.rename_column(db.shorten_name(u'main_host_inventory_sources'), 'inventorysource_id', 'inventorysourcenew_id') db.rename_table(db.shorten_name(u'main_host_inventory_sources'), db.shorten_name(u'main_host_new_inventory_sources')) db.rename_column(u'main_host', 'last_job_id', 'new_last_job_id') db.rename_column(u'main_permission', 'project_id', 'new_project_id') + db.rename_column(db.shorten_name(u'main_organization_projects'), 'project_id', 'projectnew_id') db.rename_table(db.shorten_name(u'main_organization_projects'), db.shorten_name(u'main_organization_new_projects')) + db.rename_column(db.shorten_name(u'main_team_projects'), 'project_id', 'projectnew_id') db.rename_table(db.shorten_name(u'main_team_projects'), db.shorten_name(u'main_team_new_projects')) db.rename_table(u'main_job', 'main_jobnew') diff --git a/awx/main/models/activity_stream.py b/awx/main/models/activity_stream.py index d25b2220fc..65f1818748 100644 --- a/awx/main/models/activity_stream.py +++ b/awx/main/models/activity_stream.py @@ -58,12 +58,12 @@ class ActivityStreamBase(models.Model): # For compatibility with Django 1.4.x, attempt to handle any calls to # save that pass update_fields. try: - super(ActivityStream, self).save(*args, **kwargs) + super(ActivityStreamBase, self).save(*args, **kwargs) except TypeError: if 'update_fields' not in kwargs: raise kwargs.pop('update_fields') - super(ActivityStream, self).save(*args, **kwargs) + super(ActivityStreamBase, self).save(*args, **kwargs) if getattr(settings, 'UNIFIED_JOBS_STEP') == 0: diff --git a/awx/main/models/inventory.py b/awx/main/models/inventory.py index ed82395829..02c5e92e82 100644 --- a/awx/main/models/inventory.py +++ b/awx/main/models/inventory.py @@ -129,7 +129,8 @@ class Inventory(CommonModel): active_groups = self.groups.filter(active=True) failed_groups = active_groups.filter(has_active_failures=True) active_inventory_sources = self.inventory_sources.filter(active=True, source__in=CLOUD_INVENTORY_SOURCES) - failed_inventory_sources = active_inventory_sources.filter(last_update_failed=True) + #failed_inventory_sources = active_inventory_sources.filter(last_update_failed=True) + failed_inventory_sources = active_inventory_sources.filter(last_job_failed=True) computed_fields = { 'has_active_failures': bool(failed_hosts.count()), 'total_hosts': active_hosts.count(), @@ -229,7 +230,7 @@ class HostBase(CommonModelNameNotUnique): When marking hosts inactive, remove all associations to related inventory sources. ''' - super(Host, self).mark_inactive(save=save) + super(HostBase, self).mark_inactive(save=save) self.inventory_sources.clear() def update_computed_fields(self, update_inventory=True, update_groups=True): @@ -453,7 +454,7 @@ class GroupBase(CommonModelNameNotUnique): groups/hosts/inventory_sources. ''' def mark_actual(): - super(Group, self).mark_inactive(save=save) + super(GroupBase, self).mark_inactive(save=save) self.inventory_source.mark_inactive(save=save) self.inventory_sources.clear() self.parents.clear() @@ -670,20 +671,6 @@ class InventorySourceOptions(BaseModel): help_text=_('Overwrite local variables from remote inventory source.'), ) - -class InventorySourceBase(InventorySourceOptions): - - class Meta: - abstract = True - app_label = 'main' - - update_on_launch = models.BooleanField( - default=False, - ) - update_cache_timeout = models.PositiveIntegerField( - default=0, - ) - @classmethod def get_ec2_region_choices(cls): ec2_region_names = getattr(settings, 'EC2_REGION_NAMES', {}) @@ -754,57 +741,46 @@ class InventorySourceBase(InventorySourceOptions): ', '.join(invalid_regions))) return ','.join(regions) + +class InventorySourceBase(InventorySourceOptions): + + class Meta: + abstract = True + app_label = 'main' + + update_on_launch = models.BooleanField( + default=False, + ) + update_cache_timeout = models.PositiveIntegerField( + default=0, + ) + + +class InventorySourceBaseMethods(object): + def save(self, *args, **kwargs): - new_instance = not bool(self.pk) # 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', []) - # Update status and last_updated fields. - updated_fields = self.set_status_and_last_updated(save=False) - for field in updated_fields: - if field not in update_fields: - update_fields.append(field) # Update inventory from group (if available). if self.group and not self.inventory: self.inventory = self.group.inventory if 'inventory' not in update_fields: update_fields.append('inventory') + # Set name automatically. + if not self.name: + self.name = 'inventory_source %s' % now() + if 'name' not in update_fields: + update_fields.append('name') # Do the actual save. - super(InventorySource, self).save(*args, **kwargs) + super(InventorySourceBaseMethods, self).save(*args, **kwargs) source_vars_dict = VarsDictProperty('source_vars') - def set_status_and_last_updated(self, save=True): - # Determine current status. - if self.source: - if self.current_update: - status = 'updating' - elif not self.last_update: - status = 'never updated' - elif self.last_update_failed: - status = 'failed' - else: - status = 'successful' - else: - status = 'none' - # Determine current last_updated timestamp. - last_updated = None - if self.source and self.last_update: - last_updated = self.last_update.modified - # Update values if changed. - update_fields = [] - if self.status != status: - self.status = status - update_fields.append('status') - if self.last_updated != last_updated: - self.last_updated = last_updated - update_fields.append('last_updated') - if save and update_fields: - self.save(update_fields=update_fields) - return update_fields + def get_absolute_url(self): + return reverse('api:inventory_source_detail', args=(self.pk,)) - @property - def can_update(self): + def _can_update(self): # FIXME: Prevent update when another one is active! return bool(self.source) @@ -820,13 +796,10 @@ class InventorySourceBase(InventorySourceOptions): inventory_update.start() return inventory_update - def get_absolute_url(self): - return reverse('api:inventory_source_detail', args=(self.pk,)) - if getattr(settings, 'UNIFIED_JOBS_STEP') == 0: - class InventorySource(PrimordialModel, InventorySourceBase): + class InventorySource(InventorySourceBaseMethods, PrimordialModel, InventorySourceBase): INVENTORY_SOURCE_STATUS_CHOICES = [ ('none', _('No External Source')), @@ -886,7 +859,7 @@ if getattr(settings, 'UNIFIED_JOBS_STEP') == 0: if getattr(settings, 'UNIFIED_JOBS_STEP') in (0, 1): - class InventorySourceNew(UnifiedJobTemplate, InventorySourceBase): + class InventorySourceNew(InventorySourceBaseMethods, UnifiedJobTemplate, InventorySourceBase): class Meta: app_label = 'main' @@ -916,7 +889,7 @@ if getattr(settings, 'UNIFIED_JOBS_STEP') == 1: if getattr(settings, 'UNIFIED_JOBS_STEP') == 2: - class InventorySource(UnifiedJobTemplate, InventorySourceBase): + class InventorySource(InventorySourceBaseMethods, UnifiedJobTemplate, InventorySourceBase): class Meta: app_label = 'main' @@ -952,6 +925,9 @@ class InventoryUpdateBase(InventorySourceOptions): editable=False, ) + +class InventoryUpdateBaseMethods(object): + def save(self, *args, **kwargs): update_fields = kwargs.get('update_fields', []) if bool('license' in self.result_stdout and @@ -959,7 +935,7 @@ class InventoryUpdateBase(InventorySourceOptions): self.license_error = True if 'license_error' not in update_fields: update_fields.append('license_error') - super(InventoryUpdate, self).save(*args, **kwargs) + super(InventoryUpdateBaseMethods, self).save(*args, **kwargs) def _get_parent_instance(self): return self.inventory_source @@ -974,7 +950,7 @@ class InventoryUpdateBase(InventorySourceOptions): if getattr(settings, 'UNIFIED_JOBS_STEP') == 0: - class InventoryUpdate(CommonTask, InventoryUpdateBase): + class InventoryUpdate(InventoryUpdateBaseMethods, CommonTask, InventoryUpdateBase): class Meta: app_label = 'main' @@ -988,7 +964,7 @@ if getattr(settings, 'UNIFIED_JOBS_STEP') == 0: if getattr(settings, 'UNIFIED_JOBS_STEP') in (0, 1): - class InventoryUpdateNew(UnifiedJob, InventoryUpdateBase): + class InventoryUpdateNew(InventoryUpdateBaseMethods, UnifiedJob, InventoryUpdateBase): class Meta: app_label = 'main' @@ -1009,7 +985,7 @@ if getattr(settings, 'UNIFIED_JOBS_STEP') == 1: if getattr(settings, 'UNIFIED_JOBS_STEP') == 2: - class InventoryUpdate(UnifiedJob, InventoryUpdateBase): + class InventoryUpdate(InventoryUpdateBaseMethods, UnifiedJob, InventoryUpdateBase): class Meta: app_label = 'main' diff --git a/awx/main/models/jobs.py b/awx/main/models/jobs.py index 45350dbd7f..75aa93f14e 100644 --- a/awx/main/models/jobs.py +++ b/awx/main/models/jobs.py @@ -29,6 +29,9 @@ from django.utils.timezone import now, make_aware, get_default_timezone # Django-JSONField from jsonfield import JSONField +# Django-Polymorphic +from polymorphic import PolymorphicModel + # AWX from awx.main.models.base import * from awx.main.models.unified_jobs import * @@ -138,6 +141,7 @@ class JobTemplateBase(JobOptions): default='', ) +class JobTemplateBaseMethods(object): def create_job(self, **kwargs): ''' @@ -181,7 +185,7 @@ class JobTemplateBase(JobOptions): if getattr(settings, 'UNIFIED_JOBS_STEP') == 0: - class JobTemplate(CommonModel, JobTemplateBase): + class JobTemplate(JobTemplateBaseMethods, CommonModel, JobTemplateBase): class Meta: app_label = 'main' @@ -195,7 +199,7 @@ if getattr(settings, 'UNIFIED_JOBS_STEP') == 0: if getattr(settings, 'UNIFIED_JOBS_STEP') in (0, 1): - class JobTemplateNew(UnifiedJobTemplate, JobTemplateBase): + class JobTemplateNew(JobTemplateBaseMethods, UnifiedJobTemplate, JobTemplateBase): class Meta: app_label = 'main' @@ -217,7 +221,8 @@ if getattr(settings, 'UNIFIED_JOBS_STEP') == 1: if getattr(settings, 'UNIFIED_JOBS_STEP') == 2: - class JobTemplate(UnifiedJobTemplate, JobTemplateBase): + #class JobTemplate(JobTemplateBase, UnifiedJobTemplate): + class JobTemplate(JobTemplateBaseMethods, UnifiedJobTemplate, JobTemplateBase): class Meta: app_label = 'main' @@ -249,6 +254,8 @@ class JobBase(JobOptions): through='JobHostSummary', ) +class JobBaseMethods(object): + def get_absolute_url(self): return reverse('api:job_detail', args=(self.pk,)) @@ -374,7 +381,7 @@ class JobBase(JobOptions): if getattr(settings, 'UNIFIED_JOBS_STEP') == 0: - class Job(CommonTask, JobBase): + class Job(JobBaseMethods, CommonTask, JobBase): LAUNCH_TYPE_CHOICES = [ ('manual', _('Manual')), @@ -408,7 +415,7 @@ if getattr(settings, 'UNIFIED_JOBS_STEP') == 0: if getattr(settings, 'UNIFIED_JOBS_STEP') in (0, 1): - class JobNew(UnifiedJob, JobBase): + class JobNew(JobBaseMethods, UnifiedJob, JobBase): class Meta: app_label = 'main' @@ -437,7 +444,8 @@ if getattr(settings, 'UNIFIED_JOBS_STEP') == 1: if getattr(settings, 'UNIFIED_JOBS_STEP') == 2: - class Job(UnifiedJob, JobBase): + #class Job(JobBase, UnifiedJob): + class Job(JobBaseMethods, UnifiedJob, JobBase): class Meta: app_label = 'main' @@ -504,7 +512,7 @@ class JobHostSummaryBase(CreatedModifiedModel): update_fields = kwargs.get('update_fields', []) self.failed = bool(self.dark or self.failures) update_fields.append('failed') - super(JobHostSummary, self).save(*args, **kwargs) + super(JobHostSummaryBase, self).save(*args, **kwargs) self.update_host_last_job_summary() def update_host_last_job_summary(self): @@ -856,7 +864,7 @@ class JobEventBase(CreatedModifiedModel): self.parent = self._find_parent() if 'parent' not in update_fields: update_fields.append('parent') - super(JobEvent, self).save(*args, **kwargs) + super(JobEventBase, self).save(*args, **kwargs) if post_process and not from_parent_update: self.update_parent_failed_and_changed() # FIXME: The update_hosts() call (and its queries) are the current diff --git a/awx/main/models/projects.py b/awx/main/models/projects.py index 3c366c828a..bd86ffb991 100644 --- a/awx/main/models/projects.py +++ b/awx/main/models/projects.py @@ -171,6 +171,9 @@ class ProjectBase(ProjectOptions): default=0, ) + +class ProjectBaseMethods(object): + def save(self, *args, **kwargs): new_instance = not bool(self.pk) # If update_fields has been specified, add our field names to it, @@ -178,7 +181,7 @@ class ProjectBase(ProjectOptions): update_fields = kwargs.get('update_fields', []) # Check if scm_type or scm_url changes. if self.pk: - project_before = Project.objects.get(pk=self.pk) + project_before = self.__class__.objects.get(pk=self.pk) if project_before.scm_type != self.scm_type or project_before.scm_url != self.scm_url: self.scm_delete_on_next_update = True if 'scm_delete_on_next_update' not in update_fields: @@ -189,13 +192,8 @@ class ProjectBase(ProjectOptions): self.local_path = u'_%d__%s' % (self.pk, slug_name) if 'local_path' not in update_fields: update_fields.append('local_path') - # Update status and last_updated fields. - updated_fields = self.set_status_and_last_updated(save=False) - for field in updated_fields: - if field not in update_fields: - update_fields.append(field) # Do the actual save. - super(Project, self).save(*args, **kwargs) + super(ProjectBaseMethods, self).save(*args, **kwargs) if new_instance: update_fields=[] # Generate local_path for SCM after initial save (so we have a PK). @@ -207,50 +205,37 @@ class ProjectBase(ProjectOptions): if new_instance and self.scm_type: self.update() - def set_status_and_last_updated(self, save=True): - # Determine current status. + def _get_current_status(self): if self.scm_type: if self.current_update: - status = 'updating' - elif not self.last_update: - status = 'never updated' - elif self.last_update_failed: - status = 'failed' + return 'updating' + elif not self.last_job: + return 'never updated' + elif self.last_job_failed: + return 'failed' elif not self.get_project_path(): - status = 'missing' + return 'missing' else: - status = 'successful' + return 'successful' elif not self.get_project_path(): - status = 'missing' + return 'missing' else: - status = 'ok' - # Determine current last_updated timestamp. - last_updated = None - if self.scm_type and self.last_update: - last_updated = self.last_update.modified + return 'ok' + + def _get_last_job_run(self): + if self.scm_type and self.last_job: + return self.last_job.finished else: project_path = self.get_project_path() if project_path: try: mtime = os.path.getmtime(project_path) dt = datetime.datetime.fromtimestamp(mtime) - last_updated = make_aware(dt, get_default_timezone()) + return make_aware(dt, get_default_timezone()) except os.error: pass - # Update values if changed. - update_fields = [] - if self.status != status: - self.status = status - update_fields.append('status') - if self.last_updated != last_updated: - self.last_updated = last_updated - update_fields.append('last_updated') - if save and update_fields: - self.save(update_fields=update_fields) - return update_fields - @property - def can_update(self): + def _can_update(self): # FIXME: Prevent update when another one is active! return bool(self.scm_type)# and not self.current_update) @@ -312,7 +297,7 @@ class ProjectBase(ProjectOptions): if getattr(settings, 'UNIFIED_JOBS_STEP') == 0: - class Project(CommonModel, ProjectBase): + class Project(ProjectBaseMethods, CommonModel, ProjectBase): PROJECT_STATUS_CHOICES = [ ('ok', 'OK'), @@ -359,7 +344,7 @@ if getattr(settings, 'UNIFIED_JOBS_STEP') == 0: if getattr(settings, 'UNIFIED_JOBS_STEP') in (0, 1): - class ProjectNew(UnifiedJobTemplate, ProjectBase): + class ProjectNew(ProjectBaseMethods, UnifiedJobTemplate, ProjectBase): class Meta: app_label = 'main' @@ -373,7 +358,7 @@ if getattr(settings, 'UNIFIED_JOBS_STEP') == 1: if getattr(settings, 'UNIFIED_JOBS_STEP') == 2: - class Project(UnifiedJobTemplate, ProjectBase): + class Project(ProjectBaseMethods, UnifiedJobTemplate, ProjectBase): class Meta: app_label = 'main' @@ -388,12 +373,15 @@ class ProjectUpdateBase(ProjectOptions): app_label = 'main' abstract = True - def get_absolute_url(self): - return reverse('api:project_update_detail', args=(self.pk,)) + +class ProjectUpdateBaseMethods(object): def _get_parent_instance(self): return self.project + def get_absolute_url(self): + return reverse('api:project_update_detail', args=(self.pk,)) + def _get_task_class(self): from awx.main.tasks import RunProjectUpdate return RunProjectUpdate @@ -402,25 +390,25 @@ class ProjectUpdateBase(ProjectOptions): parent_instance = self._get_parent_instance() if parent_instance: if self.status in ('pending', 'waiting', 'running'): - if parent_instance.current_update != self: - parent_instance.current_update = self - parent_instance.save(update_fields=['current_update']) + if parent_instance.current_job != self: + parent_instance.current_job = self + parent_instance.save(update_fields=['current_job']) elif self.status in ('successful', 'failed', 'error', 'canceled'): - if parent_instance.current_update == self: - parent_instance.current_update = None - parent_instance.last_update = self - parent_instance.last_update_failed = self.failed + if parent_instance.current_job == self: + parent_instance.current_job = None + parent_instance.last_job = self + parent_instance.last_job_failed = self.failed if not self.failed and parent_instance.scm_delete_on_next_update: parent_instance.scm_delete_on_next_update = False - parent_instance.save(update_fields=['current_update', - 'last_update', - 'last_update_failed', + parent_instance.save(update_fields=['current_job', + 'last_job', + 'last_job_failed', 'scm_delete_on_next_update']) if getattr(settings, 'UNIFIED_JOBS_STEP') == 0: - class ProjectUpdate(CommonTask, ProjectUpdateBase): + class ProjectUpdate(ProjectUpdateBaseMethods, CommonTask, ProjectUpdateBase): class Meta: app_label = 'main' @@ -434,7 +422,7 @@ if getattr(settings, 'UNIFIED_JOBS_STEP') == 0: if getattr(settings, 'UNIFIED_JOBS_STEP') in (0, 1): - class ProjectUpdateNew(UnifiedJob, ProjectUpdateBase): + class ProjectUpdateNew(ProjectUpdateBaseMethods, UnifiedJob, ProjectUpdateBase): class Meta: app_label = 'main' @@ -455,7 +443,7 @@ if getattr(settings, 'UNIFIED_JOBS_STEP') == 1: if getattr(settings, 'UNIFIED_JOBS_STEP') == 2: - class ProjectUpdate(UnifiedJob, ProjectUpdateBase): + class ProjectUpdate(ProjectUpdateBaseMethods, UnifiedJob, ProjectUpdateBase): class Meta: app_label = 'main' diff --git a/awx/main/models/schedules.py b/awx/main/models/schedules.py index 44a9a969fa..06da1ecdfe 100644 --- a/awx/main/models/schedules.py +++ b/awx/main/models/schedules.py @@ -40,3 +40,6 @@ class Schedule(CommonModel): rrule = models.CharField( max_length=255, ) + + def save(self, *args, **kwargs): + super(Schedule, self).save(*args, **kwargs) diff --git a/awx/main/models/unified_jobs.py b/awx/main/models/unified_jobs.py index 9673910e31..c26ef64ba7 100644 --- a/awx/main/models/unified_jobs.py +++ b/awx/main/models/unified_jobs.py @@ -108,8 +108,85 @@ class UnifiedJobTemplate(PolymorphicModel, CommonModelNameNotUnique): default='ok', editable=False, ) - - # FIXME: Include code common to Project/InventorySource/JobTemplate + + @property + def current_update(self): + return self.current_job + + @property + def last_update(self): + return self.last_job + + @property + def last_update_failed(self): + return self.last_job_failed + + @property + def last_updated(self): + return self.last_job_run + + def save(self, *args, **kwargs): + # 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', []) + # Update status and last_updated fields. + updated_fields = self._set_status_and_last_job_run(save=False) + for field in updated_fields: + if field not in update_fields: + update_fields.append(field) + # Do the actual save. + super(UnifiedJobTemplate, self).save(*args, **kwargs) + + def _get_current_status(self): + # Override in subclasses as needed. + if self.current_job: + return 'updating' + elif not self.last_job: + return 'never updated' + elif self.last_job_failed: + return 'failed' + else: + return 'successful' + + def _get_last_job_run(self): + # Override in subclasses as needed. + if self.last_job: + return self.last_job.finished + + def _set_status_and_last_job_run(self, save=True): + status = self._get_current_status() + last_job_run = self._get_last_job_run() + # Update values if changed. + update_fields = [] + if self.status != status: + self.status = status + update_fields.append('status') + if self.last_job_run != last_job_run: + self.last_job_run = last_job_run + update_fields.append('last_job_run') + if save and update_fields: + self.save(update_fields=update_fields) + return update_fields + + def _can_update(self): + # Override in subclasses as needed. + return False + + @property + def can_update(self): + return self._can_update() + + def update_signature(self, **kwargs): + raise NotImplementedError # Implement in subclass. + + def update(self, **kwargs): + raise NotImplementedError # Implement in subclass. + + def _get_child_queryset(self): + pass + + def _create_child_instance(self, **kwargs): + pass class UnifiedJob(PolymorphicModel, PrimordialModel): @@ -156,7 +233,6 @@ class UnifiedJob(PolymorphicModel, PrimordialModel): editable=False, related_name='%(class)s_blocked_by+', ) - cancel_flag = models.BooleanField( blank=True, default=False, @@ -229,4 +305,176 @@ class UnifiedJob(PolymorphicModel, PrimordialModel): default='', editable=False, ) - # FIXME: Add methods from CommonTask. + + def __unicode__(self): + return u'%s-%s-%s' % (self.created, self.id, self.status) + + def _get_parent_instance(self): + return self.job_template + + def _update_parent_instance(self): + parent_instance = self._get_parent_instance() + if parent_instance: + if self.status in ('pending', 'waiting', 'running'): + if parent_instance.current_job != self: + parent_instance.current_job = self + parent_instance.save(update_fields=['current_job']) + elif self.status in ('successful', 'failed', 'error', 'canceled'): + if parent_instance.current_job == self: + parent_instance.current_job = None + parent_instance.last_job = self + parent_instance.last_job_failed = self.failed + parent_instance.save(update_fields=['current_job', + 'last_job', + 'last_job_failed']) + + def save(self, *args, **kwargs): + # 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 self.pk: + self_before = self.__class__.objects.get(pk=self.pk) + if self_before.status != self.status: + status_before = self_before.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') + if self.status == 'running' and not self.started: + self.started = now() + if 'started' not in update_fields: + update_fields.append('started') + 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 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) + else: + elapsed = 0.0 + if self.elapsed != elapsed: + self.elapsed = elapsed + if 'elapsed' not in update_fields: + update_fields.append('elapsed') + super(UnifiedJob, self).save(*args, **kwargs) + # If status changed, update parent instance.... + if self.status != status_before: + self._update_parent_instance() + + def delete(self): + if self.result_stdout_file != "": + try: + os.remove(self.result_stdout_file) + except Exception, e: + pass + super(UnifiedJob, self).delete() + + @property + def result_stdout(self): + if self.result_stdout_file != "": + if not os.path.exists(self.result_stdout_file): + return "stdout capture is missing" + stdout_fd = open(self.result_stdout_file, "r") + output = stdout_fd.read() + stdout_fd.close() + return output + return self.result_stdout_text + + @property + def celery_task(self): + try: + if self.celery_task_id: + return TaskMeta.objects.get(task_id=self.celery_task_id) + except TaskMeta.DoesNotExist: + pass + + @property + def can_start(self): + return bool(self.status == 'new') + + def _get_task_class(self): + raise NotImplementedError + + def _get_passwords_needed_to_start(self): + return [] + + def start_signature(self, **kwargs): + from awx.main.tasks import handle_work_error + + task_class = self._get_task_class() + if not self.can_start: + return False + needed = self._get_passwords_needed_to_start() + opts = dict([(field, kwargs.get(field, '')) for field in needed]) + if not all(opts.values()): + return False + self.status = 'pending' + self.save(update_fields=['status']) + transaction.commit() + task_actual = task_class().si(self.pk, **opts) + return task_actual + + def start(self, **kwargs): + task_actual = self.start_signature(**kwargs) + # TODO: Callback for status + task_result = task_actual.delay() + # Reload instance from database so we don't clobber results from task + # (mainly from tests when using Django 1.4.x). + instance = self.__class__.objects.get(pk=self.pk) + # The TaskMeta instance in the database isn't created until the worker + # starts processing the task, so we can only store the task ID here. + instance.celery_task_id = task_result.task_id + instance.save(update_fields=['celery_task_id']) + return True + + @property + def can_cancel(self): + return bool(self.status in ('pending', 'waiting', 'running')) + + def _force_cancel(self): + # Update the status to 'canceled' if we can detect that the job + # really isn't running (i.e. celery has crashed or forcefully + # killed the worker). + task_statuses = ('STARTED', 'SUCCESS', 'FAILED', 'RETRY', 'REVOKED') + try: + taskmeta = self.celery_task + if not taskmeta or taskmeta.status not in task_statuses: + return + from celery import current_app + i = current_app.control.inspect() + for v in (i.active() or {}).values(): + if taskmeta.task_id in [x['id'] for x in v]: + return + for v in (i.reserved() or {}).values(): + if taskmeta.task_id in [x['id'] for x in v]: + return + for v in (i.revoked() or {}).values(): + if taskmeta.task_id in [x['id'] for x in v]: + return + for v in (i.scheduled() or {}).values(): + if taskmeta.task_id in [x['id'] for x in v]: + return + instance = self.__class__.objects.get(pk=self.pk) + if instance.can_cancel: + instance.status = 'canceled' + update_fields = ['status'] + if not instance.result_traceback: + instance.result_traceback = 'Forced cancel' + update_fields.append('result_traceback') + instance.save(update_fields=update_fields) + except: # FIXME: Log this exception! + if settings.DEBUG: + raise + + def cancel(self): + if self.can_cancel: + if not self.cancel_flag: + self.cancel_flag = True + self.save(update_fields=['cancel_flag']) + if settings.BROKER_URL.startswith('amqp://'): + self._force_cancel() + return self.cancel_flag diff --git a/awx/main/tests/base.py b/awx/main/tests/base.py index aa82d04062..aceee37222 100644 --- a/awx/main/tests/base.py +++ b/awx/main/tests/base.py @@ -372,7 +372,16 @@ class BaseTestMixin(object): self.check_list_ids(response, qs, check_order) if fields: for obj in response['results']: - self.assertTrue(set(obj.keys()) <= set(fields)) + returned_fields = set(obj.keys()) + expected_fields = set(fields) + msg = '' + not_expected = returned_fields - expected_fields + if not_expected: + msg += 'fields %s not expected ' % ', '.join(not_expected) + not_returned = expected_fields - returned_fields + if not_returned: + msg += 'fields %s not returned ' % ', '.join(not_returned) + self.assertTrue(set(obj.keys()) <= set(fields), msg) def start_queue(self, consumer_port, queue_port): self.queue_process = Process(target=run_subscriber, diff --git a/awx/main/tests/jobs.py b/awx/main/tests/jobs.py index 4e84c2b310..503eed4d21 100644 --- a/awx/main/tests/jobs.py +++ b/awx/main/tests/jobs.py @@ -451,7 +451,7 @@ class BaseJobTestMixin(BaseTestMixin): class JobTemplateTest(BaseJobTestMixin, django.test.TestCase): - JOB_TEMPLATE_FIELDS = ('id', 'url', 'related', 'summary_fields', 'created', + JOB_TEMPLATE_FIELDS = ('id', 'type', 'url', 'related', 'summary_fields', 'created', 'modified', 'name', 'description', 'job_type', 'inventory', 'project', 'playbook', 'credential', 'cloud_credential', 'forks', 'limit', 'verbosity', diff --git a/awx/main/tests/projects.py b/awx/main/tests/projects.py index 5a3ff9df3e..6b8e7c4a7f 100644 --- a/awx/main/tests/projects.py +++ b/awx/main/tests/projects.py @@ -1603,7 +1603,7 @@ class ProjectUpdatesTest(BaseTransactionTest): self.assertEqual(job.status, 'new') self.assertFalse(job.passwords_needed_to_start) self.assertTrue(job.start()) - self.assertEqual(job.status, 'pending') + self.assertTrue(job.status in ('pending', 'waiting'), job.status) job = Job.objects.get(pk=job.pk) self.assertTrue(job.status in ('successful', 'failed'), job.result_stdout + job.result_traceback) @@ -1617,7 +1617,7 @@ class ProjectUpdatesTest(BaseTransactionTest): self.assertEqual(job.status, 'new') self.assertFalse(job.passwords_needed_to_start) self.assertTrue(job.start()) - self.assertEqual(job.status, 'pending') + self.assertTrue(job.status in ('pending', 'waiting'), job.status) job = Job.objects.get(pk=job.pk) # FIXME: Not quite sure why the project update still returns successful # in this case? diff --git a/awx/settings/local_settings.py.example b/awx/settings/local_settings.py.example index 5200ee29f4..24182ab30f 100644 --- a/awx/settings/local_settings.py.example +++ b/awx/settings/local_settings.py.example @@ -269,8 +269,8 @@ TEST_GIT_USERNAME = '' TEST_GIT_PASSWORD = '' TEST_GIT_KEY_DATA = TEST_SSH_KEY_DATA TEST_GIT_PUBLIC_HTTPS = 'https://github.com/ansible/ansible.github.com.git' -TEST_GIT_PRIVATE_HTTPS = 'https://github.com/ansible/ansible-doc.git' -TEST_GIT_PRIVATE_SSH = 'git@github.com:ansible/ansible-doc.git' +TEST_GIT_PRIVATE_HTTPS = 'https://github.com/ansible/product-docs.git' +TEST_GIT_PRIVATE_SSH = 'git@github.com:ansible/product-docs.git' TEST_HG_USERNAME = '' TEST_HG_PASSWORD = '' @@ -282,7 +282,7 @@ TEST_HG_PRIVATE_SSH = '' TEST_SVN_USERNAME = '' TEST_SVN_PASSWORD = '' TEST_SVN_PUBLIC_HTTPS = 'https://github.com/ansible/ansible.github.com' -TEST_SVN_PRIVATE_HTTPS = 'https://github.com/ansible/ansible-doc' +TEST_SVN_PRIVATE_HTTPS = 'https://github.com/ansible/product-docs' # To test repo access via SSH login to localhost. import getpass From 52b87920586bfbba65092ceaa168f98087e744dc Mon Sep 17 00:00:00 2001 From: Chris Church Date: Thu, 20 Mar 2014 21:46:16 -0400 Subject: [PATCH 5/7] AC-1040 Fix migrations to work when creating an empty database for testing. --- awx/main/migrations/0035_v148_changes.py | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/awx/main/migrations/0035_v148_changes.py b/awx/main/migrations/0035_v148_changes.py index b60eac4783..4551c00926 100644 --- a/awx/main/migrations/0035_v148_changes.py +++ b/awx/main/migrations/0035_v148_changes.py @@ -3,6 +3,7 @@ from south.utils import datetime_utils as datetime from south.db import db from south.v2 import DataMigration from django.db import models +from django.utils.encoding import smart_text class Migration(DataMigration): @@ -46,11 +47,18 @@ class Migration(DataMigration): }) return d + def _get_content_type_for_model(self, orm, model): + app_label = model._meta.app_label + model_name = model._meta.module_name + defaults = {'name': smart_text(model._meta.verbose_name_raw)} + content_type, created = orm['contenttypes.ContentType'].objects.get_or_create(app_label=app_label, model=model_name, defaults=defaults) + return content_type + def forwards(self, orm): "Write your forwards methods here." # Copy Project old to new. - new_ctype = orm['contenttypes.ContentType'].objects.get(app_label=orm.Project._meta.app_label, model=orm.Project._meta.module_name) + new_ctype = self._get_content_type_for_model(orm, orm.Project) for project in orm.Project.objects.order_by('pk'): d = self._get_dict_from_common_model(project) d.update({ @@ -68,7 +76,7 @@ class Migration(DataMigration): new_project, created = orm.ProjectNew.objects.get_or_create(old_pk=project.pk, defaults=d) # Copy ProjectUpdate old to new. - new_ctype = orm['contenttypes.ContentType'].objects.get(app_label=orm.ProjectUpdate._meta.app_label, model=orm.ProjectUpdate._meta.module_name) + new_ctype = self._get_content_type_for_model(orm, orm.ProjectUpdate) for project_update in orm.ProjectUpdate.objects.order_by('pk'): project = project_update.project d = self._get_dict_from_common_task_model(project_update) @@ -118,7 +126,7 @@ class Migration(DataMigration): permission.save() # Copy InventorySource old to new. - new_ctype = orm['contenttypes.ContentType'].objects.get(app_label=orm.InventorySource._meta.app_label, model=orm.InventorySource._meta.module_name) + new_ctype = self._get_content_type_for_model(orm, orm.InventorySource) for inventory_source in orm.InventorySource.objects.order_by('pk'): d = self._get_dict_from_common_model(inventory_source) d.update({ @@ -137,7 +145,7 @@ class Migration(DataMigration): new_inventory_source, created = orm.InventorySourceNew.objects.get_or_create(old_pk=inventory_source.pk, defaults=d) # Copy InventoryUpdate old to new. - new_ctype = orm['contenttypes.ContentType'].objects.get(app_label=orm.InventoryUpdate._meta.app_label, model=orm.InventoryUpdate._meta.module_name) + new_ctype = self._get_content_type_for_model(orm, orm.InventoryUpdate) for inventory_update in orm.InventoryUpdate.objects.order_by('pk'): inventory_source = inventory_update.inventory_source d = self._get_dict_from_common_task_model(inventory_update) @@ -180,7 +188,7 @@ class Migration(DataMigration): host.new_inventory_sources.add(new_inventory_source) # Copy JobTemplate old to new. - new_ctype = orm['contenttypes.ContentType'].objects.get(app_label=orm.JobTemplate._meta.app_label, model=orm.JobTemplate._meta.module_name) + new_ctype = self._get_content_type_for_model(orm, orm.JobTemplate) for job_template in orm.JobTemplate.objects.order_by('pk'): d = self._get_dict_from_common_model(job_template) d.update({ @@ -201,7 +209,7 @@ class Migration(DataMigration): new_job_template, created = orm.JobTemplateNew.objects.get_or_create(old_pk=job_template.pk, defaults=d) # Copy Job old to new. - new_ctype = orm['contenttypes.ContentType'].objects.get(app_label=orm.Job._meta.app_label, model=orm.Job._meta.module_name) + new_ctype = self._get_content_type_for_model(orm, orm.Job) for job in orm.Job.objects.order_by('pk'): d = self._get_dict_from_common_task_model(job) d.update({ From 2cb3f31b0195fadd1f611bcad4bbf39b12271d14 Mon Sep 17 00:00:00 2001 From: Chris Church Date: Fri, 21 Mar 2014 00:05:36 -0400 Subject: [PATCH 6/7] AC-1040 Give unified jobs a copy of config from unified job templates to capture the settings as they were when the job is run. --- awx/main/migrations/0035_v148_changes.py | 12 ++- awx/main/models/inventory.py | 36 +++++--- awx/main/models/jobs.py | 41 ++++----- awx/main/models/projects.py | 112 +++++++++++++---------- awx/main/models/unified_jobs.py | 48 ++++++++-- awx/main/tasks.py | 71 +++++++------- 6 files changed, 189 insertions(+), 131 deletions(-) diff --git a/awx/main/migrations/0035_v148_changes.py b/awx/main/migrations/0035_v148_changes.py index 4551c00926..0801683e42 100644 --- a/awx/main/migrations/0035_v148_changes.py +++ b/awx/main/migrations/0035_v148_changes.py @@ -79,10 +79,12 @@ class Migration(DataMigration): new_ctype = self._get_content_type_for_model(orm, orm.ProjectUpdate) for project_update in orm.ProjectUpdate.objects.order_by('pk'): project = project_update.project + new_project = orm.ProjectNew.objects.get(old_pk=project_update.project_id) d = self._get_dict_from_common_task_model(project_update) d.update({ 'polymorphic_ctype_id': new_ctype.pk, - 'project_id': orm.ProjectNew.objects.get(old_pk=project_update.project_id).pk, + 'project_id': new_project.pk, + 'unified_job_template_id': new_project.pk, 'local_path': project.local_path, 'scm_type': project.scm_type, 'scm_url': project.scm_url, @@ -148,6 +150,7 @@ class Migration(DataMigration): new_ctype = self._get_content_type_for_model(orm, orm.InventoryUpdate) for inventory_update in orm.InventoryUpdate.objects.order_by('pk'): inventory_source = inventory_update.inventory_source + new_inventory_source = orm.InventorySourceNew.objects.get(old_pk=inventory_update.inventory_source_id) d = self._get_dict_from_common_task_model(inventory_update) d.update({ 'polymorphic_ctype_id': new_ctype.pk, @@ -158,7 +161,8 @@ class Migration(DataMigration): 'source_regions': inventory_source.source_regions, 'overwrite': inventory_source.overwrite, 'overwrite_vars': inventory_source.overwrite_vars, - 'inventory_source_id': orm.InventorySourceNew.objects.get(old_pk=inventory_update.inventory_source_id).pk, + 'inventory_source_id': new_inventory_source.pk, + 'unified_job_template_id': new_inventory_source.pk, 'license_error': inventory_update.license_error, }) new_inventory_update, created = orm.InventoryUpdateNew.objects.get_or_create(old_pk=inventory_update.pk, defaults=d) @@ -227,7 +231,9 @@ class Migration(DataMigration): if job.project: d['project_id'] = orm.ProjectNew.objects.get(old_pk=job.project_id).pk if job.job_template: - d['job_template_id'] = orm.JobTemplateNew.objects.get(old_pk=job.job_template_id).pk + new_job_template = orm.JobTemplateNew.objects.get(old_pk=job.job_template_id) + d['job_template_id'] = new_job_template.pk + d['unified_job_template_id'] = new_job_template.pk new_job, created = orm.JobNew.objects.get_or_create(old_pk=job.pk, defaults=d) # Update JobTemplate last run. diff --git a/awx/main/models/inventory.py b/awx/main/models/inventory.py index 02c5e92e82..5a8e6ee207 100644 --- a/awx/main/models/inventory.py +++ b/awx/main/models/inventory.py @@ -741,6 +741,8 @@ class InventorySourceOptions(BaseModel): ', '.join(invalid_regions))) return ','.join(regions) + source_vars_dict = VarsDictProperty('source_vars') + class InventorySourceBase(InventorySourceOptions): @@ -758,6 +760,15 @@ class InventorySourceBase(InventorySourceOptions): class InventorySourceBaseMethods(object): + @classmethod + def _get_unified_job_class(cls): + return InventoryUpdate + + @classmethod + def _get_unified_job_field_names(cls): + return ['source', 'source_path', 'source_vars', 'credential', + 'source_regions', 'overwrite', 'overwrite_vars'] + def save(self, *args, **kwargs): # 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. @@ -775,8 +786,6 @@ class InventorySourceBaseMethods(object): # Do the actual save. super(InventorySourceBaseMethods, self).save(*args, **kwargs) - source_vars_dict = VarsDictProperty('source_vars') - def get_absolute_url(self): return reverse('api:inventory_source_detail', args=(self.pk,)) @@ -784,15 +793,18 @@ class InventorySourceBaseMethods(object): # FIXME: Prevent update when another one is active! return bool(self.source) + def create_inventory_update(self, **kwargs): + return self._create_unified_job_instance(**kwargs) + def update_signature(self, **kwargs): if self.can_update: - inventory_update = self.inventory_updates.create() # FIXME: Copy inventory source fields to update + inventory_update = self.create_inventory_update() inventory_update_sig = inventory_update.start_signature() return (inventory_update, inventory_update_sig) def update(self, **kwargs): if self.can_update: - inventory_update = self.inventory_updates.create() # FIXME: Copy inventory source fields to update + inventory_update = self.create_inventory_update() inventory_update.start() return inventory_update @@ -928,6 +940,15 @@ class InventoryUpdateBase(InventorySourceOptions): class InventoryUpdateBaseMethods(object): + @classmethod + def _get_parent_field_name(cls): + return 'inventory_source' + + @classmethod + def _get_task_class(cls): + from awx.main.tasks import RunInventoryUpdate + return RunInventoryUpdate + def save(self, *args, **kwargs): update_fields = kwargs.get('update_fields', []) if bool('license' in self.result_stdout and @@ -937,16 +958,9 @@ class InventoryUpdateBaseMethods(object): update_fields.append('license_error') super(InventoryUpdateBaseMethods, self).save(*args, **kwargs) - def _get_parent_instance(self): - return self.inventory_source - def get_absolute_url(self): return reverse('api:inventory_update_detail', args=(self.pk,)) - def _get_task_class(self): - from awx.main.tasks import RunInventoryUpdate - return RunInventoryUpdate - if getattr(settings, 'UNIFIED_JOBS_STEP') == 0: diff --git a/awx/main/models/jobs.py b/awx/main/models/jobs.py index 75aa93f14e..b7e96f2405 100644 --- a/awx/main/models/jobs.py +++ b/awx/main/models/jobs.py @@ -143,27 +143,21 @@ class JobTemplateBase(JobOptions): class JobTemplateBaseMethods(object): + @classmethod + def _get_unified_job_class(cls): + return Job + + @classmethod + def _get_unified_job_field_names(cls): + return ['job_type', 'inventory', 'project', 'playbook', 'credential', + 'cloud_credential', 'forks', 'limit', 'verbosity', + 'extra_vars', 'job_tags'] + def create_job(self, **kwargs): ''' Create a new job based on this template. ''' - save_job = kwargs.pop('save', True) - kwargs['job_template'] = self - kwargs.setdefault('job_type', self.job_type) - kwargs.setdefault('inventory', self.inventory) - kwargs.setdefault('project', self.project) - kwargs.setdefault('playbook', self.playbook) - kwargs.setdefault('credential', self.credential) - kwargs.setdefault('cloud_credential', self.cloud_credential) - kwargs.setdefault('forks', self.forks) - kwargs.setdefault('limit', self.limit) - kwargs.setdefault('verbosity', self.verbosity) - kwargs.setdefault('extra_vars', self.extra_vars) - kwargs.setdefault('job_tags', self.job_tags) - job = Job(**kwargs) - if save_job: - job.save() - return job + return self._create_unified_job_instance(**kwargs) def get_absolute_url(self): return reverse('api:job_template_detail', args=(self.pk,)) @@ -256,6 +250,15 @@ class JobBase(JobOptions): class JobBaseMethods(object): + @classmethod + def _get_parent_field_name(cls): + return 'job_template' + + @classmethod + def _get_task_class(cls): + from awx.main.tasks import RunJob + return RunJob + def get_absolute_url(self): return reverse('api:job_detail', args=(self.pk,)) @@ -278,10 +281,6 @@ class JobBaseMethods(object): needed.append(pw) return needed - def _get_task_class(self): - from awx.main.tasks import RunJob - return RunJob - def _get_passwords_needed_to_start(self): return self.passwords_needed_to_start diff --git a/awx/main/models/projects.py b/awx/main/models/projects.py index bd86ffb991..3eb7926ed7 100644 --- a/awx/main/models/projects.py +++ b/awx/main/models/projects.py @@ -147,6 +147,46 @@ class ProjectOptions(models.Model): pass return cred + def get_project_path(self, check_if_exists=True): + local_path = os.path.basename(self.local_path) + if local_path and not local_path.startswith('.'): + proj_path = os.path.join(settings.PROJECTS_ROOT, local_path) + if not check_if_exists or os.path.exists(proj_path): + return proj_path + + @property + def playbooks(self): + valid_re = re.compile(r'^\s*?-?\s*?(?:hosts|include):\s*?.*?$') + results = [] + project_path = self.get_project_path() + if project_path: + for dirpath, dirnames, filenames in os.walk(project_path): + for filename in filenames: + if os.path.splitext(filename)[-1] not in ['.yml', '.yaml']: + continue + playbook = os.path.join(dirpath, filename) + # Filter files that do not have either hosts or top-level + # includes. Use regex to allow files with invalid YAML to + # show up. + matched = False + try: + for line in file(playbook): + if valid_re.match(line): + matched = True + except IOError: + continue + if not matched: + continue + playbook = os.path.relpath(playbook, project_path) + # Filter files in a roles subdirectory. + if 'roles' in playbook.split(os.sep): + continue + # Filter files in a tasks subdirectory. + if 'tasks' in playbook.split(os.sep): + continue + results.append(playbook) + return results + class ProjectBase(ProjectOptions): ''' @@ -174,6 +214,15 @@ class ProjectBase(ProjectOptions): class ProjectBaseMethods(object): + @classmethod + def _get_unified_job_class(cls): + return ProjectUpdate + + @classmethod + def _get_unified_job_field_names(cls): + return ['local_path', 'scm_type', 'scm_url', 'scm_branch', + 'scm_clean', 'scm_delete_on_update', 'credential'] + def save(self, *args, **kwargs): new_instance = not bool(self.pk) # If update_fields has been specified, add our field names to it, @@ -239,61 +288,26 @@ class ProjectBaseMethods(object): # FIXME: Prevent update when another one is active! return bool(self.scm_type)# and not self.current_update) + def create_project_update(self, **kwargs): + if self.scm_delete_on_next_update: + kwargs['scm_delete_on_update'] = True + return self._create_unified_job_instance(**kwargs) + def update_signature(self, **kwargs): if self.can_update: - project_update = self.project_updates.create() # FIXME: Copy options to ProjectUpdate + project_update = self.create_project_update() project_update_sig = project_update.start_signature() return (project_update, project_update_sig) def update(self, **kwargs): if self.can_update: - project_update = self.project_updates.create() # FIXME: Copy options to ProjectUpdate + project_update = self.create_project_update() project_update.start() return project_update def get_absolute_url(self): return reverse('api:project_detail', args=(self.pk,)) - def get_project_path(self, check_if_exists=True): - local_path = os.path.basename(self.local_path) - if local_path and not local_path.startswith('.'): - proj_path = os.path.join(settings.PROJECTS_ROOT, local_path) - if not check_if_exists or os.path.exists(proj_path): - return proj_path - - @property - def playbooks(self): - valid_re = re.compile(r'^\s*?-?\s*?(?:hosts|include):\s*?.*?$') - results = [] - project_path = self.get_project_path() - if project_path: - for dirpath, dirnames, filenames in os.walk(project_path): - for filename in filenames: - if os.path.splitext(filename)[-1] not in ['.yml', '.yaml']: - continue - playbook = os.path.join(dirpath, filename) - # Filter files that do not have either hosts or top-level - # includes. Use regex to allow files with invalid YAML to - # show up. - matched = False - try: - for line in file(playbook): - if valid_re.match(line): - matched = True - except IOError: - continue - if not matched: - continue - playbook = os.path.relpath(playbook, project_path) - # Filter files in a roles subdirectory. - if 'roles' in playbook.split(os.sep): - continue - # Filter files in a tasks subdirectory. - if 'tasks' in playbook.split(os.sep): - continue - results.append(playbook) - return results - if getattr(settings, 'UNIFIED_JOBS_STEP') == 0: @@ -376,16 +390,18 @@ class ProjectUpdateBase(ProjectOptions): class ProjectUpdateBaseMethods(object): - def _get_parent_instance(self): - return self.project + @classmethod + def _get_parent_field_name(cls): + return 'project' + + @classmethod + def _get_task_class(cls): + from awx.main.tasks import RunProjectUpdate + return RunProjectUpdate def get_absolute_url(self): return reverse('api:project_update_detail', args=(self.pk,)) - def _get_task_class(self): - from awx.main.tasks import RunProjectUpdate - return RunProjectUpdate - def _update_parent_instance(self): parent_instance = self._get_parent_instance() if parent_instance: diff --git a/awx/main/models/unified_jobs.py b/awx/main/models/unified_jobs.py index c26ef64ba7..db279348dd 100644 --- a/awx/main/models/unified_jobs.py +++ b/awx/main/models/unified_jobs.py @@ -182,11 +182,34 @@ class UnifiedJobTemplate(PolymorphicModel, CommonModelNameNotUnique): def update(self, **kwargs): raise NotImplementedError # Implement in subclass. - def _get_child_queryset(self): - pass + @classmethod + def _get_unified_job_class(cls): + raise NotImplementedError # Implement in subclass. - def _create_child_instance(self, **kwargs): - pass + @classmethod + def _get_unified_job_field_names(cls): + raise NotImplementedError # Implement in subclass. + + def _create_unified_job_instance(self, **kwargs): + ''' + Create a new unified job based on this unified job template. + ''' + save_unified_job = kwargs.pop('save', True) + unified_job_class = self._get_unified_job_class() + parent_field_name = unified_job_class._get_parent_field_name() + kwargs.pop('%s_id' % parent_field_name, None) + kwargs[parent_field_name] = self + for field_name in self._get_unified_job_field_names(): + if field_name in kwargs: + continue + # Foreign keys can be specified as field_name or field_name_id. + if hasattr(self, '%s_id' % field_name) and ('%s_id' % field_name) in kwargs: + continue + kwargs[field_name] = getattr(self, field_name) + unified_job = unified_job_class(**kwargs) + if save_unified_job: + unified_job.save() + return unified_job class UnifiedJob(PolymorphicModel, PrimordialModel): @@ -306,11 +329,19 @@ class UnifiedJob(PolymorphicModel, PrimordialModel): editable=False, ) + @classmethod + def _get_task_class(cls): + raise NotImplementedError # Implement in subclasses. + + @classmethod + def _get_parent_field_name(cls): + return 'unified_job_template' # Override in subclasses. + def __unicode__(self): return u'%s-%s-%s' % (self.created, self.id, self.status) def _get_parent_instance(self): - return self.job_template + return getattr(self, self._get_parent_field_name()) def _update_parent_instance(self): parent_instance = self._get_parent_instance() @@ -360,6 +391,10 @@ class UnifiedJob(PolymorphicModel, PrimordialModel): self.elapsed = elapsed if 'elapsed' not in update_fields: update_fields.append('elapsed') + 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.... if self.status != status_before: @@ -396,9 +431,6 @@ class UnifiedJob(PolymorphicModel, PrimordialModel): def can_start(self): return bool(self.status == 'new') - def _get_task_class(self): - raise NotImplementedError - def _get_passwords_needed_to_start(self): return [] diff --git a/awx/main/tasks.py b/awx/main/tasks.py index 7abf10af28..c90b7d85ee 100644 --- a/awx/main/tasks.py +++ b/awx/main/tasks.py @@ -516,9 +516,8 @@ class RunProjectUpdate(BaseTask): ''' Return SSH private key data needed for this project update. ''' - project = project_update.project - if project.credential: - return decrypt_field(project.credential, 'ssh_key_data') or None + if project_update.credential: + return decrypt_field(project_update.credential, 'ssh_key_data') or None def build_passwords(self, project_update, **kwargs): ''' @@ -527,12 +526,11 @@ class RunProjectUpdate(BaseTask): ''' passwords = super(RunProjectUpdate, self).build_passwords(project_update, **kwargs) - project = project_update.project - if project.credential: - passwords['scm_key_unlock'] = decrypt_field(project.credential, + if project_update.credential: + passwords['scm_key_unlock'] = decrypt_field(project_update.credential, 'ssh_key_unlock') - passwords['scm_username'] = project.credential.username - passwords['scm_password'] = decrypt_field(project.credential, + passwords['scm_username'] = project_update.credential.username + passwords['scm_password'] = decrypt_field(project_update.credential, 'password') return passwords @@ -552,9 +550,8 @@ class RunProjectUpdate(BaseTask): for authentication. ''' extra_vars = {} - project = project_update.project - scm_type = project.scm_type - scm_url = update_scm_url(scm_type, project.scm_url, + scm_type = project_update.scm_type + scm_url = update_scm_url(scm_type, project_update.scm_url, check_special_cases=False) scm_url_parts = urlparse.urlsplit(scm_url) scm_username = kwargs.get('passwords', {}).get('scm_username', '') @@ -597,18 +594,16 @@ class RunProjectUpdate(BaseTask): args.append('-vvv') else: args.append('-v') - project = project_update.project scm_url, extra_vars = self._build_scm_url_extra_vars(project_update, **kwargs) - scm_branch = project.scm_branch or {'hg': 'tip'}.get(project.scm_type, 'HEAD') - scm_delete_on_update = project.scm_delete_on_update or project.scm_delete_on_next_update + scm_branch = project_update.scm_branch or {'hg': 'tip'}.get(project_update.scm_type, 'HEAD') extra_vars.update({ - 'project_path': project.get_project_path(check_if_exists=False), - 'scm_type': project.scm_type, + 'project_path': project_update.get_project_path(check_if_exists=False), + 'scm_type': project_update.scm_type, 'scm_url': scm_url, 'scm_branch': scm_branch, - 'scm_clean': project.scm_clean, - 'scm_delete_on_update': scm_delete_on_update, + 'scm_clean': project_update.scm_clean, + 'scm_delete_on_update': project_update.scm_delete_on_update, }) args.extend(['-e', json.dumps(extra_vars)]) args.append('project_update.yml') @@ -652,8 +647,7 @@ class RunProjectUpdate(BaseTask): **kwargs)[0] if after_url != before_url: output_replacements.append((before_url, after_url)) - project = project_update.project - if project.scm_type == 'svn' and scm_username and scm_password: + if project_update.scm_type == 'svn' and scm_username and scm_password: d_before = { 'username': scm_username, 'password': scm_password, @@ -719,14 +713,13 @@ class RunInventoryUpdate(BaseTask): ''' Return private data needed for inventory update. ''' - inventory_source = inventory_update.inventory_source cp = ConfigParser.ConfigParser() # Build custom ec2.ini for ec2 inventory script to use. - if inventory_source.source == 'ec2': + if inventory_update.source == 'ec2': section = 'ec2' cp.add_section(section) - ec2_opts = dict(inventory_source.source_vars_dict.items()) - regions = inventory_source.source_regions or 'all' + ec2_opts = dict(inventory_update.source_vars_dict.items()) + regions = inventory_update.source_regions or 'all' regions = ','.join([x.strip() for x in regions.split(',')]) regions_blacklist = ','.join(settings.EC2_REGIONS_BLACKLIST) ec2_opts['regions'] = regions @@ -739,10 +732,10 @@ class RunInventoryUpdate(BaseTask): for k,v in ec2_opts.items(): cp.set(section, k, str(v)) # Build pyrax creds INI for rax inventory script. - elif inventory_source.source == 'rax': + elif inventory_update.source == 'rax': section = 'rackspace_cloud' cp.add_section(section) - credential = inventory_source.credential + credential = inventory_update.credential if credential: cp.set(section, 'username', credential.username) cp.set(section, 'api_key', decrypt_field(credential, @@ -759,8 +752,7 @@ class RunInventoryUpdate(BaseTask): ''' passwords = super(RunInventoryUpdate, self).build_passwords(inventory_update, **kwargs) - inventory_source = inventory_update.inventory_source - credential = inventory_source.credential + credential = inventory_update.credential if credential: passwords['source_username'] = credential.username passwords['source_password'] = decrypt_field(credential, 'password') @@ -772,20 +764,19 @@ class RunInventoryUpdate(BaseTask): ''' env = super(RunInventoryUpdate, self).build_env(inventory_update, **kwargs) # Pass inventory source ID to inventory script. - inventory_source = inventory_update.inventory_source - env['INVENTORY_SOURCE_ID'] = str(inventory_source.pk) + env['INVENTORY_SOURCE_ID'] = str(inventory_update.inventory_source_id) # Set environment variables specific to each source. - if inventory_source.source == 'ec2': + if inventory_update.source == 'ec2': env['AWS_ACCESS_KEY_ID'] = kwargs.get('passwords', {}).get('source_username', '') env['AWS_SECRET_ACCESS_KEY'] = kwargs.get('passwords', {}).get('source_password', '') env['EC2_INI_PATH'] = kwargs.get('private_data_file', '') - elif inventory_source.source == 'rax': + elif inventory_update.source == 'rax': env['RAX_CREDS_FILE'] = kwargs.get('private_data_file', '') - env['RAX_REGION'] = inventory_source.source_regions or 'all' + env['RAX_REGION'] = inventory_update.source_regions or 'all' # Set this environment variable so the vendored package won't # complain about not being able to determine its version number. env['PBR_VERSION'] = '0.5.21' - elif inventory_source.source == 'file': + elif inventory_update.source == 'file': # FIXME: Parse source_env to dict, update env. pass #print env @@ -799,25 +790,25 @@ class RunInventoryUpdate(BaseTask): inventory = inventory_source.group.inventory args = ['awx-manage', 'inventory_import'] args.extend(['--inventory-id', str(inventory.pk)]) - if inventory_source.overwrite: + if inventory_update.overwrite: args.append('--overwrite') - if inventory_source.overwrite_vars: + if inventory_update.overwrite_vars: args.append('--overwrite-vars') args.append('--source') - if inventory_source.source == 'ec2': + if inventory_update.source == 'ec2': ec2_path = self.get_path_to('..', 'plugins', 'inventory', 'ec2.py') args.append(ec2_path) args.extend(['--enabled-var', 'ec2_state']) args.extend(['--enabled-value', 'running']) #args.extend(['--instance-id', 'ec2_id']) - elif inventory_source.source == 'rax': + elif inventory_update.source == 'rax': rax_path = self.get_path_to('..', 'plugins', 'inventory', 'rax.py') args.append(rax_path) args.extend(['--enabled-var', 'rax_status']) args.extend(['--enabled-value', 'ACTIVE']) #args.extend(['--instance-id', 'rax_id']) - elif inventory_source.source == 'file': - args.append(inventory_source.source_path) + elif inventory_update.source == 'file': + args.append(inventory_update.source_path) verbosity = getattr(settings, 'INVENTORY_UPDATE_VERBOSITY', 1) args.append('-v%d' % verbosity) if settings.DEBUG: From 99c62f1261d04efec4d22184932bbc440362cd5f Mon Sep 17 00:00:00 2001 From: Chris Church Date: Mon, 24 Mar 2014 16:09:49 -0400 Subject: [PATCH 7/7] AC-1040 Inserted migration 34 from master, defined additional model changes needed, regenerated previous migrations 34/35/36/37 as 35/36/37/38. --- awx/main/migrations/0034_v148_changes.py | 986 ++----------------- awx/main/migrations/0035_v148_changes.py | 1142 ++++++++++++++++------ awx/main/migrations/0036_v148_changes.py | 871 ++++++++++------- awx/main/migrations/0037_v148_changes.py | 567 ++++++++--- awx/main/migrations/0038_v148_changes.py | 500 ++++++++++ awx/main/models/activity_stream.py | 1 + awx/main/models/base.py | 16 + awx/main/models/inventory.py | 34 +- awx/main/models/jobs.py | 11 +- awx/main/models/organization.py | 15 +- awx/main/models/projects.py | 3 + awx/main/models/schedules.py | 12 +- awx/main/models/unified_jobs.py | 35 +- 13 files changed, 2399 insertions(+), 1794 deletions(-) create mode 100644 awx/main/migrations/0038_v148_changes.py diff --git a/awx/main/migrations/0034_v148_changes.py b/awx/main/migrations/0034_v148_changes.py index a9234cbbc5..be0d8f88ed 100644 --- a/awx/main/migrations/0034_v148_changes.py +++ b/awx/main/migrations/0034_v148_changes.py @@ -8,726 +8,31 @@ from django.db import models class Migration(SchemaMigration): def forwards(self, orm): - # Adding model 'InventoryUpdateNew' - db.create_table(u'main_inventoryupdatenew', ( - (u'unifiedjob_ptr', self.gf('django.db.models.fields.related.OneToOneField')(to=orm['main.UnifiedJob'], unique=True, primary_key=True)), - ('source', self.gf('django.db.models.fields.CharField')(default='', max_length=32, blank=True)), - ('source_path', self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True)), - ('source_vars', self.gf('django.db.models.fields.TextField')(default='', blank=True)), - ('credential', self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name='inventoryupdatenews', null=True, blank=True, to=orm['main.Credential'])), - ('source_regions', self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True)), - ('overwrite', self.gf('django.db.models.fields.BooleanField')(default=False)), - ('overwrite_vars', self.gf('django.db.models.fields.BooleanField')(default=False)), - ('license_error', self.gf('django.db.models.fields.BooleanField')(default=False)), - ('inventory_source', self.gf('django.db.models.fields.related.ForeignKey')(related_name='inventory_updates', to=orm['main.InventorySourceNew'])), - )) - db.send_create_signal('main', ['InventoryUpdateNew']) - - # Adding model 'JobNew' - db.create_table(u'main_jobnew', ( - (u'unifiedjob_ptr', self.gf('django.db.models.fields.related.OneToOneField')(to=orm['main.UnifiedJob'], unique=True, primary_key=True)), - ('job_type', self.gf('django.db.models.fields.CharField')(max_length=64)), - ('inventory', self.gf('django.db.models.fields.related.ForeignKey')(related_name='jobnews', null=True, on_delete=models.SET_NULL, to=orm['main.Inventory'])), - ('playbook', self.gf('django.db.models.fields.CharField')(default='', max_length=1024)), - ('credential', self.gf('django.db.models.fields.related.ForeignKey')(related_name='jobnews', on_delete=models.SET_NULL, default=None, to=orm['main.Credential'], blank=True, null=True)), - ('cloud_credential', self.gf('django.db.models.fields.related.ForeignKey')(related_name='jobnews_as_cloud_credential+', on_delete=models.SET_NULL, default=None, to=orm['main.Credential'], blank=True, null=True)), - ('forks', self.gf('django.db.models.fields.PositiveIntegerField')(default=0, blank=True)), - ('limit', self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True)), - ('verbosity', self.gf('django.db.models.fields.PositiveIntegerField')(default=0, blank=True)), - ('extra_vars', self.gf('django.db.models.fields.TextField')(default='', blank=True)), - ('job_tags', self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True)), - ('job_template', self.gf('django.db.models.fields.related.ForeignKey')(related_name='jobs', on_delete=models.SET_NULL, default=None, to=orm['main.JobTemplateNew'], blank=True, null=True)), - ('project', self.gf('django.db.models.fields.related.ForeignKey')(related_name='jobs', null=True, on_delete=models.SET_NULL, to=orm['main.ProjectNew'])), - )) - db.send_create_signal('main', ['JobNew']) - - # Adding model 'UnifiedJob' - db.create_table(u'main_unifiedjob', ( - (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), - ('polymorphic_ctype', self.gf('django.db.models.fields.related.ForeignKey')(related_name='polymorphic_main.unifiedjob_set', null=True, to=orm['contenttypes.ContentType'])), - ('created', self.gf('django.db.models.fields.DateTimeField')(default=None)), - ('modified', self.gf('django.db.models.fields.DateTimeField')(default=None)), - ('description', self.gf('django.db.models.fields.TextField')(default='', blank=True)), - ('created_by', self.gf('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=orm['auth.User'])), - ('modified_by', self.gf('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=orm['auth.User'])), - ('active', self.gf('django.db.models.fields.BooleanField')(default=True)), - ('old_pk', self.gf('django.db.models.fields.PositiveIntegerField')(default=None, null=True)), - ('unified_job_template', self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name='unifiedjob_unified_jobs', null=True, to=orm['main.UnifiedJobTemplate'])), - ('launch_type', self.gf('django.db.models.fields.CharField')(default='manual', max_length=20)), - ('schedule', self.gf('django.db.models.fields.related.ForeignKey')(default=None, to=orm['main.Schedule'], null=True)), - ('cancel_flag', self.gf('django.db.models.fields.BooleanField')(default=False)), - ('status', self.gf('django.db.models.fields.CharField')(default='new', max_length=20)), - ('failed', self.gf('django.db.models.fields.BooleanField')(default=False)), - ('started', self.gf('django.db.models.fields.DateTimeField')(default=None, null=True)), - ('finished', self.gf('django.db.models.fields.DateTimeField')(default=None, null=True)), - ('elapsed', self.gf('django.db.models.fields.DecimalField')(max_digits=12, decimal_places=3)), - ('job_args', self.gf('django.db.models.fields.TextField')(default='', blank=True)), - ('job_cwd', self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True)), - ('job_env', self.gf('jsonfield.fields.JSONField')(default={}, blank=True)), - ('start_args', self.gf('django.db.models.fields.TextField')(default='', blank=True)), - ('result_stdout_text', self.gf('django.db.models.fields.TextField')(default='', blank=True)), - ('result_stdout_file', self.gf('django.db.models.fields.TextField')(default='', blank=True)), - ('result_traceback', self.gf('django.db.models.fields.TextField')(default='', blank=True)), - ('celery_task_id', self.gf('django.db.models.fields.CharField')(default='', max_length=100, blank=True)), - )) - db.send_create_signal('main', ['UnifiedJob']) - - # Adding M2M table for field depends_on on 'UnifiedJob' - m2m_table_name = db.shorten_name(u'main_unifiedjob_depends_on') - db.create_table(m2m_table_name, ( - ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), - ('from_unifiedjob', models.ForeignKey(orm['main.unifiedjob'], null=False)), - ('to_unifiedjob', models.ForeignKey(orm['main.unifiedjob'], null=False)) - )) - db.create_unique(m2m_table_name, ['from_unifiedjob_id', 'to_unifiedjob_id']) - - # Adding model 'Schedule' - db.create_table(u'main_schedule', ( - (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), - ('created', self.gf('django.db.models.fields.DateTimeField')(default=None)), - ('modified', self.gf('django.db.models.fields.DateTimeField')(default=None)), - ('description', self.gf('django.db.models.fields.TextField')(default='', blank=True)), - ('created_by', self.gf('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=orm['auth.User'])), - ('modified_by', self.gf('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=orm['auth.User'])), - ('active', self.gf('django.db.models.fields.BooleanField')(default=True)), - ('name', self.gf('django.db.models.fields.CharField')(unique=True, max_length=512)), - ('job_template', self.gf('django.db.models.fields.related.ForeignKey')(related_name='schedules', to=orm['main.UnifiedJobTemplate'])), - ('dtstart', self.gf('django.db.models.fields.DateTimeField')()), - ('dtend', self.gf('django.db.models.fields.DateTimeField')(default=None, null=True)), - ('rrule', self.gf('django.db.models.fields.CharField')(max_length=255)), - )) - db.send_create_signal('main', ['Schedule']) - - # Adding model 'InventorySourceNew' - db.create_table(u'main_inventorysourcenew', ( - (u'unifiedjobtemplate_ptr', self.gf('django.db.models.fields.related.OneToOneField')(to=orm['main.UnifiedJobTemplate'], unique=True, primary_key=True)), - ('source', self.gf('django.db.models.fields.CharField')(default='', max_length=32, blank=True)), - ('source_path', self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True)), - ('source_vars', self.gf('django.db.models.fields.TextField')(default='', blank=True)), - ('credential', self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name='inventorysourcenews', null=True, blank=True, to=orm['main.Credential'])), - ('source_regions', self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True)), - ('overwrite', self.gf('django.db.models.fields.BooleanField')(default=False)), - ('overwrite_vars', self.gf('django.db.models.fields.BooleanField')(default=False)), - ('update_on_launch', self.gf('django.db.models.fields.BooleanField')(default=False)), - ('update_cache_timeout', self.gf('django.db.models.fields.PositiveIntegerField')(default=0)), - ('inventory', self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name='new_inventory_sources', null=True, to=orm['main.Inventory'])), - ('group', self.gf('awx.main.fields.AutoOneToOneField')(related_name='new_inventory_source', null=True, default=None, to=orm['main.Group'], blank=True, unique=True)), - )) - db.send_create_signal('main', ['InventorySourceNew']) - - # Adding model 'JobTemplateNew' - db.create_table('main_jobtemplatenew', ( - (u'unifiedjobtemplate_ptr', self.gf('django.db.models.fields.related.OneToOneField')(to=orm['main.UnifiedJobTemplate'], unique=True, primary_key=True)), - ('job_type', self.gf('django.db.models.fields.CharField')(max_length=64)), - ('inventory', self.gf('django.db.models.fields.related.ForeignKey')(related_name='jobtemplatenews', null=True, on_delete=models.SET_NULL, to=orm['main.Inventory'])), - ('playbook', self.gf('django.db.models.fields.CharField')(default='', max_length=1024)), - ('credential', self.gf('django.db.models.fields.related.ForeignKey')(related_name='jobtemplatenews', on_delete=models.SET_NULL, default=None, to=orm['main.Credential'], blank=True, null=True)), - ('cloud_credential', self.gf('django.db.models.fields.related.ForeignKey')(related_name='jobtemplatenews_as_cloud_credential+', on_delete=models.SET_NULL, default=None, to=orm['main.Credential'], blank=True, null=True)), - ('forks', self.gf('django.db.models.fields.PositiveIntegerField')(default=0, blank=True)), - ('limit', self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True)), - ('verbosity', self.gf('django.db.models.fields.PositiveIntegerField')(default=0, blank=True)), - ('extra_vars', self.gf('django.db.models.fields.TextField')(default='', blank=True)), - ('job_tags', self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True)), - ('host_config_key', self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True)), - ('project', self.gf('django.db.models.fields.related.ForeignKey')(related_name='job_templates', null=True, on_delete=models.SET_NULL, to=orm['main.ProjectNew'])), - )) - db.send_create_signal('main', ['JobTemplateNew']) - - # Adding model 'ProjectNew' - db.create_table(u'main_projectnew', ( - (u'unifiedjobtemplate_ptr', self.gf('django.db.models.fields.related.OneToOneField')(to=orm['main.UnifiedJobTemplate'], unique=True, primary_key=True)), - ('local_path', self.gf('django.db.models.fields.CharField')(max_length=1024, blank=True)), - ('scm_type', self.gf('django.db.models.fields.CharField')(default='', max_length=8, blank=True)), - ('scm_url', self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True)), - ('scm_branch', self.gf('django.db.models.fields.CharField')(default='', max_length=256, blank=True)), - ('scm_clean', self.gf('django.db.models.fields.BooleanField')(default=False)), - ('scm_delete_on_update', self.gf('django.db.models.fields.BooleanField')(default=False)), - ('credential', self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name='projectnews', null=True, blank=True, to=orm['main.Credential'])), - ('scm_delete_on_next_update', self.gf('django.db.models.fields.BooleanField')(default=False)), - ('scm_update_on_launch', self.gf('django.db.models.fields.BooleanField')(default=False)), - ('scm_update_cache_timeout', self.gf('django.db.models.fields.PositiveIntegerField')(default=0)), - )) - db.send_create_signal('main', ['ProjectNew']) - - # Adding model 'ProjectUpdateNew' - db.create_table(u'main_projectupdatenew', ( - (u'unifiedjob_ptr', self.gf('django.db.models.fields.related.OneToOneField')(to=orm['main.UnifiedJob'], unique=True, primary_key=True)), - ('local_path', self.gf('django.db.models.fields.CharField')(max_length=1024, blank=True)), - ('scm_type', self.gf('django.db.models.fields.CharField')(default='', max_length=8, blank=True)), - ('scm_url', self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True)), - ('scm_branch', self.gf('django.db.models.fields.CharField')(default='', max_length=256, blank=True)), - ('scm_clean', self.gf('django.db.models.fields.BooleanField')(default=False)), - ('scm_delete_on_update', self.gf('django.db.models.fields.BooleanField')(default=False)), - ('credential', self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name='projectupdatenews', null=True, blank=True, to=orm['main.Credential'])), - ('project', self.gf('django.db.models.fields.related.ForeignKey')(related_name='project_updates', to=orm['main.ProjectNew'])), - )) - db.send_create_signal('main', ['ProjectUpdateNew']) - - # Adding model 'UnifiedJobTemplate' - db.create_table(u'main_unifiedjobtemplate', ( - (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), - ('polymorphic_ctype', self.gf('django.db.models.fields.related.ForeignKey')(related_name='polymorphic_main.unifiedjobtemplate_set', null=True, to=orm['contenttypes.ContentType'])), - ('created', self.gf('django.db.models.fields.DateTimeField')(default=None)), - ('modified', self.gf('django.db.models.fields.DateTimeField')(default=None)), - ('description', self.gf('django.db.models.fields.TextField')(default='', blank=True)), - ('created_by', self.gf('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=orm['auth.User'])), - ('modified_by', self.gf('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=orm['auth.User'])), - ('active', self.gf('django.db.models.fields.BooleanField')(default=True)), - ('name', self.gf('django.db.models.fields.CharField')(max_length=512)), - ('old_pk', self.gf('django.db.models.fields.PositiveIntegerField')(default=None, null=True)), - ('current_job', self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name='unifiedjobtemplate_as_current_job+', null=True, to=orm['main.UnifiedJob'])), - ('last_job', self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name='unifiedjobtemplate_as_last_job+', null=True, to=orm['main.UnifiedJob'])), - ('last_job_failed', self.gf('django.db.models.fields.BooleanField')(default=False)), - ('last_job_run', self.gf('django.db.models.fields.DateTimeField')(default=None, null=True)), - ('has_schedules', self.gf('django.db.models.fields.BooleanField')(default=False)), - ('next_job_run', self.gf('django.db.models.fields.DateTimeField')(default=None, null=True)), - ('status', self.gf('django.db.models.fields.CharField')(default='ok', max_length=32)), - )) - db.send_create_signal('main', ['UnifiedJobTemplate']) - - # Adding unique constraint on 'UnifiedJobTemplate', fields ['polymorphic_ctype', 'name'] - db.create_unique(u'main_unifiedjobtemplate', ['polymorphic_ctype_id', 'name']) - - - # Changing field 'Profile.created' - db.alter_column(u'main_profile', 'created', self.gf('django.db.models.fields.DateTimeField')()) - - # Changing field 'Profile.modified' - db.alter_column(u'main_profile', 'modified', self.gf('django.db.models.fields.DateTimeField')()) - # Adding field 'ProjectUpdate.local_path' - db.add_column(u'main_projectupdate', 'local_path', - self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True), - keep_default=False) - - # Adding field 'ProjectUpdate.scm_type' - db.add_column(u'main_projectupdate', 'scm_type', - self.gf('django.db.models.fields.CharField')(default='', max_length=8, blank=True), - keep_default=False) - - # Adding field 'ProjectUpdate.scm_url' - db.add_column(u'main_projectupdate', 'scm_url', - self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True), - keep_default=False) - - # Adding field 'ProjectUpdate.scm_branch' - db.add_column(u'main_projectupdate', 'scm_branch', - self.gf('django.db.models.fields.CharField')(default='', max_length=256, blank=True), - keep_default=False) - - # Adding field 'ProjectUpdate.scm_clean' - db.add_column(u'main_projectupdate', 'scm_clean', - self.gf('django.db.models.fields.BooleanField')(default=False), - keep_default=False) - - # Adding field 'ProjectUpdate.scm_delete_on_update' - db.add_column(u'main_projectupdate', 'scm_delete_on_update', - self.gf('django.db.models.fields.BooleanField')(default=False), - keep_default=False) - - # Adding field 'ProjectUpdate.credential' - db.add_column(u'main_projectupdate', 'credential', - self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name='projectupdates', null=True, blank=True, to=orm['main.Credential']), - keep_default=False) - - - # Changing field 'ProjectUpdate.created' - db.alter_column(u'main_projectupdate', 'created', self.gf('django.db.models.fields.DateTimeField')()) - - # Changing field 'ProjectUpdate.modified' - db.alter_column(u'main_projectupdate', 'modified', self.gf('django.db.models.fields.DateTimeField')()) - # Adding M2M table for field new_inventory_sources on 'Group' - m2m_table_name = db.shorten_name(u'main_group_new_inventory_sources') - db.create_table(m2m_table_name, ( - ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), - ('group', models.ForeignKey(orm['main.group'], null=False)), - ('inventorysourcenew', models.ForeignKey(orm['main.inventorysourcenew'], null=False)) - )) - db.create_unique(m2m_table_name, ['group_id', 'inventorysourcenew_id']) - - - # Changing field 'Group.created' - db.alter_column(u'main_group', 'created', self.gf('django.db.models.fields.DateTimeField')()) - - # Changing field 'Group.modified' - db.alter_column(u'main_group', 'modified', self.gf('django.db.models.fields.DateTimeField')()) - - # Changing field 'Job.created' - db.alter_column(u'main_job', 'created', self.gf('django.db.models.fields.DateTimeField')()) - - # Changing field 'Job.modified' - db.alter_column(u'main_job', 'modified', self.gf('django.db.models.fields.DateTimeField')()) - - # Changing field 'Inventory.created' - db.alter_column(u'main_inventory', 'created', self.gf('django.db.models.fields.DateTimeField')()) - - # Changing field 'Inventory.modified' - db.alter_column(u'main_inventory', 'modified', self.gf('django.db.models.fields.DateTimeField')()) - # Adding field 'Host.new_last_job' - db.add_column(u'main_host', 'new_last_job', - self.gf('django.db.models.fields.related.ForeignKey')(related_name='hosts_as_last_job+', on_delete=models.SET_NULL, default=None, to=orm['main.JobNew'], blank=True, null=True), - keep_default=False) - - # Adding M2M table for field new_inventory_sources on 'Host' - m2m_table_name = db.shorten_name(u'main_host_new_inventory_sources') - db.create_table(m2m_table_name, ( - ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), - ('host', models.ForeignKey(orm['main.host'], null=False)), - ('inventorysourcenew', models.ForeignKey(orm['main.inventorysourcenew'], null=False)) - )) - db.create_unique(m2m_table_name, ['host_id', 'inventorysourcenew_id']) - - - # Changing field 'Host.created' - db.alter_column(u'main_host', 'created', self.gf('django.db.models.fields.DateTimeField')()) - - # Changing field 'Host.modified' - db.alter_column(u'main_host', 'modified', self.gf('django.db.models.fields.DateTimeField')()) - # Adding field 'JobHostSummary.new_job' - db.add_column(u'main_jobhostsummary', 'new_job', - self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name='new_job_host_summaries', null=True, to=orm['main.JobNew']), - keep_default=False) - - - # Changing field 'JobHostSummary.created' - db.alter_column(u'main_jobhostsummary', 'created', self.gf('django.db.models.fields.DateTimeField')()) - - # Changing field 'JobHostSummary.modified' - db.alter_column(u'main_jobhostsummary', 'modified', self.gf('django.db.models.fields.DateTimeField')()) - # Adding unique constraint on 'JobHostSummary', fields ['new_job', 'host'] - db.create_unique(u'main_jobhostsummary', ['new_job_id', 'host_id']) - - # Adding field 'InventoryUpdate.source' - db.add_column(u'main_inventoryupdate', 'source', - self.gf('django.db.models.fields.CharField')(default='', max_length=32, blank=True), - keep_default=False) - - # Adding field 'InventoryUpdate.source_path' - db.add_column(u'main_inventoryupdate', 'source_path', - self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True), - keep_default=False) - - # Adding field 'InventoryUpdate.source_vars' - db.add_column(u'main_inventoryupdate', 'source_vars', + # Adding field 'ProjectUpdate.start_args' + db.add_column(u'main_projectupdate', 'start_args', self.gf('django.db.models.fields.TextField')(default='', blank=True), keep_default=False) - # Adding field 'InventoryUpdate.credential' - db.add_column(u'main_inventoryupdate', 'credential', - self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name='inventoryupdates', null=True, blank=True, to=orm['main.Credential']), + # Adding field 'Job.start_args' + db.add_column(u'main_job', 'start_args', + self.gf('django.db.models.fields.TextField')(default='', blank=True), keep_default=False) - # Adding field 'InventoryUpdate.source_regions' - db.add_column(u'main_inventoryupdate', 'source_regions', - self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True), - keep_default=False) - - # Adding field 'InventoryUpdate.overwrite' - db.add_column(u'main_inventoryupdate', 'overwrite', - self.gf('django.db.models.fields.BooleanField')(default=False), - keep_default=False) - - # Adding field 'InventoryUpdate.overwrite_vars' - db.add_column(u'main_inventoryupdate', 'overwrite_vars', - self.gf('django.db.models.fields.BooleanField')(default=False), - keep_default=False) - - - # Changing field 'InventoryUpdate.created' - db.alter_column(u'main_inventoryupdate', 'created', self.gf('django.db.models.fields.DateTimeField')()) - - # Changing field 'InventoryUpdate.modified' - db.alter_column(u'main_inventoryupdate', 'modified', self.gf('django.db.models.fields.DateTimeField')()) - - # Changing field 'Credential.created' - db.alter_column(u'main_credential', 'created', self.gf('django.db.models.fields.DateTimeField')()) - - # Changing field 'Credential.modified' - db.alter_column(u'main_credential', 'modified', self.gf('django.db.models.fields.DateTimeField')()) - - # Changing field 'JobTemplate.created' - db.alter_column(u'main_jobtemplate', 'created', self.gf('django.db.models.fields.DateTimeField')()) - - # Changing field 'JobTemplate.modified' - db.alter_column(u'main_jobtemplate', 'modified', self.gf('django.db.models.fields.DateTimeField')()) - # Adding M2M table for field unified_job_template on 'ActivityStream' - m2m_table_name = db.shorten_name(u'main_activitystream_unified_job_template') - db.create_table(m2m_table_name, ( - ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), - ('activitystream', models.ForeignKey(orm['main.activitystream'], null=False)), - ('unifiedjobtemplate', models.ForeignKey(orm['main.unifiedjobtemplate'], null=False)) - )) - db.create_unique(m2m_table_name, ['activitystream_id', 'unifiedjobtemplate_id']) - - # Adding M2M table for field unified_job on 'ActivityStream' - m2m_table_name = db.shorten_name(u'main_activitystream_unified_job') - db.create_table(m2m_table_name, ( - ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), - ('activitystream', models.ForeignKey(orm['main.activitystream'], null=False)), - ('unifiedjob', models.ForeignKey(orm['main.unifiedjob'], null=False)) - )) - db.create_unique(m2m_table_name, ['activitystream_id', 'unifiedjob_id']) - - # Adding M2M table for field new_inventory_source on 'ActivityStream' - m2m_table_name = db.shorten_name(u'main_activitystream_new_inventory_source') - db.create_table(m2m_table_name, ( - ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), - ('activitystream', models.ForeignKey(orm['main.activitystream'], null=False)), - ('inventorysourcenew', models.ForeignKey(orm['main.inventorysourcenew'], null=False)) - )) - db.create_unique(m2m_table_name, ['activitystream_id', 'inventorysourcenew_id']) - - # Adding M2M table for field new_inventory_update on 'ActivityStream' - m2m_table_name = db.shorten_name(u'main_activitystream_new_inventory_update') - db.create_table(m2m_table_name, ( - ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), - ('activitystream', models.ForeignKey(orm['main.activitystream'], null=False)), - ('inventoryupdatenew', models.ForeignKey(orm['main.inventoryupdatenew'], null=False)) - )) - db.create_unique(m2m_table_name, ['activitystream_id', 'inventoryupdatenew_id']) - - # Adding M2M table for field new_project on 'ActivityStream' - m2m_table_name = db.shorten_name(u'main_activitystream_new_project') - db.create_table(m2m_table_name, ( - ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), - ('activitystream', models.ForeignKey(orm['main.activitystream'], null=False)), - ('projectnew', models.ForeignKey(orm['main.projectnew'], null=False)) - )) - db.create_unique(m2m_table_name, ['activitystream_id', 'projectnew_id']) - - # Adding M2M table for field new_project_update on 'ActivityStream' - m2m_table_name = db.shorten_name(u'main_activitystream_new_project_update') - db.create_table(m2m_table_name, ( - ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), - ('activitystream', models.ForeignKey(orm['main.activitystream'], null=False)), - ('projectupdatenew', models.ForeignKey(orm['main.projectupdatenew'], null=False)) - )) - db.create_unique(m2m_table_name, ['activitystream_id', 'projectupdatenew_id']) - - # Adding M2M table for field new_job_template on 'ActivityStream' - m2m_table_name = db.shorten_name(u'main_activitystream_new_job_template') - db.create_table(m2m_table_name, ( - ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), - ('activitystream', models.ForeignKey(orm['main.activitystream'], null=False)), - ('jobtemplatenew', models.ForeignKey(orm['main.jobtemplatenew'], null=False)) - )) - db.create_unique(m2m_table_name, ['activitystream_id', 'jobtemplatenew_id']) - - # Adding M2M table for field new_job on 'ActivityStream' - m2m_table_name = db.shorten_name(u'main_activitystream_new_job') - db.create_table(m2m_table_name, ( - ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), - ('activitystream', models.ForeignKey(orm['main.activitystream'], null=False)), - ('jobnew', models.ForeignKey(orm['main.jobnew'], null=False)) - )) - db.create_unique(m2m_table_name, ['activitystream_id', 'jobnew_id']) - - # Adding M2M table for field new_projects on 'Team' - m2m_table_name = db.shorten_name(u'main_team_new_projects') - db.create_table(m2m_table_name, ( - ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), - ('team', models.ForeignKey(orm['main.team'], null=False)), - ('projectnew', models.ForeignKey(orm['main.projectnew'], null=False)) - )) - db.create_unique(m2m_table_name, ['team_id', 'projectnew_id']) - - - # Changing field 'Team.created' - db.alter_column(u'main_team', 'created', self.gf('django.db.models.fields.DateTimeField')()) - - # Changing field 'Team.modified' - db.alter_column(u'main_team', 'modified', self.gf('django.db.models.fields.DateTimeField')()) - # Adding field 'Project.scm_update_cache_timeout' - db.add_column(u'main_project', 'scm_update_cache_timeout', - self.gf('django.db.models.fields.PositiveIntegerField')(default=0), - keep_default=False) - - - # Changing field 'Project.created' - db.alter_column(u'main_project', 'created', self.gf('django.db.models.fields.DateTimeField')()) - - # Changing field 'Project.modified' - db.alter_column(u'main_project', 'modified', self.gf('django.db.models.fields.DateTimeField')()) - # Adding M2M table for field new_projects on 'Organization' - m2m_table_name = db.shorten_name(u'main_organization_new_projects') - db.create_table(m2m_table_name, ( - ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), - ('organization', models.ForeignKey(orm['main.organization'], null=False)), - ('projectnew', models.ForeignKey(orm['main.projectnew'], null=False)) - )) - db.create_unique(m2m_table_name, ['organization_id', 'projectnew_id']) - - - # Changing field 'Organization.created' - db.alter_column(u'main_organization', 'created', self.gf('django.db.models.fields.DateTimeField')()) - - # Changing field 'Organization.modified' - db.alter_column(u'main_organization', 'modified', self.gf('django.db.models.fields.DateTimeField')()) - # Adding field 'Permission.new_project' - db.add_column(u'main_permission', 'new_project', - self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='permissions', null=True, on_delete=models.SET_NULL, to=orm['main.ProjectNew']), - keep_default=False) - - - # Changing field 'Permission.created' - db.alter_column(u'main_permission', 'created', self.gf('django.db.models.fields.DateTimeField')()) - - # Changing field 'Permission.modified' - db.alter_column(u'main_permission', 'modified', self.gf('django.db.models.fields.DateTimeField')()) - # Deleting field 'InventorySource.update_interval' - db.delete_column(u'main_inventorysource', 'update_interval') - - # Adding field 'InventorySource.update_cache_timeout' - db.add_column(u'main_inventorysource', 'update_cache_timeout', - self.gf('django.db.models.fields.PositiveIntegerField')(default=0), - keep_default=False) - - - # Changing field 'InventorySource.created' - db.alter_column(u'main_inventorysource', 'created', self.gf('django.db.models.fields.DateTimeField')()) - - # Changing field 'InventorySource.modified' - db.alter_column(u'main_inventorysource', 'modified', self.gf('django.db.models.fields.DateTimeField')()) - # Adding field 'JobEvent.role' - db.add_column(u'main_jobevent', 'role', - self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True), - keep_default=False) - - # Adding field 'JobEvent.new_job' - db.add_column(u'main_jobevent', 'new_job', - self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name='new_job_events', null=True, to=orm['main.JobNew']), + # Adding field 'InventoryUpdate.start_args' + db.add_column(u'main_inventoryupdate', 'start_args', + self.gf('django.db.models.fields.TextField')(default='', blank=True), keep_default=False) def backwards(self, orm): - # Removing unique constraint on 'JobHostSummary', fields ['new_job', 'host'] - db.delete_unique(u'main_jobhostsummary', ['new_job_id', 'host_id']) + # Deleting field 'ProjectUpdate.start_args' + db.delete_column(u'main_projectupdate', 'start_args') - # Removing unique constraint on 'UnifiedJobTemplate', fields ['polymorphic_ctype', 'name'] - db.delete_unique(u'main_unifiedjobtemplate', ['polymorphic_ctype_id', 'name']) + # Deleting field 'Job.start_args' + db.delete_column(u'main_job', 'start_args') - # Deleting model 'InventoryUpdateNew' - db.delete_table(u'main_inventoryupdatenew') - - # Deleting model 'JobNew' - db.delete_table(u'main_jobnew') - - # Deleting model 'UnifiedJob' - db.delete_table(u'main_unifiedjob') - - # Removing M2M table for field depends_on on 'UnifiedJob' - db.delete_table(db.shorten_name(u'main_unifiedjob_depends_on')) - - # Deleting model 'Schedule' - db.delete_table(u'main_schedule') - - # Deleting model 'InventorySourceNew' - db.delete_table(u'main_inventorysourcenew') - - # Deleting model 'JobTemplateNew' - db.delete_table('main_jobtemplatenew') - - # Deleting model 'ProjectNew' - db.delete_table(u'main_projectnew') - - # Deleting model 'ProjectUpdateNew' - db.delete_table(u'main_projectupdatenew') - - # Deleting model 'UnifiedJobTemplate' - db.delete_table(u'main_unifiedjobtemplate') - - - # Changing field 'Profile.created' - db.alter_column(u'main_profile', 'created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True)) - - # Changing field 'Profile.modified' - db.alter_column(u'main_profile', 'modified', self.gf('django.db.models.fields.DateTimeField')(auto_now=True)) - # Deleting field 'ProjectUpdate.local_path' - db.delete_column(u'main_projectupdate', 'local_path') - - # Deleting field 'ProjectUpdate.scm_type' - db.delete_column(u'main_projectupdate', 'scm_type') - - # Deleting field 'ProjectUpdate.scm_url' - db.delete_column(u'main_projectupdate', 'scm_url') - - # Deleting field 'ProjectUpdate.scm_branch' - db.delete_column(u'main_projectupdate', 'scm_branch') - - # Deleting field 'ProjectUpdate.scm_clean' - db.delete_column(u'main_projectupdate', 'scm_clean') - - # Deleting field 'ProjectUpdate.scm_delete_on_update' - db.delete_column(u'main_projectupdate', 'scm_delete_on_update') - - # Deleting field 'ProjectUpdate.credential' - db.delete_column(u'main_projectupdate', 'credential_id') - - - # Changing field 'ProjectUpdate.created' - db.alter_column(u'main_projectupdate', 'created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True)) - - # Changing field 'ProjectUpdate.modified' - db.alter_column(u'main_projectupdate', 'modified', self.gf('django.db.models.fields.DateTimeField')(auto_now=True)) - # Removing M2M table for field new_inventory_sources on 'Group' - db.delete_table(db.shorten_name(u'main_group_new_inventory_sources')) - - - # Changing field 'Group.created' - db.alter_column(u'main_group', 'created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True)) - - # Changing field 'Group.modified' - db.alter_column(u'main_group', 'modified', self.gf('django.db.models.fields.DateTimeField')(auto_now=True)) - - # Changing field 'Job.created' - db.alter_column(u'main_job', 'created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True)) - - # Changing field 'Job.modified' - db.alter_column(u'main_job', 'modified', self.gf('django.db.models.fields.DateTimeField')(auto_now=True)) - - # Changing field 'Inventory.created' - db.alter_column(u'main_inventory', 'created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True)) - - # Changing field 'Inventory.modified' - db.alter_column(u'main_inventory', 'modified', self.gf('django.db.models.fields.DateTimeField')(auto_now=True)) - # Deleting field 'Host.new_last_job' - db.delete_column(u'main_host', 'new_last_job_id') - - # Removing M2M table for field new_inventory_sources on 'Host' - db.delete_table(db.shorten_name(u'main_host_new_inventory_sources')) - - - # Changing field 'Host.created' - db.alter_column(u'main_host', 'created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True)) - - # Changing field 'Host.modified' - db.alter_column(u'main_host', 'modified', self.gf('django.db.models.fields.DateTimeField')(auto_now=True)) - # Deleting field 'JobHostSummary.new_job' - db.delete_column(u'main_jobhostsummary', 'new_job_id') - - - # Changing field 'JobHostSummary.created' - db.alter_column(u'main_jobhostsummary', 'created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True)) - - # Changing field 'JobHostSummary.modified' - db.alter_column(u'main_jobhostsummary', 'modified', self.gf('django.db.models.fields.DateTimeField')(auto_now=True)) - # Deleting field 'InventoryUpdate.source' - db.delete_column(u'main_inventoryupdate', 'source') - - # Deleting field 'InventoryUpdate.source_path' - db.delete_column(u'main_inventoryupdate', 'source_path') - - # Deleting field 'InventoryUpdate.source_vars' - db.delete_column(u'main_inventoryupdate', 'source_vars') - - # Deleting field 'InventoryUpdate.credential' - db.delete_column(u'main_inventoryupdate', 'credential_id') - - # Deleting field 'InventoryUpdate.source_regions' - db.delete_column(u'main_inventoryupdate', 'source_regions') - - # Deleting field 'InventoryUpdate.overwrite' - db.delete_column(u'main_inventoryupdate', 'overwrite') - - # Deleting field 'InventoryUpdate.overwrite_vars' - db.delete_column(u'main_inventoryupdate', 'overwrite_vars') - - - # Changing field 'InventoryUpdate.created' - db.alter_column(u'main_inventoryupdate', 'created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True)) - - # Changing field 'InventoryUpdate.modified' - db.alter_column(u'main_inventoryupdate', 'modified', self.gf('django.db.models.fields.DateTimeField')(auto_now=True)) - - # Changing field 'Credential.created' - db.alter_column(u'main_credential', 'created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True)) - - # Changing field 'Credential.modified' - db.alter_column(u'main_credential', 'modified', self.gf('django.db.models.fields.DateTimeField')(auto_now=True)) - - # Changing field 'JobTemplate.created' - db.alter_column(u'main_jobtemplate', 'created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True)) - - # Changing field 'JobTemplate.modified' - db.alter_column(u'main_jobtemplate', 'modified', self.gf('django.db.models.fields.DateTimeField')(auto_now=True)) - # Removing M2M table for field unified_job_template on 'ActivityStream' - db.delete_table(db.shorten_name(u'main_activitystream_unified_job_template')) - - # Removing M2M table for field unified_job on 'ActivityStream' - db.delete_table(db.shorten_name(u'main_activitystream_unified_job')) - - # Removing M2M table for field new_inventory_source on 'ActivityStream' - db.delete_table(db.shorten_name(u'main_activitystream_new_inventory_source')) - - # Removing M2M table for field new_inventory_update on 'ActivityStream' - db.delete_table(db.shorten_name(u'main_activitystream_new_inventory_update')) - - # Removing M2M table for field new_project on 'ActivityStream' - db.delete_table(db.shorten_name(u'main_activitystream_new_project')) - - # Removing M2M table for field new_project_update on 'ActivityStream' - db.delete_table(db.shorten_name(u'main_activitystream_new_project_update')) - - # Removing M2M table for field new_job_template on 'ActivityStream' - db.delete_table(db.shorten_name(u'main_activitystream_new_job_template')) - - # Removing M2M table for field new_job on 'ActivityStream' - db.delete_table(db.shorten_name(u'main_activitystream_new_job')) - - # Removing M2M table for field new_projects on 'Team' - db.delete_table(db.shorten_name(u'main_team_new_projects')) - - - # Changing field 'Team.created' - db.alter_column(u'main_team', 'created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True)) - - # Changing field 'Team.modified' - db.alter_column(u'main_team', 'modified', self.gf('django.db.models.fields.DateTimeField')(auto_now=True)) - # Deleting field 'Project.scm_update_cache_timeout' - db.delete_column(u'main_project', 'scm_update_cache_timeout') - - - # Changing field 'Project.created' - db.alter_column(u'main_project', 'created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True)) - - # Changing field 'Project.modified' - db.alter_column(u'main_project', 'modified', self.gf('django.db.models.fields.DateTimeField')(auto_now=True)) - # Removing M2M table for field new_projects on 'Organization' - db.delete_table(db.shorten_name(u'main_organization_new_projects')) - - - # Changing field 'Organization.created' - db.alter_column(u'main_organization', 'created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True)) - - # Changing field 'Organization.modified' - db.alter_column(u'main_organization', 'modified', self.gf('django.db.models.fields.DateTimeField')(auto_now=True)) - # Deleting field 'Permission.new_project' - db.delete_column(u'main_permission', 'new_project_id') - - - # Changing field 'Permission.created' - db.alter_column(u'main_permission', 'created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True)) - - # Changing field 'Permission.modified' - db.alter_column(u'main_permission', 'modified', self.gf('django.db.models.fields.DateTimeField')(auto_now=True)) - # Adding field 'InventorySource.update_interval' - db.add_column(u'main_inventorysource', 'update_interval', - self.gf('django.db.models.fields.PositiveIntegerField')(default=0), - keep_default=False) - - # Deleting field 'InventorySource.update_cache_timeout' - db.delete_column(u'main_inventorysource', 'update_cache_timeout') - - - # Changing field 'InventorySource.created' - db.alter_column(u'main_inventorysource', 'created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True)) - - # Changing field 'InventorySource.modified' - db.alter_column(u'main_inventorysource', 'modified', self.gf('django.db.models.fields.DateTimeField')(auto_now=True)) - # Deleting field 'JobEvent.role' - db.delete_column(u'main_jobevent', 'role') - - # Deleting field 'JobEvent.new_job' - db.delete_column(u'main_jobevent', 'new_job_id') + # Deleting field 'InventoryUpdate.start_args' + db.delete_column(u'main_inventoryupdate', 'start_args') models = { @@ -780,12 +85,6 @@ class Migration(SchemaMigration): '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'}), - 'new_inventory_source': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.InventorySourceNew']", 'symmetrical': 'False', 'blank': 'True'}), - 'new_inventory_update': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.InventoryUpdateNew']", 'symmetrical': 'False', 'blank': 'True'}), - 'new_job': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.JobNew']", 'symmetrical': 'False', 'blank': 'True'}), - 'new_job_template': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.JobTemplateNew']", 'symmetrical': 'False', 'blank': 'True'}), - 'new_project': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.ProjectNew']", 'symmetrical': 'False', 'blank': 'True'}), - 'new_project_update': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.ProjectUpdateNew']", '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'}), @@ -796,8 +95,6 @@ class Migration(SchemaMigration): 'project_update': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.ProjectUpdate']", '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': { @@ -813,12 +110,12 @@ class Migration(SchemaMigration): 'Meta': {'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': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), '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'}), 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': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now', 'auto_now': 'True', 'blank': 'True'}), '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'}), @@ -833,7 +130,7 @@ class Migration(SchemaMigration): 'main.group': { 'Meta': {'unique_together': "(('name', 'inventory'),)", 'object_name': 'Group'}, 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'created': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), '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'}), @@ -844,10 +141,9 @@ class Migration(SchemaMigration): 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', [], {'symmetrical': 'False', 'related_name': "'groups'", 'blank': 'True', 'to': "orm['main.InventorySource']"}), - 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now', 'auto_now': 'True', 'blank': 'True'}), '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'}), - 'new_inventory_sources': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'groups'", 'blank': 'True', 'to': "orm['main.InventorySourceNew']"}), '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'}), @@ -856,7 +152,7 @@ class Migration(SchemaMigration): 'main.host': { 'Meta': {'unique_together': "(('name', 'inventory'),)", 'object_name': 'Host'}, 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'created': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), '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'}), @@ -868,17 +164,15 @@ class Migration(SchemaMigration): 'inventory_sources': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'hosts'", 'blank': 'True', 'to': "orm['main.InventorySource']"}), 'last_job': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'hosts_as_last_job+'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.Job']", 'blank': 'True', 'null': 'True'}), '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': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now', 'auto_now': 'True', 'blank': 'True'}), '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'}), - 'new_inventory_sources': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'hosts'", 'blank': 'True', 'to': "orm['main.InventorySourceNew']"}), - 'new_last_job': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'hosts_as_last_job+'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.JobNew']", 'blank': 'True', 'null': 'True'}), 'variables': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}) }, 'main.inventory': { 'Meta': {'unique_together': "[('name', 'organization')]", 'object_name': 'Inventory'}, 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'created': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), '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'}), @@ -887,7 +181,7 @@ class Migration(SchemaMigration): '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': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now', 'auto_now': 'True', 'blank': 'True'}), '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']"}), @@ -899,9 +193,9 @@ class Migration(SchemaMigration): 'main.inventorysource': { 'Meta': {'object_name': 'InventorySource'}, 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'created': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), 'created_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'inventorysource\', \'app_label\': \'main\'}(class)s_created+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), - 'credential': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'inventorysources'", 'null': 'True', 'blank': 'True', 'to': "orm['main.Credential']"}), + 'credential': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'inventory_sources'", 'null': 'True', 'blank': 'True', 'to': "orm['main.Credential']"}), 'current_update': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'inventory_source_as_current_update+'", 'null': 'True', 'to': "orm['main.InventoryUpdate']"}), 'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), 'group': ('awx.main.fields.AutoOneToOneField', [], {'related_name': "'inventory_source'", 'null': 'True', 'default': 'None', 'to': "orm['main.Group']", 'blank': 'True', 'unique': 'True'}), @@ -910,7 +204,7 @@ class Migration(SchemaMigration): 'last_update': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'inventory_source_as_last_update+'", 'null': 'True', 'to': "orm['main.InventoryUpdate']"}), 'last_update_failed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 'last_updated': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}), - 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now', 'auto_now': 'True', 'blank': 'True'}), 'modified_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'inventorysource\', \'app_label\': \'main\'}(class)s_modified+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), 'overwrite': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 'overwrite_vars': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), @@ -919,22 +213,7 @@ class Migration(SchemaMigration): 'source_regions': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), 'source_vars': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), 'status': ('django.db.models.fields.CharField', [], {'default': "'none'", 'max_length': '32'}), - 'update_cache_timeout': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), - 'update_on_launch': ('django.db.models.fields.BooleanField', [], {'default': 'False'}) - }, - 'main.inventorysourcenew': { - 'Meta': {'object_name': 'InventorySourceNew', '_ormbases': ['main.UnifiedJobTemplate']}, - 'credential': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'inventorysourcenews'", 'null': 'True', 'blank': 'True', 'to': "orm['main.Credential']"}), - 'group': ('awx.main.fields.AutoOneToOneField', [], {'related_name': "'new_inventory_source'", 'null': 'True', 'default': 'None', 'to': "orm['main.Group']", 'blank': 'True', 'unique': 'True'}), - 'inventory': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'new_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_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_interval': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), 'update_on_launch': ('django.db.models.fields.BooleanField', [], {'default': 'False'}) }, 'main.inventoryupdate': { @@ -943,9 +222,8 @@ class Migration(SchemaMigration): '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': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), 'created_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'inventoryupdate\', \'app_label\': \'main\'}(class)s_created+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), - 'credential': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'inventoryupdates'", 'null': 'True', 'blank': 'True', 'to': "orm['main.Credential']"}), 'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), 'failed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), @@ -954,31 +232,13 @@ class Migration(SchemaMigration): 'job_cwd': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), 'job_env': ('jsonfield.fields.JSONField', [], {'default': '{}', 'blank': 'True'}), 'license_error': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now', 'auto_now': 'True', 'blank': 'True'}), 'modified_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'inventoryupdate\', \'app_label\': \'main\'}(class)s_modified+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), - 'overwrite': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'overwrite_vars': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 'result_stdout_file': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), 'result_traceback': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), - '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_vars': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'start_args': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), 'status': ('django.db.models.fields.CharField', [], {'default': "'new'", 'max_length': '20'}) }, - 'main.inventoryupdatenew': { - 'Meta': {'object_name': 'InventoryUpdateNew', '_ormbases': ['main.UnifiedJob']}, - 'credential': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'inventoryupdatenews'", 'null': 'True', 'blank': 'True', 'to': "orm['main.Credential']"}), - 'inventory_source': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'inventory_updates'", 'to': "orm['main.InventorySourceNew']"}), - '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_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': {'object_name': 'Job'}, '_result_stdout': ('django.db.models.fields.TextField', [], {'default': "''", 'db_column': "'result_stdout'", 'blank': 'True'}), @@ -986,9 +246,9 @@ class Migration(SchemaMigration): 'cancel_flag': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 'celery_task_id': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '100', 'blank': 'True'}), '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'}), - 'created': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), 'created_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'job\', \'app_label\': \'main\'}(class)s_created+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), - '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'}), + 'credential': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobs'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Credential']"}), 'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), 'extra_vars': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), 'failed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), @@ -1004,12 +264,13 @@ class Migration(SchemaMigration): 'job_type': ('django.db.models.fields.CharField', [], {'max_length': '64'}), 'launch_type': ('django.db.models.fields.CharField', [], {'default': "'manual'", 'max_length': '20'}), 'limit': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), - 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now', 'auto_now': 'True', 'blank': 'True'}), 'modified_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'job\', \'app_label\': \'main\'}(class)s_modified+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), - 'playbook': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024'}), + 'playbook': ('django.db.models.fields.CharField', [], {'max_length': '1024'}), 'project': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobs'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Project']"}), 'result_stdout_file': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), 'result_traceback': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'start_args': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), 'status': ('django.db.models.fields.CharField', [], {'default': "'new'", 'max_length': '20'}), 'verbosity': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0', 'blank': 'True'}) }, @@ -1025,111 +286,73 @@ class Migration(SchemaMigration): 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'}), - 'new_job': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'new_job_events'", 'null': 'True', 'to': "orm['main.JobNew']"}), 'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'children'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.JobEvent']", 'blank': 'True', 'null': 'True'}), 'play': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), - 'role': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), 'task': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}) }, 'main.jobhostsummary': { - 'Meta': {'ordering': "('-pk',)", 'unique_together': "[('job', 'host'), ('new_job', 'host')]", 'object_name': 'JobHostSummary'}, + 'Meta': {'ordering': "('-pk',)", 'unique_together': "[('job', 'host')]", 'object_name': 'JobHostSummary'}, 'changed': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), - 'created': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now', 'auto_now_add': 'True', 'blank': 'True'}), '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', [], {'related_name': "'job_host_summaries'", 'to': "orm['main.Host']"}), 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'}), - 'new_job': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'new_job_host_summaries'", 'null': 'True', 'to': "orm['main.JobNew']"}), + 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now', 'auto_now': 'True', 'blank': 'True'}), '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.jobnew': { - 'Meta': {'object_name': 'JobNew', '_ormbases': ['main.UnifiedJob']}, - 'cloud_credential': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobnews_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': "'jobnews'", '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'}), - 'forks': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0', 'blank': 'True'}), - 'hosts': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'jobnews'", 'blank': 'True', 'through': "orm['main.JobHostSummary']", 'to': "orm['main.Host']"}), - 'inventory': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobnews'", '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.JobTemplateNew']", '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.ProjectNew']"}), - 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.jobtemplate': { 'Meta': {'object_name': 'JobTemplate'}, 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - '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'}), - 'created': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'cloud_credential': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'job_templates_as_cloud_credential+'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.Credential']", 'blank': 'True', 'null': 'True'}), + 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), 'created_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'jobtemplate\', \'app_label\': \'main\'}(class)s_created+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), - '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'}), + 'credential': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'job_templates'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.Credential']", 'blank': 'True', 'null': 'True'}), 'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), 'extra_vars': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), 'forks': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0', 'blank': 'True'}), 'host_config_key': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'inventory': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobtemplates'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Inventory']"}), + 'inventory': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'job_templates'", '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'}), - 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now', 'auto_now': 'True', 'blank': 'True'}), 'modified_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'jobtemplate\', \'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'}), 'playbook': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024'}), 'project': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'job_templates'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Project']"}), 'verbosity': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0', 'blank': 'True'}) }, - 'main.jobtemplatenew': { - 'Meta': {'object_name': 'JobTemplateNew', '_ormbases': ['main.UnifiedJobTemplate']}, - 'cloud_credential': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobtemplatenews_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': "'jobtemplatenews'", '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'}), - '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': "'jobtemplatenews'", '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': "'job_templates'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.ProjectNew']"}), - 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': {'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': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), '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': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now', 'auto_now': 'True', 'blank': 'True'}), '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'}), - 'new_projects': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'organizations'", 'blank': 'True', 'to': "orm['main.ProjectNew']"}), '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': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), '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': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now', 'auto_now': 'True', 'blank': 'True'}), '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'}), - 'new_project': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'permissions'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.ProjectNew']"}), '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']"}), @@ -1137,16 +360,16 @@ class Migration(SchemaMigration): }, 'main.profile': { 'Meta': {'object_name': 'Profile'}, - 'created': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), 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'}), + 'modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), 'user': ('awx.main.fields.AutoOneToOneField', [], {'related_name': "'profile'", 'unique': 'True', 'to': u"orm['auth.User']"}) }, 'main.project': { 'Meta': {'object_name': 'Project'}, 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'created': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), 'created_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'project\', \'app_label\': \'main\'}(class)s_created+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), 'credential': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'projects'", 'null': 'True', 'blank': 'True', 'to': "orm['main.Credential']"}), 'current_update': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'project_as_current_update+'", 'null': 'True', 'to': "orm['main.ProjectUpdate']"}), @@ -1156,7 +379,7 @@ class Migration(SchemaMigration): 'last_update_failed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 'last_updated': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}), 'local_path': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'blank': 'True'}), - 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now', 'auto_now': 'True', 'blank': 'True'}), 'modified_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'project\', \'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'}), 'scm_branch': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '256', 'blank': 'True'}), @@ -1164,145 +387,46 @@ class Migration(SchemaMigration): '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'}), 'status': ('django.db.models.fields.CharField', [], {'default': "'ok'", 'max_length': '32', 'null': 'True'}) }, - 'main.projectnew': { - 'Meta': {'object_name': 'ProjectNew', '_ormbases': ['main.UnifiedJobTemplate']}, - 'credential': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'projectnews'", 'null': 'True', 'blank': 'True', 'to': "orm['main.Credential']"}), - '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'}, '_result_stdout': ('django.db.models.fields.TextField', [], {'default': "''", 'db_column': "'result_stdout'", 'blank': 'True'}), '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': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), 'created_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'projectupdate\', \'app_label\': \'main\'}(class)s_created+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), - 'credential': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'projectupdates'", 'null': 'True', 'blank': 'True', 'to': "orm['main.Credential']"}), 'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), 'failed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 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'}), - 'local_path': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'blank': 'True'}), - 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now', 'auto_now': 'True', 'blank': 'True'}), 'modified_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'projectupdate\', \'app_label\': \'main\'}(class)s_modified+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), 'project': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'project_updates'", 'to': "orm['main.Project']"}), 'result_stdout_file': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), 'result_traceback': ('django.db.models.fields.TextField', [], {'default': "''", '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_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'}), + 'start_args': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), 'status': ('django.db.models.fields.CharField', [], {'default': "'new'", 'max_length': '20'}) }, - 'main.projectupdatenew': { - 'Meta': {'object_name': 'ProjectUpdateNew', '_ormbases': ['main.UnifiedJob']}, - 'credential': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'projectupdatenews'", 'null': 'True', 'blank': 'True', 'to': "orm['main.Credential']"}), - '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.ProjectNew']"}), - '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': {'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', [], {}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'job_template': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'schedules'", 'to': "orm['main.UnifiedJobTemplate']"}), - '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'}), - 'rrule': ('django.db.models.fields.CharField', [], {'max_length': '255'}) - }, 'main.team': { 'Meta': {'unique_together': "[('organization', 'name')]", 'object_name': 'Team'}, 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'created': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), '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': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now', 'auto_now': 'True', 'blank': 'True'}), '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'}), - 'new_projects': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'teams'", 'blank': 'True', 'to': "orm['main.ProjectNew']"}), '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']"}), - 'depends_on': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'depends_on_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'}), - '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']"}), - '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'}), - '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', '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', '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', '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'}), - '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'}) - }, u'taggit.tag': { 'Meta': {'object_name': 'Tag'}, u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), diff --git a/awx/main/migrations/0035_v148_changes.py b/awx/main/migrations/0035_v148_changes.py index 0801683e42..354b7b166f 100644 --- a/awx/main/migrations/0035_v148_changes.py +++ b/awx/main/migrations/0035_v148_changes.py @@ -1,299 +1,814 @@ # -*- coding: utf-8 -*- from south.utils import datetime_utils as datetime from south.db import db -from south.v2 import DataMigration +from south.v2 import SchemaMigration from django.db import models -from django.utils.encoding import smart_text -class Migration(DataMigration): - def _get_dict_from_primordial_model(self, instance): - return { - 'description': instance.description, - 'created': instance.created, - 'modified': instance.modified, - 'created_by': instance.created_by, - 'modified_by': instance.modified_by, - 'active': instance.active, - 'old_pk': instance.pk, - } - - def _get_dict_from_common_model(self, instance): - d = self._get_dict_from_primordial_model(instance) - if hasattr(instance, 'name'): - d['name'] = instance.name - else: - d['name'] = u'%s-%s' % (instance._meta.verbose_name, instance.pk) - return d - - def _get_dict_from_common_task_model(self, instance): - d = self._get_dict_from_primordial_model(instance) - td = instance.modified - instance.created - elapsed = (td.microseconds + (td.seconds + td.days * 24 * 3600) * 10**6) / (10**6 * 1.0) - d.update({ - 'launch_type': getattr(instance, 'launch_type', 'manual'), - 'cancel_flag': instance.cancel_flag, - 'status': instance.status, - 'failed': instance.failed, - 'started': instance.created, - 'finished': instance.modified, - 'elapsed': elapsed, - 'job_args': instance.job_args, - 'job_env': instance.job_env, - 'result_stdout_text': instance._result_stdout, - 'result_stdout_file': instance.result_stdout_file, - 'result_traceback': instance.result_traceback, - 'celery_task_id': instance.celery_task_id, - }) - return d - - def _get_content_type_for_model(self, orm, model): - app_label = model._meta.app_label - model_name = model._meta.module_name - defaults = {'name': smart_text(model._meta.verbose_name_raw)} - content_type, created = orm['contenttypes.ContentType'].objects.get_or_create(app_label=app_label, model=model_name, defaults=defaults) - return content_type +class Migration(SchemaMigration): def forwards(self, orm): - "Write your forwards methods here." + # Adding model 'InventoryUpdateNew' + db.create_table(u'main_inventoryupdatenew', ( + (u'unifiedjob_ptr', self.gf('django.db.models.fields.related.OneToOneField')(to=orm['main.UnifiedJob'], unique=True, primary_key=True)), + ('source', self.gf('django.db.models.fields.CharField')(default='', max_length=32, blank=True)), + ('source_path', self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True)), + ('source_vars', self.gf('django.db.models.fields.TextField')(default='', blank=True)), + ('credential', self.gf('django.db.models.fields.related.ForeignKey')(related_name='inventoryupdatenews', on_delete=models.SET_NULL, default=None, to=orm['main.Credential'], blank=True, null=True)), + ('source_regions', self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True)), + ('overwrite', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('overwrite_vars', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('license_error', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('inventory_source', self.gf('django.db.models.fields.related.ForeignKey')(related_name='inventory_updates', to=orm['main.InventorySourceNew'])), + )) + db.send_create_signal('main', ['InventoryUpdateNew']) - # Copy Project old to new. - new_ctype = self._get_content_type_for_model(orm, orm.Project) - for project in orm.Project.objects.order_by('pk'): - d = self._get_dict_from_common_model(project) - d.update({ - 'polymorphic_ctype_id': new_ctype.pk, - 'local_path': project.local_path, - 'scm_type': project.scm_type, - 'scm_url': project.scm_url, - 'scm_branch': project.scm_branch, - 'scm_clean': project.scm_clean, - 'scm_delete_on_update': project.scm_delete_on_update, - 'credential_id': project.credential_id, - 'scm_delete_on_next_update': project.scm_delete_on_next_update, - 'scm_update_on_launch': project.scm_update_on_launch, - }) - new_project, created = orm.ProjectNew.objects.get_or_create(old_pk=project.pk, defaults=d) + # Adding model 'JobNew' + db.create_table(u'main_jobnew', ( + (u'unifiedjob_ptr', self.gf('django.db.models.fields.related.OneToOneField')(to=orm['main.UnifiedJob'], unique=True, primary_key=True)), + ('job_type', self.gf('django.db.models.fields.CharField')(max_length=64)), + ('inventory', self.gf('django.db.models.fields.related.ForeignKey')(related_name='jobnews', null=True, on_delete=models.SET_NULL, to=orm['main.Inventory'])), + ('playbook', self.gf('django.db.models.fields.CharField')(default='', max_length=1024)), + ('credential', self.gf('django.db.models.fields.related.ForeignKey')(related_name='jobnews', on_delete=models.SET_NULL, default=None, to=orm['main.Credential'], blank=True, null=True)), + ('cloud_credential', self.gf('django.db.models.fields.related.ForeignKey')(related_name='jobnews_as_cloud_credential+', on_delete=models.SET_NULL, default=None, to=orm['main.Credential'], blank=True, null=True)), + ('forks', self.gf('django.db.models.fields.PositiveIntegerField')(default=0, blank=True)), + ('limit', self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True)), + ('verbosity', self.gf('django.db.models.fields.PositiveIntegerField')(default=0, blank=True)), + ('extra_vars', self.gf('django.db.models.fields.TextField')(default='', blank=True)), + ('job_tags', self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True)), + ('job_template', self.gf('django.db.models.fields.related.ForeignKey')(related_name='jobs', on_delete=models.SET_NULL, default=None, to=orm['main.JobTemplateNew'], blank=True, null=True)), + ('project', self.gf('django.db.models.fields.related.ForeignKey')(related_name='jobs', null=True, on_delete=models.SET_NULL, to=orm['main.ProjectNew'])), + )) + db.send_create_signal('main', ['JobNew']) - # Copy ProjectUpdate old to new. - new_ctype = self._get_content_type_for_model(orm, orm.ProjectUpdate) - for project_update in orm.ProjectUpdate.objects.order_by('pk'): - project = project_update.project - new_project = orm.ProjectNew.objects.get(old_pk=project_update.project_id) - d = self._get_dict_from_common_task_model(project_update) - d.update({ - 'polymorphic_ctype_id': new_ctype.pk, - 'project_id': new_project.pk, - 'unified_job_template_id': new_project.pk, - 'local_path': project.local_path, - 'scm_type': project.scm_type, - 'scm_url': project.scm_url, - 'scm_branch': project.scm_branch, - 'scm_clean': project.scm_clean, - 'scm_delete_on_update': project.scm_delete_on_update, - 'credential_id': project.credential_id, - }) - new_project_update, created = orm.ProjectUpdateNew.objects.get_or_create(old_pk=project_update.pk, defaults=d) + # Adding model 'UnifiedJob' + db.create_table(u'main_unifiedjob', ( + (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('polymorphic_ctype', self.gf('django.db.models.fields.related.ForeignKey')(related_name='polymorphic_main.unifiedjob_set', null=True, to=orm['contenttypes.ContentType'])), + ('created', self.gf('django.db.models.fields.DateTimeField')(default=None)), + ('modified', self.gf('django.db.models.fields.DateTimeField')(default=None)), + ('description', self.gf('django.db.models.fields.TextField')(default='', blank=True)), + ('created_by', self.gf('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=orm['auth.User'])), + ('modified_by', self.gf('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=orm['auth.User'])), + ('active', self.gf('django.db.models.fields.BooleanField')(default=True)), + ('name', self.gf('django.db.models.fields.CharField')(max_length=512)), + ('old_pk', self.gf('django.db.models.fields.PositiveIntegerField')(default=None, null=True)), + ('unified_job_template', self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name='unifiedjob_unified_jobs', null=True, on_delete=models.SET_NULL, to=orm['main.UnifiedJobTemplate'])), + ('launch_type', self.gf('django.db.models.fields.CharField')(default='manual', max_length=20)), + ('schedule', self.gf('django.db.models.fields.related.ForeignKey')(default=None, to=orm['main.Schedule'], null=True, on_delete=models.SET_NULL)), + ('cancel_flag', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('status', self.gf('django.db.models.fields.CharField')(default='new', max_length=20)), + ('failed', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('started', self.gf('django.db.models.fields.DateTimeField')(default=None, null=True)), + ('finished', self.gf('django.db.models.fields.DateTimeField')(default=None, null=True)), + ('elapsed', self.gf('django.db.models.fields.DecimalField')(max_digits=12, decimal_places=3)), + ('job_args', self.gf('django.db.models.fields.TextField')(default='', blank=True)), + ('job_cwd', self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True)), + ('job_env', self.gf('jsonfield.fields.JSONField')(default={}, blank=True)), + ('start_args', self.gf('django.db.models.fields.TextField')(default='', blank=True)), + ('result_stdout_text', self.gf('django.db.models.fields.TextField')(default='', blank=True)), + ('result_stdout_file', self.gf('django.db.models.fields.TextField')(default='', blank=True)), + ('result_traceback', self.gf('django.db.models.fields.TextField')(default='', blank=True)), + ('celery_task_id', self.gf('django.db.models.fields.CharField')(default='', max_length=100, blank=True)), + )) + db.send_create_signal('main', ['UnifiedJob']) - # Update Project last run. - for project in orm.Project.objects.order_by('pk'): - new_project = orm.ProjectNew.objects.get(old_pk=project.pk) - if project.current_update: - new_project.current_job = orm.ProjectUpdateNew.objects.get(old_pk=project.current_update_id) - if project.last_update: - new_project.last_job = orm.ProjectUpdateNew.objects.get(old_pk=project.last_update_id) - new_project.last_job_failed = project.last_update_failed - new_project.last_job_run = project.last_updated - new_project.status = project.status - new_project.save() + # Adding M2M table for field dependent_jobs on 'UnifiedJob' + m2m_table_name = db.shorten_name(u'main_unifiedjob_dependent_jobs') + db.create_table(m2m_table_name, ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('from_unifiedjob', models.ForeignKey(orm['main.unifiedjob'], null=False)), + ('to_unifiedjob', models.ForeignKey(orm['main.unifiedjob'], null=False)) + )) + db.create_unique(m2m_table_name, ['from_unifiedjob_id', 'to_unifiedjob_id']) - # Update Organization projects. - for organization in orm.Organization.objects.order_by('pk'): - for project in organization.projects.order_by('pk'): - new_project = orm.ProjectNew.objects.get(old_pk=project.pk) - organization.new_projects.add(new_project) + # Adding model 'Schedule' + db.create_table(u'main_schedule', ( + (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('created', self.gf('django.db.models.fields.DateTimeField')(default=None)), + ('modified', self.gf('django.db.models.fields.DateTimeField')(default=None)), + ('description', self.gf('django.db.models.fields.TextField')(default='', blank=True)), + ('created_by', self.gf('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=orm['auth.User'])), + ('modified_by', self.gf('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=orm['auth.User'])), + ('active', self.gf('django.db.models.fields.BooleanField')(default=True)), + ('name', self.gf('django.db.models.fields.CharField')(unique=True, max_length=512)), + ('unified_job_template', self.gf('django.db.models.fields.related.ForeignKey')(related_name='schedules', to=orm['main.UnifiedJobTemplate'])), + ('enabled', self.gf('django.db.models.fields.BooleanField')(default=True)), + ('dtstart', self.gf('django.db.models.fields.DateTimeField')()), + ('dtend', self.gf('django.db.models.fields.DateTimeField')(default=None, null=True)), + ('rrule', self.gf('django.db.models.fields.CharField')(max_length=255)), + ('next_run', self.gf('django.db.models.fields.DateTimeField')(default=None, null=True)), + )) + db.send_create_signal('main', ['Schedule']) - # Update Team projects. - for team in orm.Team.objects.order_by('pk'): - for project in team.projects.order_by('pk'): - new_project = orm.ProjectNew.objects.get(old_pk=project.pk) - team.new_projects.add(new_project) + # Adding model 'InventorySourceNew' + db.create_table(u'main_inventorysourcenew', ( + (u'unifiedjobtemplate_ptr', self.gf('django.db.models.fields.related.OneToOneField')(to=orm['main.UnifiedJobTemplate'], unique=True, primary_key=True)), + ('source', self.gf('django.db.models.fields.CharField')(default='', max_length=32, blank=True)), + ('source_path', self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True)), + ('source_vars', self.gf('django.db.models.fields.TextField')(default='', blank=True)), + ('credential', self.gf('django.db.models.fields.related.ForeignKey')(related_name='inventorysourcenews', on_delete=models.SET_NULL, default=None, to=orm['main.Credential'], blank=True, null=True)), + ('source_regions', self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True)), + ('overwrite', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('overwrite_vars', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('update_on_launch', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('update_cache_timeout', self.gf('django.db.models.fields.PositiveIntegerField')(default=0)), + ('inventory', self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name='new_inventory_sources', null=True, to=orm['main.Inventory'])), + ('group', self.gf('awx.main.fields.AutoOneToOneField')(default=None, related_name='new_inventory_source', unique=True, null=True, to=orm['main.Group'])), + )) + db.send_create_signal('main', ['InventorySourceNew']) - # Update Permission project. - for permission in orm.Permission.objects.order_by('pk'): - if not permission.project_id: - continue - new_project = orm.ProjectNew.objects.get(old_pk=permission.project_id) - permission.new_project = new_project - permission.save() + # Adding model 'JobTemplateNew' + db.create_table('main_jobtemplatenew', ( + (u'unifiedjobtemplate_ptr', self.gf('django.db.models.fields.related.OneToOneField')(to=orm['main.UnifiedJobTemplate'], unique=True, primary_key=True)), + ('job_type', self.gf('django.db.models.fields.CharField')(max_length=64)), + ('inventory', self.gf('django.db.models.fields.related.ForeignKey')(related_name='jobtemplatenews', null=True, on_delete=models.SET_NULL, to=orm['main.Inventory'])), + ('playbook', self.gf('django.db.models.fields.CharField')(default='', max_length=1024)), + ('credential', self.gf('django.db.models.fields.related.ForeignKey')(related_name='jobtemplatenews', on_delete=models.SET_NULL, default=None, to=orm['main.Credential'], blank=True, null=True)), + ('cloud_credential', self.gf('django.db.models.fields.related.ForeignKey')(related_name='jobtemplatenews_as_cloud_credential+', on_delete=models.SET_NULL, default=None, to=orm['main.Credential'], blank=True, null=True)), + ('forks', self.gf('django.db.models.fields.PositiveIntegerField')(default=0, blank=True)), + ('limit', self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True)), + ('verbosity', self.gf('django.db.models.fields.PositiveIntegerField')(default=0, blank=True)), + ('extra_vars', self.gf('django.db.models.fields.TextField')(default='', blank=True)), + ('job_tags', self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True)), + ('host_config_key', self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True)), + ('project', self.gf('django.db.models.fields.related.ForeignKey')(related_name='job_templates', null=True, on_delete=models.SET_NULL, to=orm['main.ProjectNew'])), + )) + db.send_create_signal('main', ['JobTemplateNew']) - # Copy InventorySource old to new. - new_ctype = self._get_content_type_for_model(orm, orm.InventorySource) - for inventory_source in orm.InventorySource.objects.order_by('pk'): - d = self._get_dict_from_common_model(inventory_source) - d.update({ - 'polymorphic_ctype_id': new_ctype.pk, - 'source': inventory_source.source, - 'source_path': inventory_source.source_path, - 'source_vars': inventory_source.source_vars, - 'credential_id': inventory_source.credential_id, - 'source_regions': inventory_source.source_regions, - 'overwrite': inventory_source.overwrite, - 'overwrite_vars': inventory_source.overwrite_vars, - 'update_on_launch': inventory_source.update_on_launch, - 'inventory_id': inventory_source.inventory_id, - 'group_id': inventory_source.group_id, - }) - new_inventory_source, created = orm.InventorySourceNew.objects.get_or_create(old_pk=inventory_source.pk, defaults=d) + # Adding model 'ProjectNew' + db.create_table(u'main_projectnew', ( + (u'unifiedjobtemplate_ptr', self.gf('django.db.models.fields.related.OneToOneField')(to=orm['main.UnifiedJobTemplate'], unique=True, primary_key=True)), + ('local_path', self.gf('django.db.models.fields.CharField')(max_length=1024, blank=True)), + ('scm_type', self.gf('django.db.models.fields.CharField')(default='', max_length=8, blank=True)), + ('scm_url', self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True)), + ('scm_branch', self.gf('django.db.models.fields.CharField')(default='', max_length=256, blank=True)), + ('scm_clean', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('scm_delete_on_update', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('credential', self.gf('django.db.models.fields.related.ForeignKey')(related_name='projectnews', on_delete=models.SET_NULL, default=None, to=orm['main.Credential'], blank=True, null=True)), + ('scm_delete_on_next_update', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('scm_update_on_launch', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('scm_update_cache_timeout', self.gf('django.db.models.fields.PositiveIntegerField')(default=0)), + )) + db.send_create_signal('main', ['ProjectNew']) - # Copy InventoryUpdate old to new. - new_ctype = self._get_content_type_for_model(orm, orm.InventoryUpdate) - for inventory_update in orm.InventoryUpdate.objects.order_by('pk'): - inventory_source = inventory_update.inventory_source - new_inventory_source = orm.InventorySourceNew.objects.get(old_pk=inventory_update.inventory_source_id) - d = self._get_dict_from_common_task_model(inventory_update) - d.update({ - 'polymorphic_ctype_id': new_ctype.pk, - 'source': inventory_source.source, - 'source_path': inventory_source.source_path, - 'source_vars': inventory_source.source_vars, - 'credential_id': inventory_source.credential_id, - 'source_regions': inventory_source.source_regions, - 'overwrite': inventory_source.overwrite, - 'overwrite_vars': inventory_source.overwrite_vars, - 'inventory_source_id': new_inventory_source.pk, - 'unified_job_template_id': new_inventory_source.pk, - 'license_error': inventory_update.license_error, - }) - new_inventory_update, created = orm.InventoryUpdateNew.objects.get_or_create(old_pk=inventory_update.pk, defaults=d) + # Adding model 'ProjectUpdateNew' + db.create_table(u'main_projectupdatenew', ( + (u'unifiedjob_ptr', self.gf('django.db.models.fields.related.OneToOneField')(to=orm['main.UnifiedJob'], unique=True, primary_key=True)), + ('local_path', self.gf('django.db.models.fields.CharField')(max_length=1024, blank=True)), + ('scm_type', self.gf('django.db.models.fields.CharField')(default='', max_length=8, blank=True)), + ('scm_url', self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True)), + ('scm_branch', self.gf('django.db.models.fields.CharField')(default='', max_length=256, blank=True)), + ('scm_clean', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('scm_delete_on_update', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('credential', self.gf('django.db.models.fields.related.ForeignKey')(related_name='projectupdatenews', on_delete=models.SET_NULL, default=None, to=orm['main.Credential'], blank=True, null=True)), + ('project', self.gf('django.db.models.fields.related.ForeignKey')(related_name='project_updates', to=orm['main.ProjectNew'])), + )) + db.send_create_signal('main', ['ProjectUpdateNew']) - # Update InventorySource last run. - for inventory_source in orm.InventorySource.objects.order_by('pk'): - new_inventory_source = orm.InventorySourceNew.objects.get(old_pk=inventory_source.pk) - if inventory_source.current_update: - new_inventory_source.current_job = orm.InventoryUpdateNew.objects.get(old_pk=inventory_source.current_update_id) - if inventory_source.last_update: - new_inventory_source.last_job = orm.InventoryUpdateNew.objects.get(old_pk=inventory_source.last_update_id) - new_inventory_source.last_job_failed = inventory_source.last_update_failed - new_inventory_source.last_job_run = inventory_source.last_updated - new_inventory_source.status = inventory_source.status - new_inventory_source.save() + # Adding model 'UnifiedJobTemplate' + db.create_table(u'main_unifiedjobtemplate', ( + (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('polymorphic_ctype', self.gf('django.db.models.fields.related.ForeignKey')(related_name='polymorphic_main.unifiedjobtemplate_set', null=True, to=orm['contenttypes.ContentType'])), + ('created', self.gf('django.db.models.fields.DateTimeField')(default=None)), + ('modified', self.gf('django.db.models.fields.DateTimeField')(default=None)), + ('description', self.gf('django.db.models.fields.TextField')(default='', blank=True)), + ('created_by', self.gf('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=orm['auth.User'])), + ('modified_by', self.gf('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=orm['auth.User'])), + ('active', self.gf('django.db.models.fields.BooleanField')(default=True)), + ('name', self.gf('django.db.models.fields.CharField')(max_length=512)), + ('old_pk', self.gf('django.db.models.fields.PositiveIntegerField')(default=None, null=True)), + ('current_job', self.gf('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'])), + ('last_job', self.gf('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', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('last_job_run', self.gf('django.db.models.fields.DateTimeField')(default=None, null=True)), + ('has_schedules', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('next_job_run', self.gf('django.db.models.fields.DateTimeField')(default=None, null=True)), + ('next_schedule', self.gf('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'])), + ('status', self.gf('django.db.models.fields.CharField')(default='ok', max_length=32)), + )) + db.send_create_signal('main', ['UnifiedJobTemplate']) - # Update Group inventory_sources. - for group in orm.Group.objects.order_by('pk'): - for inventory_source in group.inventory_sources.order_by('pk'): - new_inventory_source = orm.InventorySourceNew.objects.get(old_pk=inventory_source.pk) - group.new_inventory_sources.add(new_inventory_source) - - # Update Host inventory_sources. - for host in orm.Host.objects.order_by('pk'): - for inventory_source in host.inventory_sources.order_by('pk'): - new_inventory_source = orm.InventorySourceNew.objects.get(old_pk=inventory_source.pk) - host.new_inventory_sources.add(new_inventory_source) + # Adding unique constraint on 'UnifiedJobTemplate', fields ['polymorphic_ctype', 'name'] + db.create_unique(u'main_unifiedjobtemplate', ['polymorphic_ctype_id', 'name']) - # Copy JobTemplate old to new. - new_ctype = self._get_content_type_for_model(orm, orm.JobTemplate) - for job_template in orm.JobTemplate.objects.order_by('pk'): - d = self._get_dict_from_common_model(job_template) - d.update({ - 'polymorphic_ctype_id': new_ctype.pk, - 'job_type': job_template.job_type, - 'inventory_id': job_template.inventory_id, - 'playbook': job_template.playbook, - 'credential_id': job_template.credential_id, - 'cloud_credential_id': job_template.cloud_credential_id, - 'forks': job_template.forks, - 'limit': job_template.limit, - 'extra_vars': job_template.extra_vars, - 'job_tags': job_template.job_tags, - 'host_config_key': job_template.host_config_key, - }) - if job_template.project: - d['project_id'] = orm.ProjectNew.objects.get(old_pk=job_template.project_id).pk - new_job_template, created = orm.JobTemplateNew.objects.get_or_create(old_pk=job_template.pk, defaults=d) - # Copy Job old to new. - new_ctype = self._get_content_type_for_model(orm, orm.Job) - for job in orm.Job.objects.order_by('pk'): - d = self._get_dict_from_common_task_model(job) - d.update({ - 'polymorphic_ctype_id': new_ctype.pk, - 'job_type': job_template.job_type, - 'inventory_id': job_template.inventory_id, - 'playbook': job_template.playbook, - 'credential_id': job_template.credential_id, - 'cloud_credential_id': job_template.cloud_credential_id, - 'forks': job_template.forks, - 'limit': job_template.limit, - 'extra_vars': job_template.extra_vars, - 'job_tags': job_template.job_tags, - }) - if job.project: - d['project_id'] = orm.ProjectNew.objects.get(old_pk=job.project_id).pk - if job.job_template: - new_job_template = orm.JobTemplateNew.objects.get(old_pk=job.job_template_id) - d['job_template_id'] = new_job_template.pk - d['unified_job_template_id'] = new_job_template.pk - new_job, created = orm.JobNew.objects.get_or_create(old_pk=job.pk, defaults=d) + # Changing field 'Profile.created' + db.alter_column(u'main_profile', 'created', self.gf('django.db.models.fields.DateTimeField')()) - # Update JobTemplate last run. - for new_job_template in orm.JobTemplateNew.objects.order_by('pk'): - try: - new_last_job = new_job_template.jobs.order_by('-pk')[0] - new_job_template.last_job = new_last_job - new_job_template.last_job_failed = new_last_job.failed - new_job_template.last_job_run = new_last_job.finished - new_job_template.status = 'failed' if new_last_job.failed else 'successful' - except IndexError: - new_job_template.status = 'never updated' - new_inventory_source.save() + # Changing field 'Profile.modified' + db.alter_column(u'main_profile', 'modified', self.gf('django.db.models.fields.DateTimeField')()) + # Adding field 'ProjectUpdate.local_path' + db.add_column(u'main_projectupdate', 'local_path', + self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True), + keep_default=False) - # Update JobHostSummary job. - for job_host_summary in orm.JobHostSummary.objects.order_by('pk'): - new_job = orm.JobNew.objects.get(old_pk=job_host_summary.job_id) - job_host_summary.new_job = new_job - job_host_summary.save() + # Adding field 'ProjectUpdate.scm_type' + db.add_column(u'main_projectupdate', 'scm_type', + self.gf('django.db.models.fields.CharField')(default='', max_length=8, blank=True), + keep_default=False) - # Update JobEvent job. - for job_event in orm.JobEvent.objects.order_by('pk'): - new_job = orm.JobNew.objects.get(old_pk=job_event.job_id) - job_event.new_job = new_job - job_event.save() + # Adding field 'ProjectUpdate.scm_url' + db.add_column(u'main_projectupdate', 'scm_url', + self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True), + keep_default=False) - # Update Host last_job. - for host in orm.Host.objects.order_by('pk'): - if not host.last_job: - continue - new_job = orm.JobNew.objects.get(old_pk=host.last_job_id) - host.new_last_job = new_job - host.save() + # Adding field 'ProjectUpdate.scm_branch' + db.add_column(u'main_projectupdate', 'scm_branch', + self.gf('django.db.models.fields.CharField')(default='', max_length=256, blank=True), + keep_default=False) - # Update ActivityStream - for a_s in orm.ActivityStream.objects.order_by('pk'): - for project in a_s.project.all(): - new_project = orm.ProjectNew.objects.get(old_pk=project.pk) - a_s.new_project.add(new_project) - for project_update in a_s.project_update.all(): - new_project_update = orm.ProjectUpdateNew.objects.get(old_pk=project_update.pk) - a_s.new_project_update.add(new_project_update) - for inventory_source in a_s.inventory_source.all(): - new_inventory_source = orm.InventorySourceNew.objects.get(old_pk=inventory_source.pk) - a_s.new_inventory_source.add(new_inventory_source) - for inventory_update in a_s.inventory_update.all(): - new_inventory_update = orm.InventoryUpdateNew.objects.get(old_pk=inventory_update.pk) - a_s.new_inventory_update.add(new_inventory_update) - for job_template in a_s.job_template.all(): - new_job_template = orm.JobTemplateNew.objects.get(old_pk=job_template.pk) - a_s.new_job_template.add(new_job_template) - for job in a_s.job.all(): - new_job = orm.JobNew.objects.get(old_pk=job.pk) - a_s.new_job.add(new_job) + # Adding field 'ProjectUpdate.scm_clean' + db.add_column(u'main_projectupdate', 'scm_clean', + self.gf('django.db.models.fields.BooleanField')(default=False), + keep_default=False) + + # Adding field 'ProjectUpdate.scm_delete_on_update' + db.add_column(u'main_projectupdate', 'scm_delete_on_update', + self.gf('django.db.models.fields.BooleanField')(default=False), + keep_default=False) + + # Adding field 'ProjectUpdate.credential' + db.add_column(u'main_projectupdate', 'credential', + self.gf('django.db.models.fields.related.ForeignKey')(related_name='projectupdates', on_delete=models.SET_NULL, default=None, to=orm['main.Credential'], blank=True, null=True), + keep_default=False) + + + # Changing field 'ProjectUpdate.created' + db.alter_column(u'main_projectupdate', 'created', self.gf('django.db.models.fields.DateTimeField')()) + + # Changing field 'ProjectUpdate.modified' + db.alter_column(u'main_projectupdate', 'modified', self.gf('django.db.models.fields.DateTimeField')()) + # Adding M2M table for field new_inventory_sources on 'Group' + m2m_table_name = db.shorten_name(u'main_group_new_inventory_sources') + db.create_table(m2m_table_name, ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('group', models.ForeignKey(orm['main.group'], null=False)), + ('inventorysourcenew', models.ForeignKey(orm['main.inventorysourcenew'], null=False)) + )) + db.create_unique(m2m_table_name, ['group_id', 'inventorysourcenew_id']) + + + # Changing field 'Group.created' + db.alter_column(u'main_group', 'created', self.gf('django.db.models.fields.DateTimeField')()) + + # Changing field 'Group.modified' + db.alter_column(u'main_group', 'modified', self.gf('django.db.models.fields.DateTimeField')()) + + # Changing field 'Job.created' + db.alter_column(u'main_job', 'created', self.gf('django.db.models.fields.DateTimeField')()) + + # Changing field 'Job.modified' + db.alter_column(u'main_job', 'modified', self.gf('django.db.models.fields.DateTimeField')()) + + # Changing field 'Inventory.created' + db.alter_column(u'main_inventory', 'created', self.gf('django.db.models.fields.DateTimeField')()) + + # Changing field 'Inventory.modified' + db.alter_column(u'main_inventory', 'modified', self.gf('django.db.models.fields.DateTimeField')()) + # Adding field 'Host.new_last_job' + db.add_column(u'main_host', 'new_last_job', + self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name='hosts_as_last_job+', null=True, on_delete=models.SET_NULL, to=orm['main.JobNew']), + keep_default=False) + + # Adding M2M table for field new_inventory_sources on 'Host' + m2m_table_name = db.shorten_name(u'main_host_new_inventory_sources') + db.create_table(m2m_table_name, ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('host', models.ForeignKey(orm['main.host'], null=False)), + ('inventorysourcenew', models.ForeignKey(orm['main.inventorysourcenew'], null=False)) + )) + db.create_unique(m2m_table_name, ['host_id', 'inventorysourcenew_id']) + + + # Changing field 'Host.created' + db.alter_column(u'main_host', 'created', self.gf('django.db.models.fields.DateTimeField')()) + + # Changing field 'Host.modified' + db.alter_column(u'main_host', 'modified', self.gf('django.db.models.fields.DateTimeField')()) + # Adding field 'JobHostSummary.new_job' + db.add_column(u'main_jobhostsummary', 'new_job', + self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name='new_job_host_summaries', null=True, to=orm['main.JobNew']), + keep_default=False) + + + # Changing field 'JobHostSummary.created' + db.alter_column(u'main_jobhostsummary', 'created', self.gf('django.db.models.fields.DateTimeField')()) + + # Changing field 'JobHostSummary.modified' + db.alter_column(u'main_jobhostsummary', 'modified', self.gf('django.db.models.fields.DateTimeField')()) + + # Changing field 'JobHostSummary.job' + db.alter_column(u'main_jobhostsummary', 'job_id', self.gf('django.db.models.fields.related.ForeignKey')(null=True, to=orm['main.Job'])) + # Adding unique constraint on 'JobHostSummary', fields ['new_job', 'host'] + db.create_unique(u'main_jobhostsummary', ['new_job_id', 'host_id']) + + # Adding field 'InventoryUpdate.source' + db.add_column(u'main_inventoryupdate', 'source', + self.gf('django.db.models.fields.CharField')(default='', max_length=32, blank=True), + keep_default=False) + + # Adding field 'InventoryUpdate.source_path' + db.add_column(u'main_inventoryupdate', 'source_path', + self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True), + keep_default=False) + + # Adding field 'InventoryUpdate.source_vars' + db.add_column(u'main_inventoryupdate', 'source_vars', + self.gf('django.db.models.fields.TextField')(default='', blank=True), + keep_default=False) + + # Adding field 'InventoryUpdate.credential' + db.add_column(u'main_inventoryupdate', 'credential', + self.gf('django.db.models.fields.related.ForeignKey')(related_name='inventoryupdates', on_delete=models.SET_NULL, default=None, to=orm['main.Credential'], blank=True, null=True), + keep_default=False) + + # Adding field 'InventoryUpdate.source_regions' + db.add_column(u'main_inventoryupdate', 'source_regions', + self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True), + keep_default=False) + + # Adding field 'InventoryUpdate.overwrite' + db.add_column(u'main_inventoryupdate', 'overwrite', + self.gf('django.db.models.fields.BooleanField')(default=False), + keep_default=False) + + # Adding field 'InventoryUpdate.overwrite_vars' + db.add_column(u'main_inventoryupdate', 'overwrite_vars', + self.gf('django.db.models.fields.BooleanField')(default=False), + keep_default=False) + + + # Changing field 'InventoryUpdate.created' + db.alter_column(u'main_inventoryupdate', 'created', self.gf('django.db.models.fields.DateTimeField')()) + + # Changing field 'InventoryUpdate.modified' + db.alter_column(u'main_inventoryupdate', 'modified', self.gf('django.db.models.fields.DateTimeField')()) + # Adding field 'Credential.ssh_key_path' + db.add_column(u'main_credential', 'ssh_key_path', + self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True), + keep_default=False) + + # Adding field 'Credential.vault_password' + db.add_column(u'main_credential', 'vault_password', + self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True), + keep_default=False) + + + # Changing field 'Credential.created' + db.alter_column(u'main_credential', 'created', self.gf('django.db.models.fields.DateTimeField')()) + + # Changing field 'Credential.modified' + db.alter_column(u'main_credential', 'modified', self.gf('django.db.models.fields.DateTimeField')()) + + # Changing field 'JobTemplate.created' + db.alter_column(u'main_jobtemplate', 'created', self.gf('django.db.models.fields.DateTimeField')()) + + # Changing field 'JobTemplate.modified' + db.alter_column(u'main_jobtemplate', 'modified', self.gf('django.db.models.fields.DateTimeField')()) + # Adding M2M table for field schedule on 'ActivityStream' + m2m_table_name = db.shorten_name(u'main_activitystream_schedule') + db.create_table(m2m_table_name, ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('activitystream', models.ForeignKey(orm['main.activitystream'], null=False)), + ('schedule', models.ForeignKey(orm['main.schedule'], null=False)) + )) + db.create_unique(m2m_table_name, ['activitystream_id', 'schedule_id']) + + # Adding M2M table for field unified_job_template on 'ActivityStream' + m2m_table_name = db.shorten_name(u'main_activitystream_unified_job_template') + db.create_table(m2m_table_name, ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('activitystream', models.ForeignKey(orm['main.activitystream'], null=False)), + ('unifiedjobtemplate', models.ForeignKey(orm['main.unifiedjobtemplate'], null=False)) + )) + db.create_unique(m2m_table_name, ['activitystream_id', 'unifiedjobtemplate_id']) + + # Adding M2M table for field unified_job on 'ActivityStream' + m2m_table_name = db.shorten_name(u'main_activitystream_unified_job') + db.create_table(m2m_table_name, ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('activitystream', models.ForeignKey(orm['main.activitystream'], null=False)), + ('unifiedjob', models.ForeignKey(orm['main.unifiedjob'], null=False)) + )) + db.create_unique(m2m_table_name, ['activitystream_id', 'unifiedjob_id']) + + # Adding M2M table for field new_inventory_source on 'ActivityStream' + m2m_table_name = db.shorten_name(u'main_activitystream_new_inventory_source') + db.create_table(m2m_table_name, ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('activitystream', models.ForeignKey(orm['main.activitystream'], null=False)), + ('inventorysourcenew', models.ForeignKey(orm['main.inventorysourcenew'], null=False)) + )) + db.create_unique(m2m_table_name, ['activitystream_id', 'inventorysourcenew_id']) + + # Adding M2M table for field new_inventory_update on 'ActivityStream' + m2m_table_name = db.shorten_name(u'main_activitystream_new_inventory_update') + db.create_table(m2m_table_name, ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('activitystream', models.ForeignKey(orm['main.activitystream'], null=False)), + ('inventoryupdatenew', models.ForeignKey(orm['main.inventoryupdatenew'], null=False)) + )) + db.create_unique(m2m_table_name, ['activitystream_id', 'inventoryupdatenew_id']) + + # Adding M2M table for field new_project on 'ActivityStream' + m2m_table_name = db.shorten_name(u'main_activitystream_new_project') + db.create_table(m2m_table_name, ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('activitystream', models.ForeignKey(orm['main.activitystream'], null=False)), + ('projectnew', models.ForeignKey(orm['main.projectnew'], null=False)) + )) + db.create_unique(m2m_table_name, ['activitystream_id', 'projectnew_id']) + + # Adding M2M table for field new_project_update on 'ActivityStream' + m2m_table_name = db.shorten_name(u'main_activitystream_new_project_update') + db.create_table(m2m_table_name, ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('activitystream', models.ForeignKey(orm['main.activitystream'], null=False)), + ('projectupdatenew', models.ForeignKey(orm['main.projectupdatenew'], null=False)) + )) + db.create_unique(m2m_table_name, ['activitystream_id', 'projectupdatenew_id']) + + # Adding M2M table for field new_job_template on 'ActivityStream' + m2m_table_name = db.shorten_name(u'main_activitystream_new_job_template') + db.create_table(m2m_table_name, ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('activitystream', models.ForeignKey(orm['main.activitystream'], null=False)), + ('jobtemplatenew', models.ForeignKey(orm['main.jobtemplatenew'], null=False)) + )) + db.create_unique(m2m_table_name, ['activitystream_id', 'jobtemplatenew_id']) + + # Adding M2M table for field new_job on 'ActivityStream' + m2m_table_name = db.shorten_name(u'main_activitystream_new_job') + db.create_table(m2m_table_name, ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('activitystream', models.ForeignKey(orm['main.activitystream'], null=False)), + ('jobnew', models.ForeignKey(orm['main.jobnew'], null=False)) + )) + db.create_unique(m2m_table_name, ['activitystream_id', 'jobnew_id']) + + # Adding M2M table for field new_projects on 'Team' + m2m_table_name = db.shorten_name(u'main_team_new_projects') + db.create_table(m2m_table_name, ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('team', models.ForeignKey(orm['main.team'], null=False)), + ('projectnew', models.ForeignKey(orm['main.projectnew'], null=False)) + )) + db.create_unique(m2m_table_name, ['team_id', 'projectnew_id']) + + + # Changing field 'Team.created' + db.alter_column(u'main_team', 'created', self.gf('django.db.models.fields.DateTimeField')()) + + # Changing field 'Team.modified' + db.alter_column(u'main_team', 'modified', self.gf('django.db.models.fields.DateTimeField')()) + # Adding field 'Project.scm_update_cache_timeout' + db.add_column(u'main_project', 'scm_update_cache_timeout', + self.gf('django.db.models.fields.PositiveIntegerField')(default=0), + keep_default=False) + + + # Changing field 'Project.current_update' + db.alter_column(u'main_project', 'current_update_id', self.gf('django.db.models.fields.related.ForeignKey')(null=True, on_delete=models.SET_NULL, to=orm['main.ProjectUpdate'])) + + # Changing field 'Project.last_update' + db.alter_column(u'main_project', 'last_update_id', self.gf('django.db.models.fields.related.ForeignKey')(null=True, on_delete=models.SET_NULL, to=orm['main.ProjectUpdate'])) + + # Changing field 'Project.credential' + db.alter_column(u'main_project', 'credential_id', self.gf('django.db.models.fields.related.ForeignKey')(on_delete=models.SET_NULL, to=orm['main.Credential'], null=True)) + + # Changing field 'Project.created' + db.alter_column(u'main_project', 'created', self.gf('django.db.models.fields.DateTimeField')()) + + # Changing field 'Project.modified' + db.alter_column(u'main_project', 'modified', self.gf('django.db.models.fields.DateTimeField')()) + # Adding M2M table for field new_projects on 'Organization' + m2m_table_name = db.shorten_name(u'main_organization_new_projects') + db.create_table(m2m_table_name, ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('organization', models.ForeignKey(orm['main.organization'], null=False)), + ('projectnew', models.ForeignKey(orm['main.projectnew'], null=False)) + )) + db.create_unique(m2m_table_name, ['organization_id', 'projectnew_id']) + + + # Changing field 'Organization.created' + db.alter_column(u'main_organization', 'created', self.gf('django.db.models.fields.DateTimeField')()) + + # Changing field 'Organization.modified' + db.alter_column(u'main_organization', 'modified', self.gf('django.db.models.fields.DateTimeField')()) + # Adding field 'Permission.new_project' + db.add_column(u'main_permission', 'new_project', + self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='permissions', null=True, on_delete=models.SET_NULL, to=orm['main.ProjectNew']), + keep_default=False) + + + # Changing field 'Permission.created' + db.alter_column(u'main_permission', 'created', self.gf('django.db.models.fields.DateTimeField')()) + + # Changing field 'Permission.modified' + db.alter_column(u'main_permission', 'modified', self.gf('django.db.models.fields.DateTimeField')()) + # Deleting field 'InventorySource.update_interval' + db.delete_column(u'main_inventorysource', 'update_interval') + + # Adding field 'InventorySource.update_cache_timeout' + db.add_column(u'main_inventorysource', 'update_cache_timeout', + self.gf('django.db.models.fields.PositiveIntegerField')(default=0), + keep_default=False) + + + # Changing field 'InventorySource.current_update' + db.alter_column(u'main_inventorysource', 'current_update_id', self.gf('django.db.models.fields.related.ForeignKey')(null=True, on_delete=models.SET_NULL, to=orm['main.InventoryUpdate'])) + + # Changing field 'InventorySource.last_update' + db.alter_column(u'main_inventorysource', 'last_update_id', self.gf('django.db.models.fields.related.ForeignKey')(null=True, on_delete=models.SET_NULL, to=orm['main.InventoryUpdate'])) + + # Changing field 'InventorySource.credential' + db.alter_column(u'main_inventorysource', 'credential_id', self.gf('django.db.models.fields.related.ForeignKey')(on_delete=models.SET_NULL, to=orm['main.Credential'], null=True)) + + # Changing field 'InventorySource.created' + db.alter_column(u'main_inventorysource', 'created', self.gf('django.db.models.fields.DateTimeField')()) + + # Changing field 'InventorySource.modified' + db.alter_column(u'main_inventorysource', 'modified', self.gf('django.db.models.fields.DateTimeField')()) + # Adding field 'JobEvent.role' + db.add_column(u'main_jobevent', 'role', + self.gf('django.db.models.fields.CharField')(default='', max_length=1024), + keep_default=False) + + # Adding field 'JobEvent.new_job' + db.add_column(u'main_jobevent', 'new_job', + self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name='new_job_events', null=True, to=orm['main.JobNew']), + keep_default=False) + + + # Changing field 'JobEvent.job' + db.alter_column(u'main_jobevent', 'job_id', self.gf('django.db.models.fields.related.ForeignKey')(null=True, to=orm['main.Job'])) def backwards(self, orm): - "Write your backwards methods here." - - # FIXME: Would like to have this, but not required. - raise NotImplementedError() + # Removing unique constraint on 'JobHostSummary', fields ['new_job', 'host'] + db.delete_unique(u'main_jobhostsummary', ['new_job_id', 'host_id']) + + # Removing unique constraint on 'UnifiedJobTemplate', fields ['polymorphic_ctype', 'name'] + db.delete_unique(u'main_unifiedjobtemplate', ['polymorphic_ctype_id', 'name']) + + # Deleting model 'InventoryUpdateNew' + db.delete_table(u'main_inventoryupdatenew') + + # Deleting model 'JobNew' + db.delete_table(u'main_jobnew') + + # Deleting model 'UnifiedJob' + db.delete_table(u'main_unifiedjob') + + # Removing M2M table for field dependent_jobs on 'UnifiedJob' + db.delete_table(db.shorten_name(u'main_unifiedjob_dependent_jobs')) + + # Deleting model 'Schedule' + db.delete_table(u'main_schedule') + + # Deleting model 'InventorySourceNew' + db.delete_table(u'main_inventorysourcenew') + + # Deleting model 'JobTemplateNew' + db.delete_table('main_jobtemplatenew') + + # Deleting model 'ProjectNew' + db.delete_table(u'main_projectnew') + + # Deleting model 'ProjectUpdateNew' + db.delete_table(u'main_projectupdatenew') + + # Deleting model 'UnifiedJobTemplate' + db.delete_table(u'main_unifiedjobtemplate') + + + # Changing field 'Profile.created' + db.alter_column(u'main_profile', 'created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True)) + + # Changing field 'Profile.modified' + db.alter_column(u'main_profile', 'modified', self.gf('django.db.models.fields.DateTimeField')(auto_now=True)) + # Deleting field 'ProjectUpdate.local_path' + db.delete_column(u'main_projectupdate', 'local_path') + + # Deleting field 'ProjectUpdate.scm_type' + db.delete_column(u'main_projectupdate', 'scm_type') + + # Deleting field 'ProjectUpdate.scm_url' + db.delete_column(u'main_projectupdate', 'scm_url') + + # Deleting field 'ProjectUpdate.scm_branch' + db.delete_column(u'main_projectupdate', 'scm_branch') + + # Deleting field 'ProjectUpdate.scm_clean' + db.delete_column(u'main_projectupdate', 'scm_clean') + + # Deleting field 'ProjectUpdate.scm_delete_on_update' + db.delete_column(u'main_projectupdate', 'scm_delete_on_update') + + # Deleting field 'ProjectUpdate.credential' + db.delete_column(u'main_projectupdate', 'credential_id') + + + # Changing field 'ProjectUpdate.created' + db.alter_column(u'main_projectupdate', 'created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True)) + + # Changing field 'ProjectUpdate.modified' + db.alter_column(u'main_projectupdate', 'modified', self.gf('django.db.models.fields.DateTimeField')(auto_now=True)) + # Removing M2M table for field new_inventory_sources on 'Group' + db.delete_table(db.shorten_name(u'main_group_new_inventory_sources')) + + + # Changing field 'Group.created' + db.alter_column(u'main_group', 'created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True)) + + # Changing field 'Group.modified' + db.alter_column(u'main_group', 'modified', self.gf('django.db.models.fields.DateTimeField')(auto_now=True)) + + # Changing field 'Job.created' + db.alter_column(u'main_job', 'created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True)) + + # Changing field 'Job.modified' + db.alter_column(u'main_job', 'modified', self.gf('django.db.models.fields.DateTimeField')(auto_now=True)) + + # Changing field 'Inventory.created' + db.alter_column(u'main_inventory', 'created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True)) + + # Changing field 'Inventory.modified' + db.alter_column(u'main_inventory', 'modified', self.gf('django.db.models.fields.DateTimeField')(auto_now=True)) + # Deleting field 'Host.new_last_job' + db.delete_column(u'main_host', 'new_last_job_id') + + # Removing M2M table for field new_inventory_sources on 'Host' + db.delete_table(db.shorten_name(u'main_host_new_inventory_sources')) + + + # Changing field 'Host.created' + db.alter_column(u'main_host', 'created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True)) + + # Changing field 'Host.modified' + db.alter_column(u'main_host', 'modified', self.gf('django.db.models.fields.DateTimeField')(auto_now=True)) + # Deleting field 'JobHostSummary.new_job' + db.delete_column(u'main_jobhostsummary', 'new_job_id') + + + # Changing field 'JobHostSummary.created' + db.alter_column(u'main_jobhostsummary', 'created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True)) + + # Changing field 'JobHostSummary.modified' + db.alter_column(u'main_jobhostsummary', 'modified', self.gf('django.db.models.fields.DateTimeField')(auto_now=True)) + + # Changing field 'JobHostSummary.job' + db.alter_column(u'main_jobhostsummary', 'job_id', self.gf('django.db.models.fields.related.ForeignKey')(default=None, to=orm['main.Job'])) + # Deleting field 'InventoryUpdate.source' + db.delete_column(u'main_inventoryupdate', 'source') + + # Deleting field 'InventoryUpdate.source_path' + db.delete_column(u'main_inventoryupdate', 'source_path') + + # Deleting field 'InventoryUpdate.source_vars' + db.delete_column(u'main_inventoryupdate', 'source_vars') + + # Deleting field 'InventoryUpdate.credential' + db.delete_column(u'main_inventoryupdate', 'credential_id') + + # Deleting field 'InventoryUpdate.source_regions' + db.delete_column(u'main_inventoryupdate', 'source_regions') + + # Deleting field 'InventoryUpdate.overwrite' + db.delete_column(u'main_inventoryupdate', 'overwrite') + + # Deleting field 'InventoryUpdate.overwrite_vars' + db.delete_column(u'main_inventoryupdate', 'overwrite_vars') + + + # Changing field 'InventoryUpdate.created' + db.alter_column(u'main_inventoryupdate', 'created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True)) + + # Changing field 'InventoryUpdate.modified' + db.alter_column(u'main_inventoryupdate', 'modified', self.gf('django.db.models.fields.DateTimeField')(auto_now=True)) + # Deleting field 'Credential.ssh_key_path' + db.delete_column(u'main_credential', 'ssh_key_path') + + # Deleting field 'Credential.vault_password' + db.delete_column(u'main_credential', 'vault_password') + + + # Changing field 'Credential.created' + db.alter_column(u'main_credential', 'created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True)) + + # Changing field 'Credential.modified' + db.alter_column(u'main_credential', 'modified', self.gf('django.db.models.fields.DateTimeField')(auto_now=True)) + + # Changing field 'JobTemplate.created' + db.alter_column(u'main_jobtemplate', 'created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True)) + + # Changing field 'JobTemplate.modified' + db.alter_column(u'main_jobtemplate', 'modified', self.gf('django.db.models.fields.DateTimeField')(auto_now=True)) + # Removing M2M table for field schedule on 'ActivityStream' + db.delete_table(db.shorten_name(u'main_activitystream_schedule')) + + # Removing M2M table for field unified_job_template on 'ActivityStream' + db.delete_table(db.shorten_name(u'main_activitystream_unified_job_template')) + + # Removing M2M table for field unified_job on 'ActivityStream' + db.delete_table(db.shorten_name(u'main_activitystream_unified_job')) + + # Removing M2M table for field new_inventory_source on 'ActivityStream' + db.delete_table(db.shorten_name(u'main_activitystream_new_inventory_source')) + + # Removing M2M table for field new_inventory_update on 'ActivityStream' + db.delete_table(db.shorten_name(u'main_activitystream_new_inventory_update')) + + # Removing M2M table for field new_project on 'ActivityStream' + db.delete_table(db.shorten_name(u'main_activitystream_new_project')) + + # Removing M2M table for field new_project_update on 'ActivityStream' + db.delete_table(db.shorten_name(u'main_activitystream_new_project_update')) + + # Removing M2M table for field new_job_template on 'ActivityStream' + db.delete_table(db.shorten_name(u'main_activitystream_new_job_template')) + + # Removing M2M table for field new_job on 'ActivityStream' + db.delete_table(db.shorten_name(u'main_activitystream_new_job')) + + # Removing M2M table for field new_projects on 'Team' + db.delete_table(db.shorten_name(u'main_team_new_projects')) + + + # Changing field 'Team.created' + db.alter_column(u'main_team', 'created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True)) + + # Changing field 'Team.modified' + db.alter_column(u'main_team', 'modified', self.gf('django.db.models.fields.DateTimeField')(auto_now=True)) + # Deleting field 'Project.scm_update_cache_timeout' + db.delete_column(u'main_project', 'scm_update_cache_timeout') + + + # Changing field 'Project.current_update' + db.alter_column(u'main_project', 'current_update_id', self.gf('django.db.models.fields.related.ForeignKey')(null=True, to=orm['main.ProjectUpdate'])) + + # Changing field 'Project.last_update' + db.alter_column(u'main_project', 'last_update_id', self.gf('django.db.models.fields.related.ForeignKey')(null=True, to=orm['main.ProjectUpdate'])) + + # Changing field 'Project.credential' + db.alter_column(u'main_project', 'credential_id', self.gf('django.db.models.fields.related.ForeignKey')(null=True, to=orm['main.Credential'])) + + # Changing field 'Project.created' + db.alter_column(u'main_project', 'created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True)) + + # Changing field 'Project.modified' + db.alter_column(u'main_project', 'modified', self.gf('django.db.models.fields.DateTimeField')(auto_now=True)) + # Removing M2M table for field new_projects on 'Organization' + db.delete_table(db.shorten_name(u'main_organization_new_projects')) + + + # Changing field 'Organization.created' + db.alter_column(u'main_organization', 'created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True)) + + # Changing field 'Organization.modified' + db.alter_column(u'main_organization', 'modified', self.gf('django.db.models.fields.DateTimeField')(auto_now=True)) + # Deleting field 'Permission.new_project' + db.delete_column(u'main_permission', 'new_project_id') + + + # Changing field 'Permission.created' + db.alter_column(u'main_permission', 'created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True)) + + # Changing field 'Permission.modified' + db.alter_column(u'main_permission', 'modified', self.gf('django.db.models.fields.DateTimeField')(auto_now=True)) + # Adding field 'InventorySource.update_interval' + db.add_column(u'main_inventorysource', 'update_interval', + self.gf('django.db.models.fields.PositiveIntegerField')(default=0), + keep_default=False) + + # Deleting field 'InventorySource.update_cache_timeout' + db.delete_column(u'main_inventorysource', 'update_cache_timeout') + + + # Changing field 'InventorySource.current_update' + db.alter_column(u'main_inventorysource', 'current_update_id', self.gf('django.db.models.fields.related.ForeignKey')(null=True, to=orm['main.InventoryUpdate'])) + + # Changing field 'InventorySource.last_update' + db.alter_column(u'main_inventorysource', 'last_update_id', self.gf('django.db.models.fields.related.ForeignKey')(null=True, to=orm['main.InventoryUpdate'])) + + # Changing field 'InventorySource.credential' + db.alter_column(u'main_inventorysource', 'credential_id', self.gf('django.db.models.fields.related.ForeignKey')(null=True, to=orm['main.Credential'])) + + # Changing field 'InventorySource.created' + db.alter_column(u'main_inventorysource', 'created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True)) + + # Changing field 'InventorySource.modified' + db.alter_column(u'main_inventorysource', 'modified', self.gf('django.db.models.fields.DateTimeField')(auto_now=True)) + # Deleting field 'JobEvent.role' + db.delete_column(u'main_jobevent', 'role') + + # Deleting field 'JobEvent.new_job' + db.delete_column(u'main_jobevent', 'new_job_id') + + + # Changing field 'JobEvent.job' + db.alter_column(u'main_jobevent', 'job_id', self.gf('django.db.models.fields.related.ForeignKey')(default=None, to=orm['main.Job'])) models = { u'auth.group': { @@ -359,6 +874,7 @@ class Migration(DataMigration): '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']"}), @@ -388,12 +904,14 @@ class Migration(DataMigration): 'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}), 'password': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), 'ssh_key_data': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'ssh_key_path': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), 'ssh_key_unlock': ('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'}) + '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.group': { 'Meta': {'unique_together': "(('name', 'inventory'),)", 'object_name': 'Group'}, @@ -408,11 +926,11 @@ class Migration(DataMigration): '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', [], {'symmetrical': 'False', 'related_name': "'groups'", 'blank': 'True', 'to': "orm['main.InventorySource']"}), + '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'}), - 'new_inventory_sources': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'groups'", 'blank': 'True', 'to': "orm['main.InventorySourceNew']"}), + 'new_inventory_sources': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'groups'", 'symmetrical': 'False', 'to': "orm['main.InventorySourceNew']"}), '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'}), @@ -430,14 +948,14 @@ class Migration(DataMigration): 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', [], {'symmetrical': 'False', 'related_name': "'hosts'", 'blank': 'True', 'to': "orm['main.InventorySource']"}), - 'last_job': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'hosts_as_last_job+'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.Job']", 'blank': 'True', 'null': 'True'}), + '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'}), - 'new_inventory_sources': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'hosts'", 'blank': 'True', 'to': "orm['main.InventorySourceNew']"}), - 'new_last_job': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'hosts_as_last_job+'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.JobNew']", 'blank': 'True', 'null': 'True'}), + 'new_inventory_sources': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'hosts'", 'symmetrical': 'False', 'to': "orm['main.InventorySourceNew']"}), + 'new_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.JobNew']"}), 'variables': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}) }, 'main.inventory': { @@ -466,13 +984,13 @@ class Migration(DataMigration): '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\': \'inventorysource\', \'app_label\': \'main\'}(class)s_created+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), - 'credential': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'inventorysources'", 'null': 'True', 'blank': 'True', 'to': "orm['main.Credential']"}), - 'current_update': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'inventory_source_as_current_update+'", 'null': 'True', 'to': "orm['main.InventoryUpdate']"}), + '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'}), + 'current_update': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'inventory_source_as_current_update+'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.InventoryUpdate']"}), 'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), - 'group': ('awx.main.fields.AutoOneToOneField', [], {'related_name': "'inventory_source'", 'null': 'True', 'default': 'None', 'to': "orm['main.Group']", 'blank': 'True', 'unique': 'True'}), + 'group': ('awx.main.fields.AutoOneToOneField', [], {'default': 'None', 'related_name': "'inventory_source'", 'unique': 'True', 'null': 'True', 'to': "orm['main.Group']"}), u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'inventory': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'inventory_sources'", 'null': 'True', 'to': "orm['main.Inventory']"}), - 'last_update': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'inventory_source_as_last_update+'", 'null': 'True', 'to': "orm['main.InventoryUpdate']"}), + 'last_update': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'inventory_source_as_last_update+'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.InventoryUpdate']"}), 'last_update_failed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 'last_updated': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}), 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), @@ -489,8 +1007,8 @@ class Migration(DataMigration): }, 'main.inventorysourcenew': { 'Meta': {'object_name': 'InventorySourceNew', '_ormbases': ['main.UnifiedJobTemplate']}, - 'credential': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'inventorysourcenews'", 'null': 'True', 'blank': 'True', 'to': "orm['main.Credential']"}), - 'group': ('awx.main.fields.AutoOneToOneField', [], {'related_name': "'new_inventory_source'", 'null': 'True', 'default': 'None', 'to': "orm['main.Group']", 'blank': 'True', 'unique': 'True'}), + 'credential': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'inventorysourcenews'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.Credential']", 'blank': 'True', 'null': 'True'}), + 'group': ('awx.main.fields.AutoOneToOneField', [], {'default': 'None', 'related_name': "'new_inventory_source'", 'unique': 'True', 'null': 'True', 'to': "orm['main.Group']"}), 'inventory': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'new_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'}), @@ -510,7 +1028,7 @@ class Migration(DataMigration): '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\': \'inventoryupdate\', \'app_label\': \'main\'}(class)s_created+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), - 'credential': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'inventoryupdates'", 'null': 'True', 'blank': 'True', 'to': "orm['main.Credential']"}), + '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'}), 'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), 'failed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), @@ -529,11 +1047,12 @@ class Migration(DataMigration): '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_vars': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'start_args': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), 'status': ('django.db.models.fields.CharField', [], {'default': "'new'", 'max_length': '20'}) }, 'main.inventoryupdatenew': { 'Meta': {'object_name': 'InventoryUpdateNew', '_ormbases': ['main.UnifiedJob']}, - 'credential': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'inventoryupdatenews'", 'null': 'True', 'blank': 'True', 'to': "orm['main.Credential']"}), + 'credential': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'inventoryupdatenews'", '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.InventorySourceNew']"}), 'license_error': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 'overwrite': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), @@ -558,7 +1077,7 @@ class Migration(DataMigration): 'extra_vars': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), 'failed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 'forks': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0', 'blank': 'True'}), - 'hosts': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'jobs'", 'blank': 'True', 'through': "orm['main.JobHostSummary']", 'to': "orm['main.Host']"}), + 'hosts': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'jobs'", 'symmetrical': 'False', 'through': "orm['main.JobHostSummary']", 'to': "orm['main.Host']"}), u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'inventory': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobs'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Inventory']"}), 'job_args': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), @@ -575,6 +1094,7 @@ class Migration(DataMigration): 'project': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobs'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Project']"}), 'result_stdout_file': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), 'result_traceback': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'start_args': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), 'status': ('django.db.models.fields.CharField', [], {'default': "'new'", 'max_length': '20'}), 'verbosity': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0', 'blank': 'True'}) }, @@ -585,16 +1105,16 @@ class Migration(DataMigration): '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', [], {'related_name': "'job_events_as_primary_host'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.Host']", 'blank': 'True', 'null': 'True'}), - 'hosts': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'job_events'", 'blank': 'True', 'to': "orm['main.Host']"}), + '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']"}), + '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']"}), + 'job': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'job_events'", 'null': 'True', 'to': "orm['main.Job']"}), 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), 'new_job': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'new_job_events'", 'null': 'True', 'to': "orm['main.JobNew']"}), - 'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'children'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.JobEvent']", 'blank': 'True', 'null': 'True'}), - 'play': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), - 'role': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), - 'task': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}) + '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'), ('new_job', 'host')]", 'object_name': 'JobHostSummary'}, @@ -605,7 +1125,7 @@ class Migration(DataMigration): 'failures': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), 'host': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'job_host_summaries'", 'to': "orm['main.Host']"}), 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']"}), + 'job': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'job_host_summaries'", 'null': 'True', 'to': "orm['main.Job']"}), 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), 'new_job': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'new_job_host_summaries'", 'null': 'True', 'to': "orm['main.JobNew']"}), 'ok': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), @@ -618,7 +1138,7 @@ class Migration(DataMigration): 'credential': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobnews'", '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'}), 'forks': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0', 'blank': 'True'}), - 'hosts': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'jobnews'", 'blank': 'True', 'through': "orm['main.JobHostSummary']", 'to': "orm['main.Host']"}), + 'hosts': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'jobnews'", 'symmetrical': 'False', 'through': "orm['main.JobHostSummary']", 'to': "orm['main.Host']"}), 'inventory': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobnews'", '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.JobTemplateNew']", 'blank': 'True', 'null': 'True'}), @@ -713,11 +1233,11 @@ class Migration(DataMigration): '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\': \'project\', \'app_label\': \'main\'}(class)s_created+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), - 'credential': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'projects'", 'null': 'True', 'blank': 'True', 'to': "orm['main.Credential']"}), - 'current_update': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'project_as_current_update+'", 'null': 'True', 'to': "orm['main.ProjectUpdate']"}), + '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'}), + 'current_update': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'project_as_current_update+'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.ProjectUpdate']"}), 'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'last_update': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'project_as_last_update+'", 'null': 'True', 'to': "orm['main.ProjectUpdate']"}), + 'last_update': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'project_as_last_update+'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.ProjectUpdate']"}), 'last_update_failed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 'last_updated': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}), 'local_path': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'blank': 'True'}), @@ -736,7 +1256,7 @@ class Migration(DataMigration): }, 'main.projectnew': { 'Meta': {'object_name': 'ProjectNew', '_ormbases': ['main.UnifiedJobTemplate']}, - 'credential': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'projectnews'", 'null': 'True', 'blank': 'True', 'to': "orm['main.Credential']"}), + 'credential': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'projectnews'", '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'}), @@ -756,7 +1276,7 @@ class Migration(DataMigration): '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\': \'projectupdate\', \'app_label\': \'main\'}(class)s_created+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), - 'credential': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'projectupdates'", 'null': 'True', 'blank': 'True', 'to': "orm['main.Credential']"}), + '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'}), 'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), 'failed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), @@ -774,11 +1294,12 @@ class Migration(DataMigration): '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'}), + 'start_args': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), 'status': ('django.db.models.fields.CharField', [], {'default': "'new'", 'max_length': '20'}) }, 'main.projectupdatenew': { 'Meta': {'object_name': 'ProjectUpdateNew', '_ormbases': ['main.UnifiedJob']}, - 'credential': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'projectupdatenews'", 'null': 'True', 'blank': 'True', 'to': "orm['main.Credential']"}), + 'credential': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'projectupdatenews'", '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.ProjectNew']"}), 'scm_branch': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '256', 'blank': 'True'}), @@ -796,12 +1317,14 @@ class Migration(DataMigration): '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', [], {}), + 'enabled': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'job_template': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'schedules'", 'to': "orm['main.UnifiedJobTemplate']"}), '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'}), - 'rrule': ('django.db.models.fields.CharField', [], {'max_length': '255'}) + '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.team': { 'Meta': {'unique_together': "[('organization', 'name')]", 'object_name': 'Team'}, @@ -825,7 +1348,7 @@ class Migration(DataMigration): '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']"}), - 'depends_on': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'depends_on_rel_+'", 'to': "orm['main.UnifiedJob']"}), + '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'}), @@ -837,33 +1360,35 @@ class Migration(DataMigration): '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'}), + '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', 'to': "orm['main.UnifiedJobTemplate']"}) + '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', 'to': "orm['main.UnifiedJob']"}), + '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', 'to': "orm['main.UnifiedJob']"}), + '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'}) @@ -883,5 +1408,4 @@ class Migration(DataMigration): } } - complete_apps = ['main'] - symmetrical = True + complete_apps = ['main'] \ No newline at end of file diff --git a/awx/main/migrations/0036_v148_changes.py b/awx/main/migrations/0036_v148_changes.py index 2947003bea..efaa270b8d 100644 --- a/awx/main/migrations/0036_v148_changes.py +++ b/awx/main/migrations/0036_v148_changes.py @@ -1,380 +1,308 @@ # -*- coding: utf-8 -*- from south.utils import datetime_utils as datetime from south.db import db -from south.v2 import SchemaMigration +from south.v2 import DataMigration from django.db import models +from django.utils.encoding import smart_text +class Migration(DataMigration): -class Migration(SchemaMigration): + def _get_dict_from_primordial_model(self, instance): + return { + 'description': instance.description, + 'created': instance.created, + 'modified': instance.modified, + 'created_by': instance.created_by, + 'modified_by': instance.modified_by, + 'active': instance.active, + 'old_pk': instance.pk, + } + + def _get_dict_from_common_model(self, instance): + d = self._get_dict_from_primordial_model(instance) + if hasattr(instance, 'name'): + d['name'] = instance.name + elif getattr(instance, 'inventory', None) and getattr(instance, 'group', None): + d['name'] = ': '.join([instance.inventory.name, instance.group.name]) + elif getattr(instance, 'inventory', None): + d['name'] = u'%s-%s' % (instance.inventory.name, instance.pk) + else: + d['name'] = u'%s-%s' % (instance._meta.verbose_name, instance.pk) + return d + + def _get_dict_from_common_task_model(self, instance): + d = self._get_dict_from_primordial_model(instance) + td = instance.modified - instance.created + elapsed = (td.microseconds + (td.seconds + td.days * 24 * 3600) * 10**6) / (10**6 * 1.0) + d.update({ + 'launch_type': getattr(instance, 'launch_type', 'manual'), + 'cancel_flag': instance.cancel_flag, + 'status': instance.status, + 'failed': instance.failed, + 'started': instance.created, + 'finished': instance.modified, + 'elapsed': elapsed, + 'job_args': instance.job_args, + 'job_env': instance.job_env, + 'result_stdout_text': instance._result_stdout, + 'result_stdout_file': instance.result_stdout_file, + 'result_traceback': instance.result_traceback, + 'celery_task_id': instance.celery_task_id, + }) + return d + + def _get_content_type_for_model(self, orm, model): + app_label = model._meta.app_label + model_name = model._meta.module_name + defaults = {'name': smart_text(model._meta.verbose_name_raw)} + content_type, created = orm['contenttypes.ContentType'].objects.get_or_create(app_label=app_label, model=model_name, defaults=defaults) + return content_type def forwards(self, orm): - # Removing unique constraint on 'JobHostSummary', fields ['job', 'host'] - db.delete_unique(u'main_jobhostsummary', ['job_id', 'host_id']) + "Write your forwards methods here." - # Deleting model 'JobTemplate' - db.delete_table(u'main_jobtemplate') + # Copy Project old to new. + new_ctype = self._get_content_type_for_model(orm, orm.Project) + for project in orm.Project.objects.order_by('pk'): + d = self._get_dict_from_common_model(project) + d.update({ + 'polymorphic_ctype_id': new_ctype.pk, + 'local_path': project.local_path, + 'scm_type': project.scm_type, + 'scm_url': project.scm_url, + 'scm_branch': project.scm_branch, + 'scm_clean': project.scm_clean, + 'scm_delete_on_update': project.scm_delete_on_update, + 'credential_id': project.credential_id, + 'scm_delete_on_next_update': project.scm_delete_on_next_update, + 'scm_update_on_launch': project.scm_update_on_launch, + }) + new_project, created = orm.ProjectNew.objects.get_or_create(old_pk=project.pk, defaults=d) - # Deleting model 'InventorySource' - db.delete_table(u'main_inventorysource') + # Copy ProjectUpdate old to new. + new_ctype = self._get_content_type_for_model(orm, orm.ProjectUpdate) + for project_update in orm.ProjectUpdate.objects.order_by('pk'): + project = project_update.project + new_project = orm.ProjectNew.objects.get(old_pk=project_update.project_id) + d = self._get_dict_from_common_task_model(project_update) + d.update({ + 'polymorphic_ctype_id': new_ctype.pk, + 'project_id': new_project.pk, + 'name': new_project.name, + 'unified_job_template_id': new_project.pk, + 'local_path': project.local_path, + 'scm_type': project.scm_type, + 'scm_url': project.scm_url, + 'scm_branch': project.scm_branch, + 'scm_clean': project.scm_clean, + 'scm_delete_on_update': project.scm_delete_on_update, + 'credential_id': project.credential_id, + }) + new_project_update, created = orm.ProjectUpdateNew.objects.get_or_create(old_pk=project_update.pk, defaults=d) - # Deleting model 'Project' - db.delete_table(u'main_project') + # Update Project last run. + for project in orm.Project.objects.order_by('pk'): + new_project = orm.ProjectNew.objects.get(old_pk=project.pk) + if project.current_update: + new_project.current_job = orm.ProjectUpdateNew.objects.get(old_pk=project.current_update_id) + if project.last_update: + new_project.last_job = orm.ProjectUpdateNew.objects.get(old_pk=project.last_update_id) + new_project.last_job_failed = project.last_update_failed + new_project.last_job_run = project.last_updated + new_project.status = project.status + new_project.save() - # Deleting model 'ProjectUpdate' - db.delete_table(u'main_projectupdate') + # Update Organization projects. + for organization in orm.Organization.objects.order_by('pk'): + for project in organization.projects.order_by('pk'): + new_project = orm.ProjectNew.objects.get(old_pk=project.pk) + organization.new_projects.add(new_project) - # Deleting model 'InventoryUpdate' - db.delete_table(u'main_inventoryupdate') + # Update Team projects. + for team in orm.Team.objects.order_by('pk'): + for project in team.projects.order_by('pk'): + new_project = orm.ProjectNew.objects.get(old_pk=project.pk) + team.new_projects.add(new_project) - # Deleting model 'Job' - db.delete_table(u'main_job') + # Update Permission project. + for permission in orm.Permission.objects.order_by('pk'): + if not permission.project_id: + continue + new_project = orm.ProjectNew.objects.get(old_pk=permission.project_id) + permission.new_project = new_project + permission.save() - # Deleting field 'Host.last_job' - db.delete_column(u'main_host', 'last_job_id') + # Copy InventorySource old to new. + new_ctype = self._get_content_type_for_model(orm, orm.InventorySource) + for inventory_source in orm.InventorySource.objects.order_by('pk'): + d = self._get_dict_from_common_model(inventory_source) + d.update({ + 'polymorphic_ctype_id': new_ctype.pk, + 'source': inventory_source.source, + 'source_path': inventory_source.source_path, + 'source_vars': inventory_source.source_vars, + 'credential_id': inventory_source.credential_id, + 'source_regions': inventory_source.source_regions, + 'overwrite': inventory_source.overwrite, + 'overwrite_vars': inventory_source.overwrite_vars, + 'update_on_launch': inventory_source.update_on_launch, + 'inventory_id': inventory_source.inventory_id, + 'group_id': inventory_source.group_id, + }) + new_inventory_source, created = orm.InventorySourceNew.objects.get_or_create(old_pk=inventory_source.pk, defaults=d) - # Removing M2M table for field inventory_sources on 'Host' - db.delete_table(db.shorten_name(u'main_host_inventory_sources')) + # Copy InventoryUpdate old to new. + new_ctype = self._get_content_type_for_model(orm, orm.InventoryUpdate) + for inventory_update in orm.InventoryUpdate.objects.order_by('pk'): + inventory_source = inventory_update.inventory_source + new_inventory_source = orm.InventorySourceNew.objects.get(old_pk=inventory_update.inventory_source_id) + d = self._get_dict_from_common_task_model(inventory_update) + d.update({ + 'polymorphic_ctype_id': new_ctype.pk, + 'name': new_inventory_source.name, + 'source': inventory_source.source, + 'source_path': inventory_source.source_path, + 'source_vars': inventory_source.source_vars, + 'credential_id': inventory_source.credential_id, + 'source_regions': inventory_source.source_regions, + 'overwrite': inventory_source.overwrite, + 'overwrite_vars': inventory_source.overwrite_vars, + 'inventory_source_id': new_inventory_source.pk, + 'unified_job_template_id': new_inventory_source.pk, + 'license_error': inventory_update.license_error, + }) + new_inventory_update, created = orm.InventoryUpdateNew.objects.get_or_create(old_pk=inventory_update.pk, defaults=d) - # Removing M2M table for field projects on 'Organization' - db.delete_table(db.shorten_name(u'main_organization_projects')) + # Update InventorySource last run. + for inventory_source in orm.InventorySource.objects.order_by('pk'): + new_inventory_source = orm.InventorySourceNew.objects.get(old_pk=inventory_source.pk) + if inventory_source.current_update: + new_inventory_source.current_job = orm.InventoryUpdateNew.objects.get(old_pk=inventory_source.current_update_id) + if inventory_source.last_update: + new_inventory_source.last_job = orm.InventoryUpdateNew.objects.get(old_pk=inventory_source.last_update_id) + new_inventory_source.last_job_failed = inventory_source.last_update_failed + new_inventory_source.last_job_run = inventory_source.last_updated + new_inventory_source.status = inventory_source.status + new_inventory_source.save() - # Removing M2M table for field projects on 'Team' - db.delete_table(db.shorten_name(u'main_team_projects')) + # Update Group inventory_sources. + for group in orm.Group.objects.order_by('pk'): + for inventory_source in group.inventory_sources.order_by('pk'): + new_inventory_source = orm.InventorySourceNew.objects.get(old_pk=inventory_source.pk) + group.new_inventory_sources.add(new_inventory_source) + + # Update Host inventory_sources. + for host in orm.Host.objects.order_by('pk'): + for inventory_source in host.inventory_sources.order_by('pk'): + new_inventory_source = orm.InventorySourceNew.objects.get(old_pk=inventory_source.pk) + host.new_inventory_sources.add(new_inventory_source) - # Deleting field 'Permission.project' - db.delete_column(u'main_permission', 'project_id') + # Copy JobTemplate old to new. + new_ctype = self._get_content_type_for_model(orm, orm.JobTemplate) + for job_template in orm.JobTemplate.objects.order_by('pk'): + d = self._get_dict_from_common_model(job_template) + d.update({ + 'polymorphic_ctype_id': new_ctype.pk, + 'job_type': job_template.job_type, + 'inventory_id': job_template.inventory_id, + 'playbook': job_template.playbook, + 'credential_id': job_template.credential_id, + 'cloud_credential_id': job_template.cloud_credential_id, + 'forks': job_template.forks, + 'limit': job_template.limit, + 'extra_vars': job_template.extra_vars, + 'job_tags': job_template.job_tags, + 'host_config_key': job_template.host_config_key, + }) + if job_template.project: + d['project_id'] = orm.ProjectNew.objects.get(old_pk=job_template.project_id).pk + new_job_template, created = orm.JobTemplateNew.objects.get_or_create(old_pk=job_template.pk, defaults=d) - # Deleting field 'JobHostSummary.job' - db.delete_column(u'main_jobhostsummary', 'job_id') + # Copy Job old to new. + new_ctype = self._get_content_type_for_model(orm, orm.Job) + for job in orm.Job.objects.order_by('pk'): + d = self._get_dict_from_common_task_model(job) + d.update({ + 'polymorphic_ctype_id': new_ctype.pk, + 'job_type': job_template.job_type, + 'inventory_id': job_template.inventory_id, + 'playbook': job_template.playbook, + 'credential_id': job_template.credential_id, + 'cloud_credential_id': job_template.cloud_credential_id, + 'forks': job_template.forks, + 'limit': job_template.limit, + 'extra_vars': job_template.extra_vars, + 'job_tags': job_template.job_tags, + }) + if job.project: + d['project_id'] = orm.ProjectNew.objects.get(old_pk=job.project_id).pk + if job.job_template: + new_job_template = orm.JobTemplateNew.objects.get(old_pk=job.job_template_id) + d['job_template_id'] = new_job_template.pk + d['unified_job_template_id'] = new_job_template.pk + d['name'] = new_job_template.name + else: + d['name'] = 'ad-hoc job' + new_job, created = orm.JobNew.objects.get_or_create(old_pk=job.pk, defaults=d) - # Changing field 'JobHostSummary.new_job' - db.alter_column(u'main_jobhostsummary', 'new_job_id', self.gf('django.db.models.fields.related.ForeignKey')(default=None, to=orm['main.JobNew'])) + # Update JobTemplate last run. + for new_job_template in orm.JobTemplateNew.objects.order_by('pk'): + try: + new_last_job = new_job_template.jobs.order_by('-pk')[0] + new_job_template.last_job = new_last_job + new_job_template.last_job_failed = new_last_job.failed + new_job_template.last_job_run = new_last_job.finished + new_job_template.status = 'failed' if new_last_job.failed else 'successful' + except IndexError: + new_job_template.status = 'never updated' + new_inventory_source.save() - # Removing M2M table for field inventory_sources on 'Group' - db.delete_table(db.shorten_name(u'main_group_inventory_sources')) + # Update JobHostSummary job. + for job_host_summary in orm.JobHostSummary.objects.order_by('pk'): + new_job = orm.JobNew.objects.get(old_pk=job_host_summary.job_id) + job_host_summary.new_job = new_job + job_host_summary.save() - # Deleting field 'JobEvent.job' - db.delete_column(u'main_jobevent', 'job_id') + # Update JobEvent job. + for job_event in orm.JobEvent.objects.order_by('pk'): + new_job = orm.JobNew.objects.get(old_pk=job_event.job_id) + job_event.new_job = new_job + job_event.save() - # Changing field 'JobEvent.new_job' - db.alter_column(u'main_jobevent', 'new_job_id', self.gf('django.db.models.fields.related.ForeignKey')(default=None, to=orm['main.JobNew'])) - - # Removing M2M table for field job_template on 'ActivityStream' - db.delete_table(db.shorten_name(u'main_activitystream_job_template')) - - # Removing M2M table for field inventory_update on 'ActivityStream' - db.delete_table(db.shorten_name(u'main_activitystream_inventory_update')) - - # Removing M2M table for field job on 'ActivityStream' - db.delete_table(db.shorten_name(u'main_activitystream_job')) - - # Removing M2M table for field project_update on 'ActivityStream' - db.delete_table(db.shorten_name(u'main_activitystream_project_update')) - - # Removing M2M table for field inventory_source on 'ActivityStream' - db.delete_table(db.shorten_name(u'main_activitystream_inventory_source')) - - # Removing M2M table for field project on 'ActivityStream' - db.delete_table(db.shorten_name(u'main_activitystream_project')) + # Update Host last_job. + for host in orm.Host.objects.order_by('pk'): + if not host.last_job: + continue + new_job = orm.JobNew.objects.get(old_pk=host.last_job_id) + host.new_last_job = new_job + host.save() + # Update ActivityStream + for a_s in orm.ActivityStream.objects.order_by('pk'): + for project in a_s.project.all(): + new_project = orm.ProjectNew.objects.get(old_pk=project.pk) + a_s.new_project.add(new_project) + for project_update in a_s.project_update.all(): + new_project_update = orm.ProjectUpdateNew.objects.get(old_pk=project_update.pk) + a_s.new_project_update.add(new_project_update) + for inventory_source in a_s.inventory_source.all(): + new_inventory_source = orm.InventorySourceNew.objects.get(old_pk=inventory_source.pk) + a_s.new_inventory_source.add(new_inventory_source) + for inventory_update in a_s.inventory_update.all(): + new_inventory_update = orm.InventoryUpdateNew.objects.get(old_pk=inventory_update.pk) + a_s.new_inventory_update.add(new_inventory_update) + for job_template in a_s.job_template.all(): + new_job_template = orm.JobTemplateNew.objects.get(old_pk=job_template.pk) + a_s.new_job_template.add(new_job_template) + for job in a_s.job.all(): + new_job = orm.JobNew.objects.get(old_pk=job.pk) + a_s.new_job.add(new_job) def backwards(self, orm): - # Adding model 'JobTemplate' - db.create_table(u'main_jobtemplate', ( - ('credential', self.gf('django.db.models.fields.related.ForeignKey')(related_name='jobtemplates', on_delete=models.SET_NULL, default=None, to=orm['main.Credential'], blank=True, null=True)), - ('modified_by', self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name="{'class': 'jobtemplate', 'app_label': 'main'}(class)s_modified+", null=True, on_delete=models.SET_NULL, to=orm['auth.User'])), - ('description', self.gf('django.db.models.fields.TextField')(default='', blank=True)), - ('created', self.gf('django.db.models.fields.DateTimeField')(default=None)), - ('extra_vars', self.gf('django.db.models.fields.TextField')(default='', blank=True)), - ('verbosity', self.gf('django.db.models.fields.PositiveIntegerField')(default=0, blank=True)), - ('job_tags', self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True)), - ('job_type', self.gf('django.db.models.fields.CharField')(max_length=64)), - ('modified', self.gf('django.db.models.fields.DateTimeField')(default=None)), - ('created_by', self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name="{'class': 'jobtemplate', 'app_label': 'main'}(class)s_created+", null=True, on_delete=models.SET_NULL, to=orm['auth.User'])), - (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), - ('project', self.gf('django.db.models.fields.related.ForeignKey')(related_name='job_templates', null=True, on_delete=models.SET_NULL, to=orm['main.Project'])), - ('host_config_key', self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True)), - ('limit', self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True)), - ('inventory', self.gf('django.db.models.fields.related.ForeignKey')(related_name='jobtemplates', null=True, on_delete=models.SET_NULL, to=orm['main.Inventory'])), - ('active', self.gf('django.db.models.fields.BooleanField')(default=True)), - ('forks', self.gf('django.db.models.fields.PositiveIntegerField')(default=0, blank=True)), - ('playbook', self.gf('django.db.models.fields.CharField')(default='', max_length=1024)), - ('cloud_credential', self.gf('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)), - ('name', self.gf('django.db.models.fields.CharField')(max_length=512, unique=True)), - )) - db.send_create_signal('main', ['JobTemplate']) - - # Adding model 'InventorySource' - db.create_table(u'main_inventorysource', ( - ('last_updated', self.gf('django.db.models.fields.DateTimeField')(default=None, null=True)), - ('source_regions', self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True)), - ('current_update', self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name='inventory_source_as_current_update+', null=True, to=orm['main.InventoryUpdate'])), - (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), - ('overwrite', self.gf('django.db.models.fields.BooleanField')(default=False)), - ('source_vars', self.gf('django.db.models.fields.TextField')(default='', blank=True)), - ('group', self.gf('awx.main.fields.AutoOneToOneField')(related_name='inventory_source', null=True, default=None, to=orm['main.Group'], blank=True, unique=True)), - ('last_update_failed', self.gf('django.db.models.fields.BooleanField')(default=False)), - ('created_by', self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name="{'class': 'inventorysource', 'app_label': 'main'}(class)s_created+", null=True, on_delete=models.SET_NULL, to=orm['auth.User'])), - ('last_update', self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name='inventory_source_as_last_update+', null=True, to=orm['main.InventoryUpdate'])), - ('source', self.gf('django.db.models.fields.CharField')(default='', max_length=32, blank=True)), - ('inventory', self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name='inventory_sources', null=True, to=orm['main.Inventory'])), - ('update_cache_timeout', self.gf('django.db.models.fields.PositiveIntegerField')(default=0)), - ('status', self.gf('django.db.models.fields.CharField')(default='none', max_length=32)), - ('credential', self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name='inventorysources', null=True, to=orm['main.Credential'], blank=True)), - ('description', self.gf('django.db.models.fields.TextField')(default='', blank=True)), - ('overwrite_vars', self.gf('django.db.models.fields.BooleanField')(default=False)), - ('active', self.gf('django.db.models.fields.BooleanField')(default=True)), - ('modified_by', self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name="{'class': 'inventorysource', 'app_label': 'main'}(class)s_modified+", null=True, on_delete=models.SET_NULL, to=orm['auth.User'])), - ('update_on_launch', self.gf('django.db.models.fields.BooleanField')(default=False)), - ('created', self.gf('django.db.models.fields.DateTimeField')(default=None)), - ('source_path', self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True)), - ('modified', self.gf('django.db.models.fields.DateTimeField')(default=None)), - )) - db.send_create_signal('main', ['InventorySource']) - - # Adding model 'Project' - db.create_table(u'main_project', ( - ('scm_branch', self.gf('django.db.models.fields.CharField')(default='', max_length=256, blank=True)), - ('scm_update_cache_timeout', self.gf('django.db.models.fields.PositiveIntegerField')(default=0)), - ('scm_clean', self.gf('django.db.models.fields.BooleanField')(default=False)), - ('scm_delete_on_update', self.gf('django.db.models.fields.BooleanField')(default=False)), - ('current_update', self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name='project_as_current_update+', null=True, to=orm['main.ProjectUpdate'])), - ('last_updated', self.gf('django.db.models.fields.DateTimeField')(default=None, null=True)), - (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), - ('modified_by', self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name="{'class': 'project', 'app_label': 'main'}(class)s_modified+", null=True, on_delete=models.SET_NULL, to=orm['auth.User'])), - ('last_update_failed', self.gf('django.db.models.fields.BooleanField')(default=False)), - ('created_by', self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name="{'class': 'project', 'app_label': 'main'}(class)s_created+", null=True, on_delete=models.SET_NULL, to=orm['auth.User'])), - ('last_update', self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name='project_as_last_update+', null=True, to=orm['main.ProjectUpdate'])), - ('local_path', self.gf('django.db.models.fields.CharField')(max_length=1024, blank=True)), - ('scm_delete_on_next_update', self.gf('django.db.models.fields.BooleanField')(default=False)), - ('status', self.gf('django.db.models.fields.CharField')(default='ok', max_length=32, null=True)), - ('credential', self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name='projects', null=True, to=orm['main.Credential'], blank=True)), - ('description', self.gf('django.db.models.fields.TextField')(default='', blank=True)), - ('scm_type', self.gf('django.db.models.fields.CharField')(default='', max_length=8, blank=True)), - ('scm_update_on_launch', self.gf('django.db.models.fields.BooleanField')(default=False)), - ('active', self.gf('django.db.models.fields.BooleanField')(default=True)), - ('name', self.gf('django.db.models.fields.CharField')(max_length=512, unique=True)), - ('created', self.gf('django.db.models.fields.DateTimeField')(default=None)), - ('modified', self.gf('django.db.models.fields.DateTimeField')(default=None)), - ('scm_url', self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True)), - )) - db.send_create_signal('main', ['Project']) - - # Adding model 'ProjectUpdate' - db.create_table(u'main_projectupdate', ( - ('cancel_flag', self.gf('django.db.models.fields.BooleanField')(default=False)), - ('scm_branch', self.gf('django.db.models.fields.CharField')(default='', max_length=256, blank=True)), - ('scm_clean', self.gf('django.db.models.fields.BooleanField')(default=False)), - ('scm_delete_on_update', self.gf('django.db.models.fields.BooleanField')(default=False)), - ('celery_task_id', self.gf('django.db.models.fields.CharField')(default='', max_length=100, blank=True)), - (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), - ('modified_by', self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name="{'class': 'projectupdate', 'app_label': 'main'}(class)s_modified+", null=True, on_delete=models.SET_NULL, to=orm['auth.User'])), - ('job_cwd', self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True)), - ('created_by', self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name="{'class': 'projectupdate', 'app_label': 'main'}(class)s_created+", null=True, on_delete=models.SET_NULL, to=orm['auth.User'])), - ('failed', self.gf('django.db.models.fields.BooleanField')(default=False)), - ('local_path', self.gf('django.db.models.fields.CharField')(max_length=1024, blank=True)), - ('status', self.gf('django.db.models.fields.CharField')(default='new', max_length=20)), - ('credential', self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name='projectupdates', null=True, to=orm['main.Credential'], blank=True)), - ('description', self.gf('django.db.models.fields.TextField')(default='', blank=True)), - ('result_traceback', self.gf('django.db.models.fields.TextField')(default='', blank=True)), - ('scm_type', self.gf('django.db.models.fields.CharField')(default='', max_length=8, blank=True)), - ('job_env', self.gf('jsonfield.fields.JSONField')(default={}, blank=True)), - ('active', self.gf('django.db.models.fields.BooleanField')(default=True)), - ('result_stdout_file', self.gf('django.db.models.fields.TextField')(default='', blank=True)), - ('created', self.gf('django.db.models.fields.DateTimeField')(default=None)), - ('job_args', self.gf('django.db.models.fields.TextField')(default='', blank=True)), - ('modified', self.gf('django.db.models.fields.DateTimeField')(default=None)), - ('scm_url', self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True)), - ('project', self.gf('django.db.models.fields.related.ForeignKey')(related_name='project_updates', to=orm['main.Project'])), - ('_result_stdout', self.gf('django.db.models.fields.TextField')(default='', db_column='result_stdout', blank=True)), - )) - db.send_create_signal('main', ['ProjectUpdate']) - - # Adding model 'InventoryUpdate' - db.create_table(u'main_inventoryupdate', ( - ('cancel_flag', self.gf('django.db.models.fields.BooleanField')(default=False)), - ('source_regions', self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True)), - ('license_error', self.gf('django.db.models.fields.BooleanField')(default=False)), - ('celery_task_id', self.gf('django.db.models.fields.CharField')(default='', max_length=100, blank=True)), - (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), - ('overwrite', self.gf('django.db.models.fields.BooleanField')(default=False)), - ('source_vars', self.gf('django.db.models.fields.TextField')(default='', blank=True)), - ('modified_by', self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name="{'class': 'inventoryupdate', 'app_label': 'main'}(class)s_modified+", null=True, on_delete=models.SET_NULL, to=orm['auth.User'])), - ('job_cwd', self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True)), - ('source', self.gf('django.db.models.fields.CharField')(default='', max_length=32, blank=True)), - ('created_by', self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name="{'class': 'inventoryupdate', 'app_label': 'main'}(class)s_created+", null=True, on_delete=models.SET_NULL, to=orm['auth.User'])), - ('failed', self.gf('django.db.models.fields.BooleanField')(default=False)), - ('status', self.gf('django.db.models.fields.CharField')(default='new', max_length=20)), - ('credential', self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name='inventoryupdates', null=True, to=orm['main.Credential'], blank=True)), - ('description', self.gf('django.db.models.fields.TextField')(default='', blank=True)), - ('overwrite_vars', self.gf('django.db.models.fields.BooleanField')(default=False)), - ('result_traceback', self.gf('django.db.models.fields.TextField')(default='', blank=True)), - ('job_env', self.gf('jsonfield.fields.JSONField')(default={}, blank=True)), - ('active', self.gf('django.db.models.fields.BooleanField')(default=True)), - ('result_stdout_file', self.gf('django.db.models.fields.TextField')(default='', blank=True)), - ('inventory_source', self.gf('django.db.models.fields.related.ForeignKey')(related_name='inventory_updates', to=orm['main.InventorySource'])), - ('created', self.gf('django.db.models.fields.DateTimeField')(default=None)), - ('job_args', self.gf('django.db.models.fields.TextField')(default='', blank=True)), - ('source_path', self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True)), - ('modified', self.gf('django.db.models.fields.DateTimeField')(default=None)), - ('_result_stdout', self.gf('django.db.models.fields.TextField')(default='', db_column='result_stdout', blank=True)), - )) - db.send_create_signal('main', ['InventoryUpdate']) - - # Adding model 'Job' - db.create_table(u'main_job', ( - ('cancel_flag', self.gf('django.db.models.fields.BooleanField')(default=False)), - ('credential', self.gf('django.db.models.fields.related.ForeignKey')(related_name='jobs', on_delete=models.SET_NULL, default=None, to=orm['main.Credential'], blank=True, null=True)), - ('description', self.gf('django.db.models.fields.TextField')(default='', blank=True)), - ('result_traceback', self.gf('django.db.models.fields.TextField')(default='', blank=True)), - ('job_type', self.gf('django.db.models.fields.CharField')(max_length=64)), - ('job_tags', self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True)), - ('celery_task_id', self.gf('django.db.models.fields.CharField')(default='', max_length=100, blank=True)), - ('playbook', self.gf('django.db.models.fields.CharField')(default='', max_length=1024)), - ('job_env', self.gf('jsonfield.fields.JSONField')(default={}, blank=True)), - ('active', self.gf('django.db.models.fields.BooleanField')(default=True)), - ('result_stdout_file', self.gf('django.db.models.fields.TextField')(default='', blank=True)), - (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), - ('status', self.gf('django.db.models.fields.CharField')(default='new', max_length=20)), - ('modified_by', self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name="{'class': 'job', 'app_label': 'main'}(class)s_modified+", null=True, on_delete=models.SET_NULL, to=orm['auth.User'])), - ('job_cwd', self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True)), - ('job_template', self.gf('django.db.models.fields.related.ForeignKey')(related_name='jobs', on_delete=models.SET_NULL, default=None, to=orm['main.JobTemplate'], blank=True, null=True)), - ('created', self.gf('django.db.models.fields.DateTimeField')(default=None)), - ('extra_vars', self.gf('django.db.models.fields.TextField')(default='', blank=True)), - ('verbosity', self.gf('django.db.models.fields.PositiveIntegerField')(default=0, blank=True)), - ('job_args', self.gf('django.db.models.fields.TextField')(default='', blank=True)), - ('modified', self.gf('django.db.models.fields.DateTimeField')(default=None)), - ('created_by', self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name="{'class': 'job', 'app_label': 'main'}(class)s_created+", null=True, on_delete=models.SET_NULL, to=orm['auth.User'])), - ('project', self.gf('django.db.models.fields.related.ForeignKey')(related_name='jobs', null=True, on_delete=models.SET_NULL, to=orm['main.Project'])), - ('failed', self.gf('django.db.models.fields.BooleanField')(default=False)), - ('inventory', self.gf('django.db.models.fields.related.ForeignKey')(related_name='jobs', null=True, on_delete=models.SET_NULL, to=orm['main.Inventory'])), - ('_result_stdout', self.gf('django.db.models.fields.TextField')(default='', db_column='result_stdout', blank=True)), - ('limit', self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True)), - ('forks', self.gf('django.db.models.fields.PositiveIntegerField')(default=0, blank=True)), - ('cloud_credential', self.gf('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)), - ('launch_type', self.gf('django.db.models.fields.CharField')(default='manual', max_length=20)), - )) - db.send_create_signal('main', ['Job']) - - # Adding field 'Host.last_job' - db.add_column(u'main_host', 'last_job', - self.gf('django.db.models.fields.related.ForeignKey')(related_name='hosts_as_last_job+', on_delete=models.SET_NULL, default=None, to=orm['main.Job'], blank=True, null=True), - keep_default=False) - - # Adding M2M table for field inventory_sources on 'Host' - m2m_table_name = db.shorten_name(u'main_host_inventory_sources') - db.create_table(m2m_table_name, ( - ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), - ('host', models.ForeignKey(orm['main.host'], null=False)), - ('inventorysource', models.ForeignKey(orm['main.inventorysource'], null=False)) - )) - db.create_unique(m2m_table_name, ['host_id', 'inventorysource_id']) - - # Adding M2M table for field projects on 'Organization' - m2m_table_name = db.shorten_name(u'main_organization_projects') - db.create_table(m2m_table_name, ( - ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), - ('organization', models.ForeignKey(orm['main.organization'], null=False)), - ('project', models.ForeignKey(orm['main.project'], null=False)) - )) - db.create_unique(m2m_table_name, ['organization_id', 'project_id']) - - # Adding M2M table for field projects on 'Team' - m2m_table_name = db.shorten_name(u'main_team_projects') - db.create_table(m2m_table_name, ( - ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), - ('team', models.ForeignKey(orm['main.team'], null=False)), - ('project', models.ForeignKey(orm['main.project'], null=False)) - )) - db.create_unique(m2m_table_name, ['team_id', 'project_id']) - - # Adding field 'Permission.project' - db.add_column(u'main_permission', 'project', - self.gf('django.db.models.fields.related.ForeignKey')(related_name='permissions', null=True, to=orm['main.Project'], on_delete=models.SET_NULL, blank=True), - keep_default=False) - - # Adding field 'JobHostSummary.job' - db.add_column(u'main_jobhostsummary', 'job', - self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name='job_host_summaries', to=orm['main.Job']), - keep_default=False) - - - # Changing field 'JobHostSummary.new_job' - db.alter_column(u'main_jobhostsummary', 'new_job_id', self.gf('django.db.models.fields.related.ForeignKey')(null=True, to=orm['main.JobNew'])) - # Adding unique constraint on 'JobHostSummary', fields ['job', 'host'] - db.create_unique(u'main_jobhostsummary', ['job_id', 'host_id']) - - # Adding M2M table for field inventory_sources on 'Group' - m2m_table_name = db.shorten_name(u'main_group_inventory_sources') - db.create_table(m2m_table_name, ( - ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), - ('group', models.ForeignKey(orm['main.group'], null=False)), - ('inventorysource', models.ForeignKey(orm['main.inventorysource'], null=False)) - )) - db.create_unique(m2m_table_name, ['group_id', 'inventorysource_id']) - - # Adding field 'JobEvent.job' - db.add_column(u'main_jobevent', 'job', - self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name='job_events', to=orm['main.Job']), - keep_default=False) - - - # Changing field 'JobEvent.new_job' - db.alter_column(u'main_jobevent', 'new_job_id', self.gf('django.db.models.fields.related.ForeignKey')(null=True, to=orm['main.JobNew'])) - # Adding M2M table for field job_template on 'ActivityStream' - m2m_table_name = db.shorten_name(u'main_activitystream_job_template') - db.create_table(m2m_table_name, ( - ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), - ('activitystream', models.ForeignKey(orm['main.activitystream'], null=False)), - ('jobtemplate', models.ForeignKey(orm['main.jobtemplate'], null=False)) - )) - db.create_unique(m2m_table_name, ['activitystream_id', 'jobtemplate_id']) - - # Adding M2M table for field inventory_update on 'ActivityStream' - m2m_table_name = db.shorten_name(u'main_activitystream_inventory_update') - db.create_table(m2m_table_name, ( - ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), - ('activitystream', models.ForeignKey(orm['main.activitystream'], null=False)), - ('inventoryupdate', models.ForeignKey(orm['main.inventoryupdate'], null=False)) - )) - db.create_unique(m2m_table_name, ['activitystream_id', 'inventoryupdate_id']) - - # Adding M2M table for field job on 'ActivityStream' - m2m_table_name = db.shorten_name(u'main_activitystream_job') - db.create_table(m2m_table_name, ( - ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), - ('activitystream', models.ForeignKey(orm['main.activitystream'], null=False)), - ('job', models.ForeignKey(orm['main.job'], null=False)) - )) - db.create_unique(m2m_table_name, ['activitystream_id', 'job_id']) - - # Adding M2M table for field project_update on 'ActivityStream' - m2m_table_name = db.shorten_name(u'main_activitystream_project_update') - db.create_table(m2m_table_name, ( - ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), - ('activitystream', models.ForeignKey(orm['main.activitystream'], null=False)), - ('projectupdate', models.ForeignKey(orm['main.projectupdate'], null=False)) - )) - db.create_unique(m2m_table_name, ['activitystream_id', 'projectupdate_id']) - - # Adding M2M table for field inventory_source on 'ActivityStream' - m2m_table_name = db.shorten_name(u'main_activitystream_inventory_source') - db.create_table(m2m_table_name, ( - ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), - ('activitystream', models.ForeignKey(orm['main.activitystream'], null=False)), - ('inventorysource', models.ForeignKey(orm['main.inventorysource'], null=False)) - )) - db.create_unique(m2m_table_name, ['activitystream_id', 'inventorysource_id']) - - # Adding M2M table for field project on 'ActivityStream' - m2m_table_name = db.shorten_name(u'main_activitystream_project') - db.create_table(m2m_table_name, ( - ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), - ('activitystream', models.ForeignKey(orm['main.activitystream'], null=False)), - ('project', models.ForeignKey(orm['main.project'], null=False)) - )) - db.create_unique(m2m_table_name, ['activitystream_id', 'project_id']) + "Write your backwards methods here." + # FIXME: Would like to have this, but not required. + raise NotImplementedError() models = { u'auth.group': { @@ -422,6 +350,10 @@ class Migration(SchemaMigration): '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'}), 'new_inventory_source': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.InventorySourceNew']", 'symmetrical': 'False', 'blank': 'True'}), 'new_inventory_update': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.InventoryUpdateNew']", 'symmetrical': 'False', 'blank': 'True'}), 'new_job': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.JobNew']", 'symmetrical': 'False', 'blank': 'True'}), @@ -434,6 +366,9 @@ class Migration(SchemaMigration): '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']"}), @@ -463,12 +398,14 @@ class Migration(SchemaMigration): 'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}), 'password': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), 'ssh_key_data': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'ssh_key_path': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), 'ssh_key_unlock': ('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'}) + '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.group': { 'Meta': {'unique_together': "(('name', 'inventory'),)", 'object_name': 'Group'}, @@ -483,10 +420,11 @@ class Migration(SchemaMigration): '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'}), - 'new_inventory_sources': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'groups'", 'blank': 'True', 'to': "orm['main.InventorySourceNew']"}), + 'new_inventory_sources': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'groups'", 'symmetrical': 'False', 'to': "orm['main.InventorySourceNew']"}), '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'}), @@ -504,12 +442,14 @@ class Migration(SchemaMigration): 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'}), - 'new_inventory_sources': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'hosts'", 'blank': 'True', 'to': "orm['main.InventorySourceNew']"}), - 'new_last_job': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'hosts_as_last_job+'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.JobNew']", 'blank': 'True', 'null': 'True'}), + 'new_inventory_sources': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'hosts'", 'symmetrical': 'False', 'to': "orm['main.InventorySourceNew']"}), + 'new_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.JobNew']"}), 'variables': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}) }, 'main.inventory': { @@ -533,10 +473,36 @@ class Migration(SchemaMigration): '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'}, + '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\': \'inventorysource\', \'app_label\': \'main\'}(class)s_created+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), + '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'}), + 'current_update': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'inventory_source_as_current_update+'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.InventoryUpdate']"}), + 'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'group': ('awx.main.fields.AutoOneToOneField', [], {'default': 'None', 'related_name': "'inventory_source'", 'unique': 'True', 'null': 'True', 'to': "orm['main.Group']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'inventory': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'inventory_sources'", 'null': 'True', 'to': "orm['main.Inventory']"}), + 'last_update': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'inventory_source_as_last_update+'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.InventoryUpdate']"}), + 'last_update_failed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_updated': ('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\': \'inventorysource\', \'app_label\': \'main\'}(class)s_modified+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), + '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_vars': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'status': ('django.db.models.fields.CharField', [], {'default': "'none'", 'max_length': '32'}), + 'update_cache_timeout': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'update_on_launch': ('django.db.models.fields.BooleanField', [], {'default': 'False'}) + }, 'main.inventorysourcenew': { 'Meta': {'object_name': 'InventorySourceNew', '_ormbases': ['main.UnifiedJobTemplate']}, - 'credential': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'inventorysourcenews'", 'null': 'True', 'blank': 'True', 'to': "orm['main.Credential']"}), - 'group': ('awx.main.fields.AutoOneToOneField', [], {'related_name': "'new_inventory_source'", 'null': 'True', 'default': 'None', 'to': "orm['main.Group']", 'blank': 'True', 'unique': 'True'}), + 'credential': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'inventorysourcenews'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.Credential']", 'blank': 'True', 'null': 'True'}), + 'group': ('awx.main.fields.AutoOneToOneField', [], {'default': 'None', 'related_name': "'new_inventory_source'", 'unique': 'True', 'null': 'True', 'to': "orm['main.Group']"}), 'inventory': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'new_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'}), @@ -548,9 +514,39 @@ class Migration(SchemaMigration): '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'}, + '_result_stdout': ('django.db.models.fields.TextField', [], {'default': "''", 'db_column': "'result_stdout'", 'blank': 'True'}), + '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\': \'inventoryupdate\', \'app_label\': \'main\'}(class)s_created+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), + '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'}), + 'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'failed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'inventory_source': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'inventory_updates'", 'to': "orm['main.InventorySource']"}), + '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'}), + 'license_error': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'modified_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'inventoryupdate\', \'app_label\': \'main\'}(class)s_modified+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), + 'overwrite': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'overwrite_vars': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'result_stdout_file': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'result_traceback': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + '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_vars': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'start_args': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'status': ('django.db.models.fields.CharField', [], {'default': "'new'", 'max_length': '20'}) + }, 'main.inventoryupdatenew': { 'Meta': {'object_name': 'InventoryUpdateNew', '_ormbases': ['main.UnifiedJob']}, - 'credential': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'inventoryupdatenews'", 'null': 'True', 'blank': 'True', 'to': "orm['main.Credential']"}), + 'credential': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'inventoryupdatenews'", '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.InventorySourceNew']"}), 'license_error': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 'overwrite': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), @@ -561,6 +557,41 @@ class Migration(SchemaMigration): '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': {'object_name': 'Job'}, + '_result_stdout': ('django.db.models.fields.TextField', [], {'default': "''", 'db_column': "'result_stdout'", 'blank': 'True'}), + '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'}), + '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'}), + 'created': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'created_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'job\', \'app_label\': \'main\'}(class)s_created+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), + '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'}), + 'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'extra_vars': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'failed': ('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']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'inventory': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobs'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Inventory']"}), + '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_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'}), + 'launch_type': ('django.db.models.fields.CharField', [], {'default': "'manual'", 'max_length': '20'}), + 'limit': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), + 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'modified_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'job\', \'app_label\': \'main\'}(class)s_modified+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), + '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']"}), + 'result_stdout_file': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'result_traceback': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'start_args': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'status': ('django.db.models.fields.CharField', [], {'default': "'new'", 'max_length': '20'}), + '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'}), @@ -568,18 +599,19 @@ class Migration(SchemaMigration): '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', [], {'related_name': "'job_events_as_primary_host'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.Host']", 'blank': 'True', 'null': 'True'}), - 'hosts': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'job_events'", 'blank': 'True', 'to': "orm['main.Host']"}), + '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']"}), + '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', [], {'default': 'None', 'related_name': "'job_events'", 'null': 'True', 'to': "orm['main.Job']"}), 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), - 'new_job': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'new_job_events'", 'to': "orm['main.JobNew']"}), - 'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'children'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.JobEvent']", 'blank': 'True', 'null': 'True'}), - 'play': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), - 'role': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), - 'task': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}) + 'new_job': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'new_job_events'", 'null': 'True', 'to': "orm['main.JobNew']"}), + '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': "[('new_job', 'host')]", 'object_name': 'JobHostSummary'}, + 'Meta': {'ordering': "('-pk',)", 'unique_together': "[('job', 'host'), ('new_job', 'host')]", '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'}), @@ -587,8 +619,9 @@ class Migration(SchemaMigration): 'failures': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), 'host': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'job_host_summaries'", 'to': "orm['main.Host']"}), u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'job': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'job_host_summaries'", 'null': 'True', 'to': "orm['main.Job']"}), 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), - 'new_job': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'new_job_host_summaries'", 'to': "orm['main.JobNew']"}), + 'new_job': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'new_job_host_summaries'", 'null': 'True', 'to': "orm['main.JobNew']"}), 'ok': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), 'processed': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), 'skipped': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}) @@ -599,7 +632,7 @@ class Migration(SchemaMigration): 'credential': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobnews'", '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'}), 'forks': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0', 'blank': 'True'}), - 'hosts': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'jobnews'", 'blank': 'True', 'through': "orm['main.JobHostSummary']", 'to': "orm['main.Host']"}), + 'hosts': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'jobnews'", 'symmetrical': 'False', 'through': "orm['main.JobHostSummary']", 'to': "orm['main.Host']"}), 'inventory': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobnews'", '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.JobTemplateNew']", 'blank': 'True', 'null': 'True'}), @@ -610,6 +643,29 @@ class Migration(SchemaMigration): 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.jobtemplate': { + 'Meta': {'object_name': 'JobTemplate'}, + 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + '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'}), + 'created': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'created_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'jobtemplate\', \'app_label\': \'main\'}(class)s_created+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), + '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'}), + 'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'extra_vars': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'forks': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0', 'blank': 'True'}), + 'host_config_key': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': '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'}), + 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'modified_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'jobtemplate\', \'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'}), + 'playbook': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024'}), + 'project': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'job_templates'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Project']"}), + 'verbosity': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0', 'blank': 'True'}) + }, 'main.jobtemplatenew': { 'Meta': {'object_name': 'JobTemplateNew', '_ormbases': ['main.UnifiedJobTemplate']}, 'cloud_credential': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobtemplatenews_as_cloud_credential+'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.Credential']", 'blank': 'True', 'null': 'True'}), @@ -638,6 +694,7 @@ class Migration(SchemaMigration): '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'}), 'new_projects': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'organizations'", 'blank': 'True', 'to': "orm['main.ProjectNew']"}), + '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': { @@ -653,6 +710,7 @@ class Migration(SchemaMigration): 'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}), 'new_project': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'permissions'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.ProjectNew']"}), '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']"}) }, @@ -664,9 +722,35 @@ class Migration(SchemaMigration): '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': {'object_name': 'Project'}, + '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\': \'project\', \'app_label\': \'main\'}(class)s_created+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), + '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'}), + 'current_update': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'project_as_current_update+'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.ProjectUpdate']"}), + 'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_update': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'project_as_last_update+'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.ProjectUpdate']"}), + 'last_update_failed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_updated': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True'}), + 'local_path': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'blank': 'True'}), + 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'modified_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'project\', \'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'}), + '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'}), + 'status': ('django.db.models.fields.CharField', [], {'default': "'ok'", 'max_length': '32', 'null': 'True'}) + }, 'main.projectnew': { 'Meta': {'object_name': 'ProjectNew', '_ormbases': ['main.UnifiedJobTemplate']}, - 'credential': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'projectnews'", 'null': 'True', 'blank': 'True', 'to': "orm['main.Credential']"}), + 'credential': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'projectnews'", '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'}), @@ -678,9 +762,38 @@ class Migration(SchemaMigration): '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'}, + '_result_stdout': ('django.db.models.fields.TextField', [], {'default': "''", 'db_column': "'result_stdout'", 'blank': 'True'}), + '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\': \'projectupdate\', \'app_label\': \'main\'}(class)s_created+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), + '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'}), + 'description': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'failed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 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'}), + 'local_path': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'blank': 'True'}), + 'modified': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}), + 'modified_by': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': '"{\'class\': \'projectupdate\', \'app_label\': \'main\'}(class)s_modified+"', 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': u"orm['auth.User']"}), + 'project': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'project_updates'", 'to': "orm['main.Project']"}), + 'result_stdout_file': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'result_traceback': ('django.db.models.fields.TextField', [], {'default': "''", '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_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'}), + 'start_args': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'status': ('django.db.models.fields.CharField', [], {'default': "'new'", 'max_length': '20'}) + }, 'main.projectupdatenew': { 'Meta': {'object_name': 'ProjectUpdateNew', '_ormbases': ['main.UnifiedJob']}, - 'credential': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'projectupdatenews'", 'null': 'True', 'blank': 'True', 'to': "orm['main.Credential']"}), + 'credential': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'projectupdatenews'", '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.ProjectNew']"}), 'scm_branch': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '256', 'blank': 'True'}), @@ -698,12 +811,14 @@ class Migration(SchemaMigration): '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', [], {}), + 'enabled': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'job_template': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'schedules'", 'to': "orm['main.UnifiedJobTemplate']"}), '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'}), - 'rrule': ('django.db.models.fields.CharField', [], {'max_length': '255'}) + '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.team': { 'Meta': {'unique_together': "[('organization', 'name')]", 'object_name': 'Team'}, @@ -717,6 +832,7 @@ class Migration(SchemaMigration): 'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}), 'new_projects': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'teams'", 'blank': 'True', 'to': "orm['main.ProjectNew']"}), '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': { @@ -726,7 +842,7 @@ class Migration(SchemaMigration): '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']"}), - 'depends_on': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'depends_on_rel_+'", 'to': "orm['main.UnifiedJob']"}), + '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'}), @@ -738,33 +854,35 @@ class Migration(SchemaMigration): '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'}), + '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', 'to': "orm['main.UnifiedJobTemplate']"}) + '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', 'to': "orm['main.UnifiedJob']"}), + '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', 'to': "orm['main.UnifiedJob']"}), + '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'}) @@ -784,4 +902,5 @@ class Migration(SchemaMigration): } } - complete_apps = ['main'] \ No newline at end of file + complete_apps = ['main'] + symmetrical = True diff --git a/awx/main/migrations/0037_v148_changes.py b/awx/main/migrations/0037_v148_changes.py index fb8a90b956..587f471430 100644 --- a/awx/main/migrations/0037_v148_changes.py +++ b/awx/main/migrations/0037_v148_changes.py @@ -6,81 +6,375 @@ from django.db import models class Migration(SchemaMigration): - ''' - Rename tables/columns to be consistent with model/field names. - ''' def forwards(self, orm): - db.rename_table(u'main_projectnew', 'main_project') - db.rename_table(u'main_projectupdatenew', 'main_projectupdate') - db.rename_table(u'main_inventorysourcenew', 'main_inventorysource') - db.rename_table(u'main_inventoryupdatenew', 'main_inventoryupdate') - db.rename_table(u'main_jobtemplatenew', 'main_jobtemplate') - db.rename_table(u'main_jobnew', 'main_job') + # Removing unique constraint on 'JobHostSummary', fields ['job', 'host'] + db.delete_unique(u'main_jobhostsummary', ['job_id', 'host_id']) - db.rename_table(db.shorten_name(u'main_team_new_projects'), db.shorten_name(u'main_team_projects')) - db.rename_column(db.shorten_name(u'main_team_projects'), 'projectnew_id', 'project_id') - db.rename_table(db.shorten_name(u'main_organization_new_projects'), db.shorten_name(u'main_organization_projects')) - db.rename_column(db.shorten_name(u'main_organization_projects'), 'projectnew_id', 'project_id') - db.rename_column(u'main_permission', 'new_project_id', 'project_id') + # Deleting model 'JobTemplate' + db.delete_table(u'main_jobtemplate') - db.rename_column(u'main_host', 'new_last_job_id', 'last_job_id') - db.rename_table(db.shorten_name(u'main_host_new_inventory_sources'), db.shorten_name(u'main_host_inventory_sources')) - db.rename_column(db.shorten_name(u'main_host_inventory_sources'), 'inventorysourcenew_id', 'inventorysource_id') - db.rename_table(db.shorten_name(u'main_group_new_inventory_sources'), db.shorten_name(u'main_group_inventory_sources')) - db.rename_column(db.shorten_name(u'main_group_inventory_sources'), 'inventorysourcenew_id', 'inventorysource_id') - - db.rename_column(u'main_jobhostsummary', 'new_job_id', 'job_id') - db.rename_column(u'main_jobevent', 'new_job_id', 'job_id') + # Deleting model 'InventorySource' + db.delete_table(u'main_inventorysource') + + # Deleting model 'Project' + db.delete_table(u'main_project') + + # Deleting model 'ProjectUpdate' + db.delete_table(u'main_projectupdate') + + # Deleting model 'InventoryUpdate' + db.delete_table(u'main_inventoryupdate') + + # Deleting model 'Job' + db.delete_table(u'main_job') + + # Deleting field 'Host.last_job' + db.delete_column(u'main_host', 'last_job_id') + + # Removing M2M table for field inventory_sources on 'Host' + db.delete_table(db.shorten_name(u'main_host_inventory_sources')) + + # Removing M2M table for field projects on 'Organization' + db.delete_table(db.shorten_name(u'main_organization_projects')) + + # Removing M2M table for field projects on 'Team' + db.delete_table(db.shorten_name(u'main_team_projects')) + + # Deleting field 'Permission.project' + db.delete_column(u'main_permission', 'project_id') + + # Deleting field 'JobHostSummary.job' + db.delete_column(u'main_jobhostsummary', 'job_id') + + # Changing field 'JobHostSummary.new_job' + db.alter_column(u'main_jobhostsummary', 'new_job_id', self.gf('django.db.models.fields.related.ForeignKey')(default=None, to=orm['main.JobNew'])) + + # Removing M2M table for field inventory_sources on 'Group' + db.delete_table(db.shorten_name(u'main_group_inventory_sources')) + + # Deleting field 'JobEvent.job' + db.delete_column(u'main_jobevent', 'job_id') + + # Changing field 'JobEvent.new_job' + db.alter_column(u'main_jobevent', 'new_job_id', self.gf('django.db.models.fields.related.ForeignKey')(default=None, to=orm['main.JobNew'])) + # Removing M2M table for field inventory_update on 'ActivityStream' + db.delete_table(db.shorten_name(u'main_activitystream_inventory_update')) + + # Removing M2M table for field project_update on 'ActivityStream' + db.delete_table(db.shorten_name(u'main_activitystream_project_update')) + + # Removing M2M table for field inventory_source on 'ActivityStream' + db.delete_table(db.shorten_name(u'main_activitystream_inventory_source')) + + # Removing M2M table for field job_template on 'ActivityStream' + db.delete_table(db.shorten_name(u'main_activitystream_job_template')) + + # Removing M2M table for field job on 'ActivityStream' + db.delete_table(db.shorten_name(u'main_activitystream_job')) + + # Removing M2M table for field project on 'ActivityStream' + db.delete_table(db.shorten_name(u'main_activitystream_project')) - db.rename_table(db.shorten_name(u'main_activitystream_new_project'), db.shorten_name(u'main_activitystream_project')) - db.rename_column(db.shorten_name(u'main_activitystream_project'), 'projectnew_id', 'project_id') - db.rename_table(db.shorten_name(u'main_activitystream_new_project_update'), db.shorten_name(u'main_activitystream_project_update')) - db.rename_column(db.shorten_name(u'main_activitystream_project_update'), 'projectupdatenew_id', 'projectupdate_id') - db.rename_table(db.shorten_name(u'main_activitystream_new_inventory_source'), db.shorten_name(u'main_activitystream_inventory_source')) - db.rename_column(db.shorten_name(u'main_activitystream_inventory_source'), 'inventorysourcenew_id', 'inventorysource_id') - db.rename_table(db.shorten_name(u'main_activitystream_new_inventory_update'), db.shorten_name(u'main_activitystream_inventory_update')) - db.rename_column(db.shorten_name(u'main_activitystream_inventory_update'), 'inventoryupdatenew_id', 'inventoryupdate_id') - db.rename_table(db.shorten_name(u'main_activitystream_new_job_template'), db.shorten_name(u'main_activitystream_job_template')) - db.rename_column(db.shorten_name(u'main_activitystream_job_template'), 'jobtemplatenew_id', 'jobtemplate_id') - db.rename_table(db.shorten_name(u'main_activitystream_new_job'), db.shorten_name(u'main_activitystream_job')) - db.rename_column(db.shorten_name(u'main_activitystream_job'), 'jobnew_id', 'job_id') def backwards(self, orm): - db.rename_column(db.shorten_name(u'main_activitystream_job'), 'job_id', 'jobnew_id') - db.rename_table(db.shorten_name(u'main_activitystream_job'), db.shorten_name(u'main_activitystream_new_job')) - db.rename_column(db.shorten_name(u'main_activitystream_job_template'), 'jobtemplate_id', 'jobtemplatenew_id') - db.rename_table(db.shorten_name(u'main_activitystream_job_template'), db.shorten_name(u'main_activitystream_new_job_template')) - db.rename_column(db.shorten_name(u'main_activitystream_inventory_update'), 'inventoryupdate_id', 'inventoryupdatenew_id') - db.rename_table(db.shorten_name(u'main_activitystream_inventory_update'), db.shorten_name(u'main_activitystream_new_inventory_update')) - db.rename_column(db.shorten_name(u'main_activitystream_inventory_source'), 'inventorysource_id', 'inventorysourcenew_id') - db.rename_table(db.shorten_name(u'main_activitystream_inventory_source'), db.shorten_name(u'main_activitystream_new_inventory_source')) - db.rename_column(db.shorten_name(u'main_activitystream_project_update'), 'projectupdate_id', 'projectupdatenew_id') - db.rename_table(db.shorten_name(u'main_activitystream_project_update'), db.shorten_name(u'main_activitystream_new_project_update')) - db.rename_column(db.shorten_name(u'main_activitystream_project'), 'project_id', 'projectnew_id') - db.rename_table(db.shorten_name(u'main_activitystream_project'), db.shorten_name(u'main_activitystream_new_project')) + # Adding model 'JobTemplate' + db.create_table(u'main_jobtemplate', ( + ('credential', self.gf('django.db.models.fields.related.ForeignKey')(related_name='jobtemplates', on_delete=models.SET_NULL, default=None, to=orm['main.Credential'], blank=True, null=True)), + ('modified_by', self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name="{'class': 'jobtemplate', 'app_label': 'main'}(class)s_modified+", null=True, on_delete=models.SET_NULL, to=orm['auth.User'])), + ('description', self.gf('django.db.models.fields.TextField')(default='', blank=True)), + ('created', self.gf('django.db.models.fields.DateTimeField')(default=None)), + ('extra_vars', self.gf('django.db.models.fields.TextField')(default='', blank=True)), + ('verbosity', self.gf('django.db.models.fields.PositiveIntegerField')(default=0, blank=True)), + ('job_tags', self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True)), + ('job_type', self.gf('django.db.models.fields.CharField')(max_length=64)), + ('modified', self.gf('django.db.models.fields.DateTimeField')(default=None)), + ('created_by', self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name="{'class': 'jobtemplate', 'app_label': 'main'}(class)s_created+", null=True, on_delete=models.SET_NULL, to=orm['auth.User'])), + (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('project', self.gf('django.db.models.fields.related.ForeignKey')(related_name='job_templates', null=True, on_delete=models.SET_NULL, to=orm['main.Project'])), + ('host_config_key', self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True)), + ('limit', self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True)), + ('inventory', self.gf('django.db.models.fields.related.ForeignKey')(related_name='jobtemplates', null=True, on_delete=models.SET_NULL, to=orm['main.Inventory'])), + ('active', self.gf('django.db.models.fields.BooleanField')(default=True)), + ('forks', self.gf('django.db.models.fields.PositiveIntegerField')(default=0, blank=True)), + ('playbook', self.gf('django.db.models.fields.CharField')(default='', max_length=1024)), + ('cloud_credential', self.gf('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)), + ('name', self.gf('django.db.models.fields.CharField')(max_length=512, unique=True)), + )) + db.send_create_signal('main', ['JobTemplate']) - db.rename_column(u'main_jobevent', 'job_id', 'new_job_id') - db.rename_column(u'main_jobhostsummary', 'job_id', 'new_job_id') + # Adding model 'InventorySource' + db.create_table(u'main_inventorysource', ( + ('last_updated', self.gf('django.db.models.fields.DateTimeField')(default=None, null=True)), + ('source_regions', self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True)), + ('current_update', self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name='inventory_source_as_current_update+', null=True, on_delete=models.SET_NULL, to=orm['main.InventoryUpdate'])), + (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('overwrite', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('source_vars', self.gf('django.db.models.fields.TextField')(default='', blank=True)), + ('group', self.gf('awx.main.fields.AutoOneToOneField')(default=None, related_name='inventory_source', unique=True, null=True, to=orm['main.Group'])), + ('last_update_failed', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('created_by', self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name="{'class': 'inventorysource', 'app_label': 'main'}(class)s_created+", null=True, on_delete=models.SET_NULL, to=orm['auth.User'])), + ('last_update', self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name='inventory_source_as_last_update+', null=True, on_delete=models.SET_NULL, to=orm['main.InventoryUpdate'])), + ('source', self.gf('django.db.models.fields.CharField')(default='', max_length=32, blank=True)), + ('inventory', self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name='inventory_sources', null=True, to=orm['main.Inventory'])), + ('update_cache_timeout', self.gf('django.db.models.fields.PositiveIntegerField')(default=0)), + ('status', self.gf('django.db.models.fields.CharField')(default='none', max_length=32)), + ('credential', self.gf('django.db.models.fields.related.ForeignKey')(related_name='inventorysources', on_delete=models.SET_NULL, default=None, to=orm['main.Credential'], blank=True, null=True)), + ('description', self.gf('django.db.models.fields.TextField')(default='', blank=True)), + ('overwrite_vars', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('active', self.gf('django.db.models.fields.BooleanField')(default=True)), + ('modified_by', self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name="{'class': 'inventorysource', 'app_label': 'main'}(class)s_modified+", null=True, on_delete=models.SET_NULL, to=orm['auth.User'])), + ('update_on_launch', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('created', self.gf('django.db.models.fields.DateTimeField')(default=None)), + ('source_path', self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True)), + ('modified', self.gf('django.db.models.fields.DateTimeField')(default=None)), + )) + db.send_create_signal('main', ['InventorySource']) - db.rename_column(db.shorten_name(u'main_group_inventory_sources'), 'inventorysource_id', 'inventorysourcenew_id') - db.rename_table(db.shorten_name(u'main_group_inventory_sources'), db.shorten_name(u'main_group_new_inventory_sources')) - db.rename_column(db.shorten_name(u'main_host_inventory_sources'), 'inventorysource_id', 'inventorysourcenew_id') - db.rename_table(db.shorten_name(u'main_host_inventory_sources'), db.shorten_name(u'main_host_new_inventory_sources')) - db.rename_column(u'main_host', 'last_job_id', 'new_last_job_id') + # Adding model 'Project' + db.create_table(u'main_project', ( + ('scm_branch', self.gf('django.db.models.fields.CharField')(default='', max_length=256, blank=True)), + ('scm_update_cache_timeout', self.gf('django.db.models.fields.PositiveIntegerField')(default=0)), + ('scm_clean', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('scm_delete_on_update', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('current_update', self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name='project_as_current_update+', null=True, on_delete=models.SET_NULL, to=orm['main.ProjectUpdate'])), + ('last_updated', self.gf('django.db.models.fields.DateTimeField')(default=None, null=True)), + (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('modified_by', self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name="{'class': 'project', 'app_label': 'main'}(class)s_modified+", null=True, on_delete=models.SET_NULL, to=orm['auth.User'])), + ('last_update_failed', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('created_by', self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name="{'class': 'project', 'app_label': 'main'}(class)s_created+", null=True, on_delete=models.SET_NULL, to=orm['auth.User'])), + ('last_update', self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name='project_as_last_update+', null=True, on_delete=models.SET_NULL, to=orm['main.ProjectUpdate'])), + ('local_path', self.gf('django.db.models.fields.CharField')(max_length=1024, blank=True)), + ('scm_delete_on_next_update', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('status', self.gf('django.db.models.fields.CharField')(default='ok', max_length=32, null=True)), + ('credential', self.gf('django.db.models.fields.related.ForeignKey')(related_name='projects', on_delete=models.SET_NULL, default=None, to=orm['main.Credential'], blank=True, null=True)), + ('description', self.gf('django.db.models.fields.TextField')(default='', blank=True)), + ('scm_type', self.gf('django.db.models.fields.CharField')(default='', max_length=8, blank=True)), + ('scm_update_on_launch', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('active', self.gf('django.db.models.fields.BooleanField')(default=True)), + ('name', self.gf('django.db.models.fields.CharField')(max_length=512, unique=True)), + ('created', self.gf('django.db.models.fields.DateTimeField')(default=None)), + ('modified', self.gf('django.db.models.fields.DateTimeField')(default=None)), + ('scm_url', self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True)), + )) + db.send_create_signal('main', ['Project']) - db.rename_column(u'main_permission', 'project_id', 'new_project_id') - db.rename_column(db.shorten_name(u'main_organization_projects'), 'project_id', 'projectnew_id') - db.rename_table(db.shorten_name(u'main_organization_projects'), db.shorten_name(u'main_organization_new_projects')) - db.rename_column(db.shorten_name(u'main_team_projects'), 'project_id', 'projectnew_id') - db.rename_table(db.shorten_name(u'main_team_projects'), db.shorten_name(u'main_team_new_projects')) - - db.rename_table(u'main_job', 'main_jobnew') - db.rename_table(u'main_jobtemplate', 'main_jobtemplatenew') - db.rename_table(u'main_inventoryupdate', 'main_inventoryupdatenew') - db.rename_table(u'main_inventorysource', 'main_inventorysourcenew') - db.rename_table(u'main_projectupdate', 'main_projectupdatenew') - db.rename_table(u'main_project', 'main_projectnew') + # Adding model 'ProjectUpdate' + db.create_table(u'main_projectupdate', ( + ('cancel_flag', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('scm_branch', self.gf('django.db.models.fields.CharField')(default='', max_length=256, blank=True)), + ('scm_clean', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('scm_delete_on_update', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('start_args', self.gf('django.db.models.fields.TextField')(default='', blank=True)), + ('celery_task_id', self.gf('django.db.models.fields.CharField')(default='', max_length=100, blank=True)), + (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('modified_by', self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name="{'class': 'projectupdate', 'app_label': 'main'}(class)s_modified+", null=True, on_delete=models.SET_NULL, to=orm['auth.User'])), + ('job_cwd', self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True)), + ('created_by', self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name="{'class': 'projectupdate', 'app_label': 'main'}(class)s_created+", null=True, on_delete=models.SET_NULL, to=orm['auth.User'])), + ('failed', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('local_path', self.gf('django.db.models.fields.CharField')(max_length=1024, blank=True)), + ('status', self.gf('django.db.models.fields.CharField')(default='new', max_length=20)), + ('credential', self.gf('django.db.models.fields.related.ForeignKey')(related_name='projectupdates', on_delete=models.SET_NULL, default=None, to=orm['main.Credential'], blank=True, null=True)), + ('description', self.gf('django.db.models.fields.TextField')(default='', blank=True)), + ('result_traceback', self.gf('django.db.models.fields.TextField')(default='', blank=True)), + ('scm_type', self.gf('django.db.models.fields.CharField')(default='', max_length=8, blank=True)), + ('job_env', self.gf('jsonfield.fields.JSONField')(default={}, blank=True)), + ('active', self.gf('django.db.models.fields.BooleanField')(default=True)), + ('result_stdout_file', self.gf('django.db.models.fields.TextField')(default='', blank=True)), + ('created', self.gf('django.db.models.fields.DateTimeField')(default=None)), + ('job_args', self.gf('django.db.models.fields.TextField')(default='', blank=True)), + ('modified', self.gf('django.db.models.fields.DateTimeField')(default=None)), + ('scm_url', self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True)), + ('project', self.gf('django.db.models.fields.related.ForeignKey')(related_name='project_updates', to=orm['main.Project'])), + ('_result_stdout', self.gf('django.db.models.fields.TextField')(default='', db_column='result_stdout', blank=True)), + )) + db.send_create_signal('main', ['ProjectUpdate']) + + # Adding model 'InventoryUpdate' + db.create_table(u'main_inventoryupdate', ( + ('cancel_flag', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('source_regions', self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True)), + ('license_error', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('start_args', self.gf('django.db.models.fields.TextField')(default='', blank=True)), + ('celery_task_id', self.gf('django.db.models.fields.CharField')(default='', max_length=100, blank=True)), + (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('overwrite', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('source_vars', self.gf('django.db.models.fields.TextField')(default='', blank=True)), + ('modified_by', self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name="{'class': 'inventoryupdate', 'app_label': 'main'}(class)s_modified+", null=True, on_delete=models.SET_NULL, to=orm['auth.User'])), + ('job_cwd', self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True)), + ('source', self.gf('django.db.models.fields.CharField')(default='', max_length=32, blank=True)), + ('created_by', self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name="{'class': 'inventoryupdate', 'app_label': 'main'}(class)s_created+", null=True, on_delete=models.SET_NULL, to=orm['auth.User'])), + ('failed', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('status', self.gf('django.db.models.fields.CharField')(default='new', max_length=20)), + ('credential', self.gf('django.db.models.fields.related.ForeignKey')(related_name='inventoryupdates', on_delete=models.SET_NULL, default=None, to=orm['main.Credential'], blank=True, null=True)), + ('description', self.gf('django.db.models.fields.TextField')(default='', blank=True)), + ('overwrite_vars', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('result_traceback', self.gf('django.db.models.fields.TextField')(default='', blank=True)), + ('job_env', self.gf('jsonfield.fields.JSONField')(default={}, blank=True)), + ('active', self.gf('django.db.models.fields.BooleanField')(default=True)), + ('result_stdout_file', self.gf('django.db.models.fields.TextField')(default='', blank=True)), + ('inventory_source', self.gf('django.db.models.fields.related.ForeignKey')(related_name='inventory_updates', to=orm['main.InventorySource'])), + ('created', self.gf('django.db.models.fields.DateTimeField')(default=None)), + ('job_args', self.gf('django.db.models.fields.TextField')(default='', blank=True)), + ('source_path', self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True)), + ('modified', self.gf('django.db.models.fields.DateTimeField')(default=None)), + ('_result_stdout', self.gf('django.db.models.fields.TextField')(default='', db_column='result_stdout', blank=True)), + )) + db.send_create_signal('main', ['InventoryUpdate']) + + # Adding model 'Job' + db.create_table(u'main_job', ( + ('cancel_flag', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('credential', self.gf('django.db.models.fields.related.ForeignKey')(related_name='jobs', on_delete=models.SET_NULL, default=None, to=orm['main.Credential'], blank=True, null=True)), + ('description', self.gf('django.db.models.fields.TextField')(default='', blank=True)), + ('result_traceback', self.gf('django.db.models.fields.TextField')(default='', blank=True)), + ('job_type', self.gf('django.db.models.fields.CharField')(max_length=64)), + ('start_args', self.gf('django.db.models.fields.TextField')(default='', blank=True)), + ('job_tags', self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True)), + ('celery_task_id', self.gf('django.db.models.fields.CharField')(default='', max_length=100, blank=True)), + ('playbook', self.gf('django.db.models.fields.CharField')(default='', max_length=1024)), + ('job_env', self.gf('jsonfield.fields.JSONField')(default={}, blank=True)), + ('active', self.gf('django.db.models.fields.BooleanField')(default=True)), + ('result_stdout_file', self.gf('django.db.models.fields.TextField')(default='', blank=True)), + (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('status', self.gf('django.db.models.fields.CharField')(default='new', max_length=20)), + ('modified_by', self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name="{'class': 'job', 'app_label': 'main'}(class)s_modified+", null=True, on_delete=models.SET_NULL, to=orm['auth.User'])), + ('job_cwd', self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True)), + ('job_template', self.gf('django.db.models.fields.related.ForeignKey')(related_name='jobs', on_delete=models.SET_NULL, default=None, to=orm['main.JobTemplate'], blank=True, null=True)), + ('created', self.gf('django.db.models.fields.DateTimeField')(default=None)), + ('extra_vars', self.gf('django.db.models.fields.TextField')(default='', blank=True)), + ('verbosity', self.gf('django.db.models.fields.PositiveIntegerField')(default=0, blank=True)), + ('job_args', self.gf('django.db.models.fields.TextField')(default='', blank=True)), + ('modified', self.gf('django.db.models.fields.DateTimeField')(default=None)), + ('created_by', self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name="{'class': 'job', 'app_label': 'main'}(class)s_created+", null=True, on_delete=models.SET_NULL, to=orm['auth.User'])), + ('project', self.gf('django.db.models.fields.related.ForeignKey')(related_name='jobs', null=True, on_delete=models.SET_NULL, to=orm['main.Project'])), + ('failed', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('inventory', self.gf('django.db.models.fields.related.ForeignKey')(related_name='jobs', null=True, on_delete=models.SET_NULL, to=orm['main.Inventory'])), + ('_result_stdout', self.gf('django.db.models.fields.TextField')(default='', db_column='result_stdout', blank=True)), + ('limit', self.gf('django.db.models.fields.CharField')(default='', max_length=1024, blank=True)), + ('forks', self.gf('django.db.models.fields.PositiveIntegerField')(default=0, blank=True)), + ('cloud_credential', self.gf('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)), + ('launch_type', self.gf('django.db.models.fields.CharField')(default='manual', max_length=20)), + )) + db.send_create_signal('main', ['Job']) + + # Adding field 'Host.last_job' + db.add_column(u'main_host', 'last_job', + self.gf('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']), + keep_default=False) + + # Adding M2M table for field inventory_sources on 'Host' + m2m_table_name = db.shorten_name(u'main_host_inventory_sources') + db.create_table(m2m_table_name, ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('host', models.ForeignKey(orm['main.host'], null=False)), + ('inventorysource', models.ForeignKey(orm['main.inventorysource'], null=False)) + )) + db.create_unique(m2m_table_name, ['host_id', 'inventorysource_id']) + + # Adding M2M table for field projects on 'Organization' + m2m_table_name = db.shorten_name(u'main_organization_projects') + db.create_table(m2m_table_name, ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('organization', models.ForeignKey(orm['main.organization'], null=False)), + ('project', models.ForeignKey(orm['main.project'], null=False)) + )) + db.create_unique(m2m_table_name, ['organization_id', 'project_id']) + + # Adding M2M table for field projects on 'Team' + m2m_table_name = db.shorten_name(u'main_team_projects') + db.create_table(m2m_table_name, ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('team', models.ForeignKey(orm['main.team'], null=False)), + ('project', models.ForeignKey(orm['main.project'], null=False)) + )) + db.create_unique(m2m_table_name, ['team_id', 'project_id']) + + # Adding field 'Permission.project' + db.add_column(u'main_permission', 'project', + self.gf('django.db.models.fields.related.ForeignKey')(related_name='permissions', null=True, to=orm['main.Project'], on_delete=models.SET_NULL, blank=True), + keep_default=False) + + # Adding field 'JobHostSummary.job' + db.add_column(u'main_jobhostsummary', 'job', + self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name='job_host_summaries', null=True, to=orm['main.Job']), + keep_default=False) + + # Changing field 'JobHostSummary.new_job' + db.alter_column(u'main_jobhostsummary', 'new_job_id', self.gf('django.db.models.fields.related.ForeignKey')(null=True, to=orm['main.JobNew'])) + + # Adding unique constraint on 'JobHostSummary', fields ['job', 'host'] + db.create_unique(u'main_jobhostsummary', ['job_id', 'host_id']) + + # Adding M2M table for field inventory_sources on 'Group' + m2m_table_name = db.shorten_name(u'main_group_inventory_sources') + db.create_table(m2m_table_name, ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('group', models.ForeignKey(orm['main.group'], null=False)), + ('inventorysource', models.ForeignKey(orm['main.inventorysource'], null=False)) + )) + db.create_unique(m2m_table_name, ['group_id', 'inventorysource_id']) + + # Adding field 'JobEvent.job' + db.add_column(u'main_jobevent', 'job', + self.gf('django.db.models.fields.related.ForeignKey')(default=None, related_name='job_events', null=True, to=orm['main.Job']), + keep_default=False) + + # Changing field 'JobEvent.new_job' + db.alter_column(u'main_jobevent', 'new_job_id', self.gf('django.db.models.fields.related.ForeignKey')(null=True, to=orm['main.JobNew'])) + # Adding M2M table for field inventory_update on 'ActivityStream' + m2m_table_name = db.shorten_name(u'main_activitystream_inventory_update') + db.create_table(m2m_table_name, ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('activitystream', models.ForeignKey(orm['main.activitystream'], null=False)), + ('inventoryupdate', models.ForeignKey(orm['main.inventoryupdate'], null=False)) + )) + db.create_unique(m2m_table_name, ['activitystream_id', 'inventoryupdate_id']) + + # Adding M2M table for field project_update on 'ActivityStream' + m2m_table_name = db.shorten_name(u'main_activitystream_project_update') + db.create_table(m2m_table_name, ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('activitystream', models.ForeignKey(orm['main.activitystream'], null=False)), + ('projectupdate', models.ForeignKey(orm['main.projectupdate'], null=False)) + )) + db.create_unique(m2m_table_name, ['activitystream_id', 'projectupdate_id']) + + # Adding M2M table for field inventory_source on 'ActivityStream' + m2m_table_name = db.shorten_name(u'main_activitystream_inventory_source') + db.create_table(m2m_table_name, ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('activitystream', models.ForeignKey(orm['main.activitystream'], null=False)), + ('inventorysource', models.ForeignKey(orm['main.inventorysource'], null=False)) + )) + db.create_unique(m2m_table_name, ['activitystream_id', 'inventorysource_id']) + + # Adding M2M table for field job_template on 'ActivityStream' + m2m_table_name = db.shorten_name(u'main_activitystream_job_template') + db.create_table(m2m_table_name, ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('activitystream', models.ForeignKey(orm['main.activitystream'], null=False)), + ('jobtemplate', models.ForeignKey(orm['main.jobtemplate'], null=False)) + )) + db.create_unique(m2m_table_name, ['activitystream_id', 'jobtemplate_id']) + + # Adding M2M table for field job on 'ActivityStream' + m2m_table_name = db.shorten_name(u'main_activitystream_job') + db.create_table(m2m_table_name, ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('activitystream', models.ForeignKey(orm['main.activitystream'], null=False)), + ('job', models.ForeignKey(orm['main.job'], null=False)) + )) + db.create_unique(m2m_table_name, ['activitystream_id', 'job_id']) + + # Adding M2M table for field project on 'ActivityStream' + m2m_table_name = db.shorten_name(u'main_activitystream_project') + db.create_table(m2m_table_name, ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('activitystream', models.ForeignKey(orm['main.activitystream'], null=False)), + ('project', models.ForeignKey(orm['main.project'], null=False)) + )) + db.create_unique(m2m_table_name, ['activitystream_id', 'project_id']) models = { @@ -129,18 +423,19 @@ class Migration(SchemaMigration): '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'}), + 'new_inventory_source': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.InventorySourceNew']", 'symmetrical': 'False', 'blank': 'True'}), + 'new_inventory_update': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.InventoryUpdateNew']", 'symmetrical': 'False', 'blank': 'True'}), + 'new_job': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.JobNew']", 'symmetrical': 'False', 'blank': 'True'}), + 'new_job_template': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.JobTemplateNew']", 'symmetrical': 'False', 'blank': 'True'}), + 'new_project': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.ProjectNew']", 'symmetrical': 'False', 'blank': 'True'}), + 'new_project_update': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['main.ProjectUpdateNew']", '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']"}), @@ -170,12 +465,14 @@ class Migration(SchemaMigration): 'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}), 'password': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), 'ssh_key_data': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'ssh_key_path': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), 'ssh_key_unlock': ('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'}) + '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.group': { 'Meta': {'unique_together': "(('name', 'inventory'),)", 'object_name': 'Group'}, @@ -190,10 +487,10 @@ class Migration(SchemaMigration): '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', [], {'symmetrical': 'False', 'related_name': "'groups'", 'blank': 'True', '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'}), + 'new_inventory_sources': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'groups'", 'symmetrical': 'False', 'to': "orm['main.InventorySourceNew']"}), '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'}), @@ -211,12 +508,12 @@ class Migration(SchemaMigration): 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', [], {'symmetrical': 'False', 'related_name': "'hosts'", 'blank': 'True', 'to': "orm['main.InventorySource']"}), - 'last_job': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'hosts_as_last_job+'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.Job']", 'blank': 'True', 'null': 'True'}), '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'}), + 'new_inventory_sources': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'hosts'", 'symmetrical': 'False', 'to': "orm['main.InventorySourceNew']"}), + 'new_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.JobNew']"}), 'variables': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}) }, 'main.inventory': { @@ -240,11 +537,11 @@ class Migration(SchemaMigration): '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', [], {'default': 'None', 'related_name': "'inventorysources'", 'null': 'True', 'blank': 'True', 'to': "orm['main.Credential']"}), - 'group': ('awx.main.fields.AutoOneToOneField', [], {'related_name': "'inventory_source'", 'null': 'True', 'default': 'None', 'to': "orm['main.Group']", 'blank': 'True', 'unique': 'True'}), - 'inventory': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'inventory_sources'", 'null': 'True', 'to': "orm['main.Inventory']"}), + 'main.inventorysourcenew': { + 'Meta': {'object_name': 'InventorySourceNew', '_ormbases': ['main.UnifiedJobTemplate']}, + 'credential': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'inventorysourcenews'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.Credential']", 'blank': 'True', 'null': 'True'}), + 'group': ('awx.main.fields.AutoOneToOneField', [], {'default': 'None', 'related_name': "'new_inventory_source'", 'unique': 'True', 'null': 'True', 'to': "orm['main.Group']"}), + 'inventory': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'new_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'}), @@ -255,10 +552,10 @@ class Migration(SchemaMigration): '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', [], {'default': 'None', 'related_name': "'inventoryupdates'", 'null': 'True', 'blank': 'True', 'to': "orm['main.Credential']"}), - 'inventory_source': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'inventory_updates'", 'to': "orm['main.InventorySource']"}), + 'main.inventoryupdatenew': { + 'Meta': {'object_name': 'InventoryUpdateNew', '_ormbases': ['main.UnifiedJob']}, + 'credential': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'inventoryupdatenews'", '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.InventorySourceNew']"}), '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'}), @@ -268,23 +565,6 @@ class Migration(SchemaMigration): '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': {'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'}), - 'forks': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0', 'blank': 'True'}), - 'hosts': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'jobs'", 'blank': 'True', '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']"}), - 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'}), @@ -292,18 +572,18 @@ class Migration(SchemaMigration): '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', [], {'related_name': "'job_events_as_primary_host'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.Host']", 'blank': 'True', 'null': 'True'}), - 'hosts': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'job_events'", 'blank': 'True', 'to': "orm['main.Host']"}), + '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']"}), + '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', [], {'related_name': "'children'", 'on_delete': 'models.SET_NULL', 'default': 'None', 'to': "orm['main.JobEvent']", 'blank': 'True', 'null': 'True'}), - 'play': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), - 'role': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), - 'task': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}) + 'new_job': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'new_job_events'", 'to': "orm['main.JobNew']"}), + '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')]", 'object_name': 'JobHostSummary'}, + 'Meta': {'ordering': "('-pk',)", 'unique_together': "[('new_job', 'host')]", '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'}), @@ -311,25 +591,42 @@ class Migration(SchemaMigration): 'failures': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), 'host': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'job_host_summaries'", 'to': "orm['main.Host']"}), 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'}), + 'new_job': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'new_job_host_summaries'", 'to': "orm['main.JobNew']"}), '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': {'object_name': 'JobTemplate', '_ormbases': ['main.UnifiedJobTemplate']}, - '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'}), + 'main.jobnew': { + 'Meta': {'object_name': 'JobNew', '_ormbases': ['main.UnifiedJob']}, + 'cloud_credential': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobnews_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': "'jobnews'", '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'}), + 'forks': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0', 'blank': 'True'}), + 'hosts': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'jobnews'", 'symmetrical': 'False', 'through': "orm['main.JobHostSummary']", 'to': "orm['main.Host']"}), + 'inventory': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobnews'", '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.JobTemplateNew']", '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.ProjectNew']"}), + 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.jobtemplatenew': { + 'Meta': {'object_name': 'JobTemplateNew', '_ormbases': ['main.UnifiedJobTemplate']}, + 'cloud_credential': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobtemplatenews_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': "'jobtemplatenews'", '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'}), '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']"}), + 'inventory': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'jobtemplatenews'", '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': "'job_templates'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Project']"}), + 'project': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'job_templates'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.ProjectNew']"}), 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'}) }, @@ -344,7 +641,7 @@ class Migration(SchemaMigration): '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']"}), + 'new_projects': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'organizations'", 'blank': 'True', 'to': "orm['main.ProjectNew']"}), 'users': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'organizations'", 'blank': 'True', 'to': u"orm['auth.User']"}) }, 'main.permission': { @@ -358,8 +655,8 @@ class Migration(SchemaMigration): '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'}), + 'new_project': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'permissions'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.ProjectNew']"}), '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']"}) }, @@ -371,9 +668,9 @@ class Migration(SchemaMigration): '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': {'object_name': 'Project', '_ormbases': ['main.UnifiedJobTemplate']}, - 'credential': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'projects'", 'null': 'True', 'blank': 'True', 'to': "orm['main.Credential']"}), + 'main.projectnew': { + 'Meta': {'object_name': 'ProjectNew', '_ormbases': ['main.UnifiedJobTemplate']}, + 'credential': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'projectnews'", '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'}), @@ -385,11 +682,11 @@ class Migration(SchemaMigration): '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', [], {'default': 'None', 'related_name': "'projectupdates'", 'null': 'True', 'blank': 'True', 'to': "orm['main.Credential']"}), + 'main.projectupdatenew': { + 'Meta': {'object_name': 'ProjectUpdateNew', '_ormbases': ['main.UnifiedJob']}, + 'credential': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'projectupdatenews'", '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']"}), + 'project': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'project_updates'", 'to': "orm['main.ProjectNew']"}), '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'}), @@ -405,12 +702,14 @@ class Migration(SchemaMigration): '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', [], {}), + 'enabled': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'job_template': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'schedules'", 'to': "orm['main.UnifiedJobTemplate']"}), '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'}), - 'rrule': ('django.db.models.fields.CharField', [], {'max_length': '255'}) + '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.team': { 'Meta': {'unique_together': "[('organization', 'name')]", 'object_name': 'Team'}, @@ -422,8 +721,8 @@ class Migration(SchemaMigration): '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'}), + 'new_projects': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'teams'", 'blank': 'True', 'to': "orm['main.ProjectNew']"}), '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': { @@ -433,7 +732,7 @@ class Migration(SchemaMigration): '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']"}), - 'depends_on': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'depends_on_rel_+'", 'to': "orm['main.UnifiedJob']"}), + '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'}), @@ -445,33 +744,35 @@ class Migration(SchemaMigration): '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'}), + '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', 'to': "orm['main.UnifiedJobTemplate']"}) + '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', 'to': "orm['main.UnifiedJob']"}), + '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', 'to': "orm['main.UnifiedJob']"}), + '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'}) diff --git a/awx/main/migrations/0038_v148_changes.py b/awx/main/migrations/0038_v148_changes.py new file mode 100644 index 0000000000..4c1d877d7e --- /dev/null +++ b/awx/main/migrations/0038_v148_changes.py @@ -0,0 +1,500 @@ +# -*- 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): + ''' + Rename tables/columns to be consistent with model/field names. + ''' + + def forwards(self, orm): + db.rename_table(u'main_projectnew', 'main_project') + db.rename_table(u'main_projectupdatenew', 'main_projectupdate') + db.rename_table(u'main_inventorysourcenew', 'main_inventorysource') + db.rename_table(u'main_inventoryupdatenew', 'main_inventoryupdate') + db.rename_table(u'main_jobtemplatenew', 'main_jobtemplate') + db.rename_table(u'main_jobnew', 'main_job') + + db.rename_table(db.shorten_name(u'main_team_new_projects'), db.shorten_name(u'main_team_projects')) + db.rename_column(db.shorten_name(u'main_team_projects'), 'projectnew_id', 'project_id') + db.rename_table(db.shorten_name(u'main_organization_new_projects'), db.shorten_name(u'main_organization_projects')) + db.rename_column(db.shorten_name(u'main_organization_projects'), 'projectnew_id', 'project_id') + db.rename_column(u'main_permission', 'new_project_id', 'project_id') + + db.rename_column(u'main_host', 'new_last_job_id', 'last_job_id') + db.rename_table(db.shorten_name(u'main_host_new_inventory_sources'), db.shorten_name(u'main_host_inventory_sources')) + db.rename_column(db.shorten_name(u'main_host_inventory_sources'), 'inventorysourcenew_id', 'inventorysource_id') + db.rename_table(db.shorten_name(u'main_group_new_inventory_sources'), db.shorten_name(u'main_group_inventory_sources')) + db.rename_column(db.shorten_name(u'main_group_inventory_sources'), 'inventorysourcenew_id', 'inventorysource_id') + + db.rename_column(u'main_jobhostsummary', 'new_job_id', 'job_id') + db.rename_column(u'main_jobevent', 'new_job_id', 'job_id') + + db.rename_table(db.shorten_name(u'main_activitystream_new_project'), db.shorten_name(u'main_activitystream_project')) + db.rename_column(db.shorten_name(u'main_activitystream_project'), 'projectnew_id', 'project_id') + db.rename_table(db.shorten_name(u'main_activitystream_new_project_update'), db.shorten_name(u'main_activitystream_project_update')) + db.rename_column(db.shorten_name(u'main_activitystream_project_update'), 'projectupdatenew_id', 'projectupdate_id') + db.rename_table(db.shorten_name(u'main_activitystream_new_inventory_source'), db.shorten_name(u'main_activitystream_inventory_source')) + db.rename_column(db.shorten_name(u'main_activitystream_inventory_source'), 'inventorysourcenew_id', 'inventorysource_id') + db.rename_table(db.shorten_name(u'main_activitystream_new_inventory_update'), db.shorten_name(u'main_activitystream_inventory_update')) + db.rename_column(db.shorten_name(u'main_activitystream_inventory_update'), 'inventoryupdatenew_id', 'inventoryupdate_id') + db.rename_table(db.shorten_name(u'main_activitystream_new_job_template'), db.shorten_name(u'main_activitystream_job_template')) + db.rename_column(db.shorten_name(u'main_activitystream_job_template'), 'jobtemplatenew_id', 'jobtemplate_id') + db.rename_table(db.shorten_name(u'main_activitystream_new_job'), db.shorten_name(u'main_activitystream_job')) + db.rename_column(db.shorten_name(u'main_activitystream_job'), 'jobnew_id', 'job_id') + + def backwards(self, orm): + db.rename_column(db.shorten_name(u'main_activitystream_job'), 'job_id', 'jobnew_id') + db.rename_table(db.shorten_name(u'main_activitystream_job'), db.shorten_name(u'main_activitystream_new_job')) + db.rename_column(db.shorten_name(u'main_activitystream_job_template'), 'jobtemplate_id', 'jobtemplatenew_id') + db.rename_table(db.shorten_name(u'main_activitystream_job_template'), db.shorten_name(u'main_activitystream_new_job_template')) + db.rename_column(db.shorten_name(u'main_activitystream_inventory_update'), 'inventoryupdate_id', 'inventoryupdatenew_id') + db.rename_table(db.shorten_name(u'main_activitystream_inventory_update'), db.shorten_name(u'main_activitystream_new_inventory_update')) + db.rename_column(db.shorten_name(u'main_activitystream_inventory_source'), 'inventorysource_id', 'inventorysourcenew_id') + db.rename_table(db.shorten_name(u'main_activitystream_inventory_source'), db.shorten_name(u'main_activitystream_new_inventory_source')) + db.rename_column(db.shorten_name(u'main_activitystream_project_update'), 'projectupdate_id', 'projectupdatenew_id') + db.rename_table(db.shorten_name(u'main_activitystream_project_update'), db.shorten_name(u'main_activitystream_new_project_update')) + db.rename_column(db.shorten_name(u'main_activitystream_project'), 'project_id', 'projectnew_id') + db.rename_table(db.shorten_name(u'main_activitystream_project'), db.shorten_name(u'main_activitystream_new_project')) + + db.rename_column(u'main_jobevent', 'job_id', 'new_job_id') + db.rename_column(u'main_jobhostsummary', 'job_id', 'new_job_id') + + db.rename_column(db.shorten_name(u'main_group_inventory_sources'), 'inventorysource_id', 'inventorysourcenew_id') + db.rename_table(db.shorten_name(u'main_group_inventory_sources'), db.shorten_name(u'main_group_new_inventory_sources')) + db.rename_column(db.shorten_name(u'main_host_inventory_sources'), 'inventorysource_id', 'inventorysourcenew_id') + db.rename_table(db.shorten_name(u'main_host_inventory_sources'), db.shorten_name(u'main_host_new_inventory_sources')) + db.rename_column(u'main_host', 'last_job_id', 'new_last_job_id') + + db.rename_column(u'main_permission', 'project_id', 'new_project_id') + db.rename_column(db.shorten_name(u'main_organization_projects'), 'project_id', 'projectnew_id') + db.rename_table(db.shorten_name(u'main_organization_projects'), db.shorten_name(u'main_organization_new_projects')) + db.rename_column(db.shorten_name(u'main_team_projects'), 'project_id', 'projectnew_id') + db.rename_table(db.shorten_name(u'main_team_projects'), db.shorten_name(u'main_team_new_projects')) + + db.rename_table(u'main_job', 'main_jobnew') + db.rename_table(u'main_jobtemplate', 'main_jobtemplatenew') + db.rename_table(u'main_inventoryupdate', 'main_inventoryupdatenew') + db.rename_table(u'main_inventorysource', 'main_inventorysourcenew') + db.rename_table(u'main_projectupdate', 'main_projectupdatenew') + db.rename_table(u'main_project', 'main_projectnew') + + 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', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), + 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', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), + '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': {'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'}), + 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'}), + 'ssh_key_data': ('django.db.models.fields.TextField', [], {'default': "''", 'blank': 'True'}), + 'ssh_key_path': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '1024', 'blank': 'True'}), + 'ssh_key_unlock': ('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.group': { + 'Meta': {'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': {'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': {'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_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_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': {'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'}), + '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']"}), + 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'}), + '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']"}), + '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')]", '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', [], {'related_name': "'job_host_summaries'", 'to': "orm['main.Host']"}), + 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': {'object_name': 'JobTemplate', '_ormbases': ['main.UnifiedJobTemplate']}, + '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'}), + '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': "'job_templates'", 'null': 'True', 'on_delete': 'models.SET_NULL', 'to': "orm['main.Project']"}), + 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': {'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': {'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': {'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', [], {}), + 'enabled': ('django.db.models.fields.BooleanField', [], {'default': '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.team': { + 'Meta': {'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'}), + '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'}) + }, + u'taggit.tag': { + 'Meta': {'object_name': 'Tag'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'}), + 'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '100'}) + }, + u'taggit.taggeditem': { + 'Meta': {'object_name': 'TaggedItem'}, + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'taggit_taggeditem_tagged_items'", 'to': u"orm['contenttypes.ContentType']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'object_id': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'}), + 'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'taggit_taggeditem_items'", 'to': u"orm['taggit.Tag']"}) + } + } + + complete_apps = ['main'] \ No newline at end of file diff --git a/awx/main/models/activity_stream.py b/awx/main/models/activity_stream.py index 65f1818748..2a8e2b0721 100644 --- a/awx/main/models/activity_stream.py +++ b/awx/main/models/activity_stream.py @@ -50,6 +50,7 @@ class ActivityStreamBase(models.Model): permission = models.ManyToManyField("Permission", blank=True) #job_template = models.ManyToManyField("JobTemplate", blank=True) #job = models.ManyToManyField("Job", blank=True) + schedule = models.ManyToManyField("Schedule", blank=True) def get_absolute_url(self): return reverse('api:activity_stream_detail', args=(self.pk,)) diff --git a/awx/main/models/base.py b/awx/main/models/base.py index 5b680c1a81..436e837f29 100644 --- a/awx/main/models/base.py +++ b/awx/main/models/base.py @@ -142,6 +142,17 @@ class BaseModel(models.Model): if errors: raise ValidationError(errors) + def update_fields(self, **kwargs): + save = kwargs.pop('save', True) + update_fields = [] + for field, value in kwargs.items(): + if getattr(self, field) != value: + setattr(self, field, value) + update_fields.append(field) + if save and update_fields: + self.save(update_fields=update_fields) + return update_fields + def save(self, *args, **kwargs): # For compatibility with Django 1.4.x, attempt to handle any calls to # save that pass update_fields. @@ -308,6 +319,11 @@ if getattr(settings, 'UNIFIED_JOBS_STEP') == 0: default={}, editable=False, ) + start_args = models.TextField( + blank=True, + default='', + editable=False, + ) _result_stdout = models.TextField( blank=True, default='', diff --git a/awx/main/models/inventory.py b/awx/main/models/inventory.py index 5a8e6ee207..dd3d59533f 100644 --- a/awx/main/models/inventory.py +++ b/awx/main/models/inventory.py @@ -47,6 +47,7 @@ class Inventory(CommonModel): 'Organization', related_name='inventories', help_text=_('Organization containing this inventory.'), + on_delete=models.CASCADE, ) variables = models.TextField( blank=True, @@ -168,6 +169,7 @@ class HostBase(CommonModelNameNotUnique): inventory = models.ForeignKey( 'Inventory', related_name='hosts', + on_delete=models.CASCADE, ) enabled = models.BooleanField( default=True, @@ -290,7 +292,6 @@ if getattr(settings, 'UNIFIED_JOBS_STEP') == 0: last_job = models.ForeignKey( 'Job', related_name='hosts_as_last_job+', - blank=True, null=True, default=None, editable=False, @@ -299,7 +300,6 @@ if getattr(settings, 'UNIFIED_JOBS_STEP') == 0: new_last_job = models.ForeignKey( 'JobNew', related_name='hosts_as_last_job+', - blank=True, null=True, default=None, editable=False, @@ -308,14 +308,12 @@ if getattr(settings, 'UNIFIED_JOBS_STEP') == 0: inventory_sources = models.ManyToManyField( 'InventorySource', related_name='hosts', - blank=True, editable=False, help_text=_('Inventory source(s) that created or modified this host.'), ) new_inventory_sources = models.ManyToManyField( 'InventorySourceNew', related_name='hosts', - blank=True, editable=False, help_text=_('Inventory source(s) that created or modified this host.'), ) @@ -331,7 +329,6 @@ if getattr(settings, 'UNIFIED_JOBS_STEP') == 1: new_last_job = models.ForeignKey( 'JobNew', related_name='hosts_as_last_job+', - blank=True, null=True, default=None, editable=False, @@ -340,7 +337,6 @@ if getattr(settings, 'UNIFIED_JOBS_STEP') == 1: new_inventory_sources = models.ManyToManyField( 'InventorySourceNew', related_name='hosts', - blank=True, editable=False, help_text=_('Inventory source(s) that created or modified this host.'), ) @@ -356,7 +352,6 @@ if getattr(settings, 'UNIFIED_JOBS_STEP') == 2: last_job = models.ForeignKey( 'Job', related_name='hosts_as_last_job+', - blank=True, null=True, default=None, editable=False, @@ -365,7 +360,6 @@ if getattr(settings, 'UNIFIED_JOBS_STEP') == 2: inventory_sources = models.ManyToManyField( 'InventorySource', related_name='hosts', - blank=True, editable=False, help_text=_('Inventory source(s) that created or modified this host.'), ) @@ -385,6 +379,7 @@ class GroupBase(CommonModelNameNotUnique): inventory = models.ForeignKey( 'Inventory', related_name='groups', + on_delete=models.CASCADE, ) # Can also be thought of as: parents == member_of, children == members parents = models.ManyToManyField( @@ -572,7 +567,6 @@ if getattr(settings, 'UNIFIED_JOBS_STEP') == 0: inventory_sources = models.ManyToManyField( 'InventorySource', related_name='groups', - blank=True, editable=False, help_text=_('Inventory source(s) that created or modified this group.'), ) @@ -580,7 +574,6 @@ if getattr(settings, 'UNIFIED_JOBS_STEP') == 0: new_inventory_sources = models.ManyToManyField( 'InventorySourceNew', related_name='groups', - blank=True, editable=False, help_text=_('Inventory source(s) that created or modified this group.'), ) @@ -596,7 +589,6 @@ if getattr(settings, 'UNIFIED_JOBS_STEP') == 1: new_inventory_sources = models.ManyToManyField( 'InventorySourceNew', related_name='groups', - blank=True, editable=False, help_text=_('Inventory source(s) that created or modified this group.'), ) @@ -612,7 +604,6 @@ if getattr(settings, 'UNIFIED_JOBS_STEP') == 2: inventory_sources = models.ManyToManyField( 'InventorySource', related_name='groups', - blank=True, editable=False, help_text=_('Inventory source(s) that created or modified this group.'), ) @@ -655,7 +646,7 @@ class InventorySourceOptions(BaseModel): null=True, default=None, blank=True, - #on_delete=models.SET_NULL, # FIXME + on_delete=models.SET_NULL, ) source_regions = models.CharField( max_length=1024, @@ -830,14 +821,15 @@ if getattr(settings, 'UNIFIED_JOBS_STEP') == 0: null=True, default=None, editable=False, + on_delete=models.CASCADE, ) group = AutoOneToOneField( 'Group', related_name='inventory_source', - blank=True, null=True, default=None, editable=False, + on_delete=models.CASCADE, ) current_update = models.ForeignKey( 'InventoryUpdate', @@ -845,6 +837,7 @@ if getattr(settings, 'UNIFIED_JOBS_STEP') == 0: default=None, editable=False, related_name='inventory_source_as_current_update+', + on_delete=models.SET_NULL, ) last_update = models.ForeignKey( 'InventoryUpdate', @@ -852,6 +845,7 @@ if getattr(settings, 'UNIFIED_JOBS_STEP') == 0: default=None, editable=False, related_name='inventory_source_as_last_update+', + on_delete=models.SET_NULL, ) last_update_failed = models.BooleanField( default=False, @@ -882,14 +876,15 @@ if getattr(settings, 'UNIFIED_JOBS_STEP') in (0, 1): null=True, default=None, editable=False, + on_delete=models.CASCADE, ) group = AutoOneToOneField( 'Group', related_name='new_inventory_source', - blank=True, null=True, default=None, editable=False, + on_delete=models.CASCADE, ) if getattr(settings, 'UNIFIED_JOBS_STEP') == 1: @@ -912,14 +907,15 @@ if getattr(settings, 'UNIFIED_JOBS_STEP') == 2: null=True, default=None, editable=False, + on_delete=models.CASCADE, ) group = AutoOneToOneField( 'Group', related_name='inventory_source', - blank=True, null=True, default=None, editable=False, + on_delete=models.CASCADE, ) @@ -972,8 +968,8 @@ if getattr(settings, 'UNIFIED_JOBS_STEP') == 0: inventory_source = models.ForeignKey( 'InventorySource', related_name='inventory_updates', - on_delete=models.CASCADE, editable=False, + on_delete=models.CASCADE, ) if getattr(settings, 'UNIFIED_JOBS_STEP') in (0, 1): @@ -986,8 +982,8 @@ if getattr(settings, 'UNIFIED_JOBS_STEP') in (0, 1): inventory_source = models.ForeignKey( 'InventorySourceNew', related_name='inventory_updates', - on_delete=models.CASCADE, editable=False, + on_delete=models.CASCADE, ) if getattr(settings, 'UNIFIED_JOBS_STEP') == 1: @@ -1007,6 +1003,6 @@ if getattr(settings, 'UNIFIED_JOBS_STEP') == 2: inventory_source = models.ForeignKey( 'InventorySource', related_name='inventory_updates', - on_delete=models.CASCADE, editable=False, + on_delete=models.CASCADE, ) diff --git a/awx/main/models/jobs.py b/awx/main/models/jobs.py index b7e96f2405..6da670b42c 100644 --- a/awx/main/models/jobs.py +++ b/awx/main/models/jobs.py @@ -243,7 +243,6 @@ class JobBase(JobOptions): hosts = models.ManyToManyField( 'Host', related_name='%(class)ss', - blank=True, editable=False, through='JobHostSummary', ) @@ -541,6 +540,8 @@ if getattr(settings, 'UNIFIED_JOBS_STEP') == 0: 'Job', related_name='job_host_summaries', on_delete=models.CASCADE, + null=True, + default=None, editable=False, ) new_job = models.ForeignKey( @@ -679,7 +680,6 @@ class JobEventBase(CreatedModifiedModel): host = models.ForeignKey( 'Host', related_name='job_events_as_primary_host', - blank=True, null=True, default=None, on_delete=models.SET_NULL, @@ -688,31 +688,26 @@ class JobEventBase(CreatedModifiedModel): hosts = models.ManyToManyField( 'Host', related_name='job_events', - blank=True, editable=False, ) play = models.CharField( max_length=1024, - blank=True, default='', editable=False, ) role = models.CharField( # FIXME: Determine from callback or task name. max_length=1024, - blank=True, default='', editable=False, ) task = models.CharField( max_length=1024, - blank=True, default='', editable=False, ) parent = models.ForeignKey( 'self', related_name='children', - blank=True, null=True, default=None, on_delete=models.SET_NULL, @@ -953,6 +948,8 @@ if getattr(settings, 'UNIFIED_JOBS_STEP') == 0: 'Job', related_name='job_events', on_delete=models.CASCADE, + null=True, + default=None, editable=False, ) new_job = models.ForeignKey( diff --git a/awx/main/models/organization.py b/awx/main/models/organization.py index 764187160f..75dba9d9ee 100644 --- a/awx/main/models/organization.py +++ b/awx/main/models/organization.py @@ -349,6 +349,13 @@ class Credential(CommonModelNameNotUnique): verbose_name=_('SSH private key'), help_text=_('RSA or DSA private key to be used instead of password.'), ) + ssh_key_path = models.CharField( + max_length=1024, + blank=True, + default='', + verbose_name=_('SSH key path'), + help_text=_('Path to SSH private key file.'), + ) ssh_key_unlock = models.CharField( max_length=1024, blank=True, @@ -369,6 +376,12 @@ class Credential(CommonModelNameNotUnique): default='', help_text=_('Sudo password (or "ASK" to prompt the user).'), ) + vault_password = models.CharField( + max_length=1024, + blank=True, + default='', + help_text=_('Vault password (or "ASK" to prompt the user).'), + ) @property def needs_password(self): @@ -377,7 +390,7 @@ class Credential(CommonModelNameNotUnique): @property def needs_ssh_key_unlock(self): return self.kind == 'ssh' and self.ssh_key_unlock == 'ASK' and \ - 'ENCRYPTED' in decrypt_field(self, 'ssh_key_data') + 'ENCRYPTED' in decrypt_field(self, 'ssh_key_data') # FIXME: Support ssh_key_path @property def needs_sudo_password(self): diff --git a/awx/main/models/projects.py b/awx/main/models/projects.py index 3eb7926ed7..5b6b923cf1 100644 --- a/awx/main/models/projects.py +++ b/awx/main/models/projects.py @@ -102,6 +102,7 @@ class ProjectOptions(models.Model): blank=True, null=True, default=None, + on_delete=models.SET_NULL, ) def clean_scm_type(self): @@ -331,6 +332,7 @@ if getattr(settings, 'UNIFIED_JOBS_STEP') == 0: default=None, editable=False, related_name='project_as_current_update+', + on_delete=models.SET_NULL, ) last_update = models.ForeignKey( 'ProjectUpdate', @@ -338,6 +340,7 @@ if getattr(settings, 'UNIFIED_JOBS_STEP') == 0: default=None, editable=False, related_name='project_as_last_update+', + on_delete=models.SET_NULL, ) last_update_failed = models.BooleanField( default=False, diff --git a/awx/main/models/schedules.py b/awx/main/models/schedules.py index 06da1ecdfe..d22648b520 100644 --- a/awx/main/models/schedules.py +++ b/awx/main/models/schedules.py @@ -24,22 +24,30 @@ class Schedule(CommonModel): objects = ScheduleManager() - job_template = models.ForeignKey( + unified_job_template = models.ForeignKey( 'UnifiedJobTemplate', related_name='schedules', on_delete=models.CASCADE, ) + enabled = models.BooleanField( + default=True, + ) dtstart = models.DateTimeField( ) dtend = models.DateTimeField( null=True, default=None, - editable=False + editable=False, ) rrule = models.CharField( max_length=255, ) + next_run = models.DateTimeField( + null=True, + default=None, + editable=False, + ) def save(self, *args, **kwargs): super(Schedule, self).save(*args, **kwargs) diff --git a/awx/main/models/unified_jobs.py b/awx/main/models/unified_jobs.py index db279348dd..9add8f69f2 100644 --- a/awx/main/models/unified_jobs.py +++ b/awx/main/models/unified_jobs.py @@ -72,6 +72,7 @@ class UnifiedJobTemplate(PolymorphicModel, CommonModelNameNotUnique): default=None, editable=False, related_name='%(class)s_as_current_job+', + on_delete=models.SET_NULL, ) last_job = models.ForeignKey( # alias for last_update 'UnifiedJob', @@ -79,6 +80,7 @@ class UnifiedJobTemplate(PolymorphicModel, CommonModelNameNotUnique): default=None, editable=False, related_name='%(class)s_as_last_job+', + on_delete=models.SET_NULL, ) last_job_failed = models.BooleanField( # alias for last_update_failed default=False, @@ -97,11 +99,19 @@ class UnifiedJobTemplate(PolymorphicModel, CommonModelNameNotUnique): # max_length=32, # choices=[], #) - next_job_run = models.DateTimeField( # FIXME: Calculate from schedule. + next_job_run = models.DateTimeField( # FIXME: Calculate from schedules. null=True, default=None, editable=False, ) + next_schedule = models.ForeignKey( # Schedule entry responsible for next_job_run. + 'Schedule', + null=True, + default=None, + editable=False, + related_name='%(class)s_as_next_schedule+', + on_delete=models.SET_NULL, + ) status = models.CharField( max_length=32, choices=STATUS_CHOICES, @@ -156,17 +166,8 @@ class UnifiedJobTemplate(PolymorphicModel, CommonModelNameNotUnique): def _set_status_and_last_job_run(self, save=True): status = self._get_current_status() last_job_run = self._get_last_job_run() - # Update values if changed. - update_fields = [] - if self.status != status: - self.status = status - update_fields.append('status') - if self.last_job_run != last_job_run: - self.last_job_run = last_job_run - update_fields.append('last_job_run') - if save and update_fields: - self.save(update_fields=update_fields) - return update_fields + return self.update_fields(status=status, last_job_run=last_job_run, + save=save) def _can_update(self): # Override in subclasses as needed. @@ -212,7 +213,7 @@ class UnifiedJobTemplate(PolymorphicModel, CommonModelNameNotUnique): return unified_job -class UnifiedJob(PolymorphicModel, PrimordialModel): +class UnifiedJob(PolymorphicModel, CommonModelNameNotUnique): ''' Concrete base class for unified job run by the task engine. ''' @@ -238,6 +239,7 @@ class UnifiedJob(PolymorphicModel, PrimordialModel): default=None, editable=False, related_name='%(class)s_unified_jobs', + on_delete=models.SET_NULL, ) launch_type = models.CharField( max_length=20, @@ -245,16 +247,17 @@ class UnifiedJob(PolymorphicModel, PrimordialModel): default='manual', editable=False, ) - schedule = models.ForeignKey( + schedule = models.ForeignKey( # Which schedule entry was responsible for starting this job. 'Schedule', null=True, default=None, editable=False, + on_delete=models.SET_NULL, ) - depends_on = models.ManyToManyField( + dependent_jobs = models.ManyToManyField( 'self', editable=False, - related_name='%(class)s_blocked_by+', + related_name='%(class)s_blocked_jobs+', ) cancel_flag = models.BooleanField( blank=True,