1
0
mirror of https://github.com/ansible/awx.git synced 2024-10-31 23:51:09 +03:00

Merge branch 'release_3.0.1' into stable

This commit is contained in:
James Laska 2016-07-29 11:31:50 -04:00
commit 4e93475be1
24 changed files with 138 additions and 195 deletions

View File

@ -5,7 +5,7 @@ import os
import sys
import warnings
__version__ = '3.0.0'
__version__ = '3.0.1'
__all__ = ['__version__']

View File

@ -1573,6 +1573,7 @@ class InventoryScanJobTemplateList(SubListAPIView):
class HostList(ListCreateAPIView):
always_allow_superuser = False
model = Host
serializer_class = HostSerializer

View File

@ -245,16 +245,18 @@ class UserAccess(BaseAccess):
def can_add(self, data):
if data is not None and 'is_superuser' in data:
if to_python_boolean(data['is_superuser'], allow_none=True) and not self.user.is_superuser:
if data is not None and ('is_superuser' in data or 'is_system_auditor' in data):
if (to_python_boolean(data.get('is_superuser', 'false'), allow_none=True) or
to_python_boolean(data.get('is_system_auditor', 'false'), allow_none=True)) and not self.user.is_superuser:
return False
if self.user.is_superuser:
return True
return Organization.accessible_objects(self.user, 'admin_role').exists()
def can_change(self, obj, data):
if data is not None and 'is_superuser' in data:
if to_python_boolean(data['is_superuser'], allow_none=True) and not self.user.is_superuser:
if data is not None and ('is_superuser' in data or 'is_system_auditor' in data):
if (to_python_boolean(data.get('is_superuser', 'false'), allow_none=True) or
to_python_boolean(data.get('is_system_auditor', 'false'), allow_none=True)) and not self.user.is_superuser:
return False
# A user can be changed if they are themselves, or by org admins or
# superusers. Change permission implies changing only certain fields
@ -720,18 +722,25 @@ class TeamAccess(BaseAccess):
def can_attach(self, obj, sub_obj, relationship, *args, **kwargs):
"""Reverse obj and sub_obj, defer to RoleAccess if this is an assignment
of a resource role to the team."""
if isinstance(sub_obj, Role) and isinstance(sub_obj.content_object, ResourceMixin):
role_access = RoleAccess(self.user)
return role_access.can_attach(sub_obj, obj, 'member_role.parents',
*args, **kwargs)
if isinstance(sub_obj, Role):
if sub_obj.content_object is None:
raise PermissionDenied("The {} role cannot be assigned to a team".format(sub_obj.name))
elif isinstance(sub_obj.content_object, User):
raise PermissionDenied("The admin_role for a User cannot be assigned to a team")
if isinstance(sub_obj.content_object, ResourceMixin):
role_access = RoleAccess(self.user)
return role_access.can_attach(sub_obj, obj, 'member_role.parents',
*args, **kwargs)
return super(TeamAccess, self).can_attach(obj, sub_obj, relationship,
*args, **kwargs)
def can_unattach(self, obj, sub_obj, relationship, *args, **kwargs):
if isinstance(sub_obj, Role) and isinstance(sub_obj.content_object, ResourceMixin):
role_access = RoleAccess(self.user)
return role_access.can_unattach(sub_obj, obj, 'member_role.parents',
*args, **kwargs)
if isinstance(sub_obj, Role):
if isinstance(sub_obj.content_object, ResourceMixin):
role_access = RoleAccess(self.user)
return role_access.can_unattach(sub_obj, obj, 'member_role.parents',
*args, **kwargs)
return super(TeamAccess, self).can_unattach(obj, sub_obj, relationship,
*args, **kwargs)
@ -906,8 +915,7 @@ class JobTemplateAccess(BaseAccess):
project = get_value(Project, 'project')
if 'job_type' in data and data['job_type'] == PERM_INVENTORY_SCAN:
if inventory:
org = inventory.organization
accessible = self.user in org.admin_role
accessible = self.user in inventory.use_role
else:
accessible = False
if not project and accessible:
@ -979,7 +987,8 @@ class JobTemplateAccess(BaseAccess):
for k, v in data.items():
if hasattr(obj, k) and getattr(obj, k) != v:
if k not in field_whitelist and v != getattr(obj, '%s_id' % k, None):
if k not in field_whitelist and v != getattr(obj, '%s_id' % k, None) \
and not (hasattr(obj, '%s_id' % k) and getattr(obj, '%s_id' % k) is None and v == ''): # Equate '' to None in the case of foreign keys
return False
return True
@ -1681,8 +1690,7 @@ class RoleAccess(BaseAccess):
if not check_user_access(self.user, sub_obj.__class__, 'read', sub_obj):
return False
if obj.object_id and \
isinstance(obj.content_object, ResourceMixin) and \
if isinstance(obj.content_object, ResourceMixin) and \
self.user in obj.content_object.admin_role:
return True
return False

View File

@ -481,6 +481,7 @@ def load_inventory_source(source, all_group=None, group_filter_re=None,
# Sanity check: We sanitize these module names for our API but Ansible proper doesn't follow
# good naming conventions
source = source.replace('azure.py', 'windows_azure.py')
source = source.replace('satellite6.py', 'foreman.py')
logger.debug('Analyzing type of source: %s', source)
original_all_group = all_group
if not os.path.exists(source):

View File

@ -4,9 +4,6 @@ from __future__ import unicode_literals
from django.db import migrations, models
from django.utils.timezone import now
from awx.api.license import feature_enabled
def create_system_job_templates(apps, schema_editor):
'''
Create default system job templates if not present. Create default schedules
@ -80,7 +77,7 @@ def create_system_job_templates(apps, schema_editor):
polymorphic_ctype=sjt_ct,
),
)
if created and feature_enabled('system_tracking', bypass_database=True):
if created:
sched = Schedule(
name='Cleanup Fact Schedule',
rrule='DTSTART:%s RRULE:FREQ=MONTHLY;INTERVAL=1;BYMONTHDAY=1' % now_str,

View File

@ -8,25 +8,8 @@ from collections import defaultdict
from awx.main.utils import getattrd
from awx.main.models.rbac import Role, batch_role_ancestor_rebuilding
logger = logging.getLogger(__name__)
logger = logging.getLogger('rbac_migrations')
def log_migration(wrapped):
'''setup the logging mechanism for each migration method
as it runs, Django resets this, so we use a decorator
to re-add the handler for each method.
'''
handler = logging.FileHandler("/tmp/tower_rbac_migrations.log", mode="a", encoding="UTF-8")
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
handler.setLevel(logging.DEBUG)
handler.setFormatter(formatter)
def wrapper(*args, **kwargs):
logger.handlers = []
logger.addHandler(handler)
return wrapped(*args, **kwargs)
return wrapper
@log_migration
def create_roles(apps, schema_editor):
'''
Implicit role creation happens in our post_save hook for all of our
@ -56,7 +39,6 @@ def create_roles(apps, schema_editor):
obj.save()
@log_migration
def migrate_users(apps, schema_editor):
User = apps.get_model('auth', "User")
Role = apps.get_model('main', "Role")
@ -89,7 +71,6 @@ def migrate_users(apps, schema_editor):
sa_role.members.add(user)
logger.warning(smart_text(u"added superuser: {}".format(user.username)))
@log_migration
def migrate_organization(apps, schema_editor):
Organization = apps.get_model('main', "Organization")
for org in Organization.objects.iterator():
@ -100,7 +81,6 @@ def migrate_organization(apps, schema_editor):
org.member_role.members.add(user)
logger.info(smart_text(u"added member: {}, {}".format(org.name, user.username)))
@log_migration
def migrate_team(apps, schema_editor):
Team = apps.get_model('main', 'Team')
for t in Team.objects.iterator():
@ -172,7 +152,6 @@ def _discover_credentials(instances, cred, orgfunc):
_update_credential_parents(org, cred)
@log_migration
def migrate_credential(apps, schema_editor):
Credential = apps.get_model('main', "Credential")
JobTemplate = apps.get_model('main', 'JobTemplate')
@ -180,7 +159,7 @@ def migrate_credential(apps, schema_editor):
InventorySource = apps.get_model('main', 'InventorySource')
for cred in Credential.objects.iterator():
results = [x for x in JobTemplate.objects.filter(Q(credential=cred) | Q(cloud_credential=cred)).all()] + \
results = [x for x in JobTemplate.objects.filter(Q(credential=cred) | Q(cloud_credential=cred), inventory__isnull=False).all()] + \
[x for x in InventorySource.objects.filter(credential=cred).all()]
if cred.deprecated_team is not None and results:
if len(results) == 1:
@ -210,7 +189,6 @@ def migrate_credential(apps, schema_editor):
logger.warning(smart_text(u"orphaned credential found Credential(name={}, kind={}, host={}), superuser only".format(cred.name, cred.kind, cred.host, )))
@log_migration
def migrate_inventory(apps, schema_editor):
Inventory = apps.get_model('main', 'Inventory')
Permission = apps.get_model('main', 'Permission')
@ -254,7 +232,6 @@ def migrate_inventory(apps, schema_editor):
execrole.members.add(perm.user)
logger.info(smart_text(u'added User({}) access to Inventory({})'.format(perm.user.username, inventory.name)))
@log_migration
def migrate_projects(apps, schema_editor):
'''
I can see projects when:
@ -368,7 +345,6 @@ def migrate_projects(apps, schema_editor):
@log_migration
def migrate_job_templates(apps, schema_editor):
'''
NOTE: This must be run after orgs, inventory, projects, credential, and
@ -420,6 +396,11 @@ def migrate_job_templates(apps, schema_editor):
jt_queryset = JobTemplate.objects.select_related('inventory', 'project', 'inventory__organization', 'execute_role')
for jt in jt_queryset.iterator():
if jt.inventory is None:
# If inventory is None, then only system admins and org admins can
# do anything with the JT in 2.4
continue
jt_permission_qs = Permission.objects.filter(
inventory=jt.inventory,
project=jt.project,
@ -494,7 +475,6 @@ def migrate_job_templates(apps, schema_editor):
@log_migration
def rebuild_role_hierarchy(apps, schema_editor):
logger.info('Computing role roots..')
start = time()

View File

@ -9,25 +9,8 @@ from awx.fact.utils.dbtransform import KeyTransform
from mongoengine.connection import ConnectionError
from pymongo.errors import OperationFailure
logger = logging.getLogger(__name__)
logger = logging.getLogger('system_tracking_migrations')
def log_migration(wrapped):
'''setup the logging mechanism for each migration method
as it runs, Django resets this, so we use a decorator
to re-add the handler for each method.
'''
handler = logging.FileHandler("/tmp/tower_system_tracking_migrations.log", mode="a", encoding="UTF-8")
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
handler.setLevel(logging.DEBUG)
handler.setFormatter(formatter)
def wrapper(*args, **kwargs):
logger.handlers = []
logger.addHandler(handler)
return wrapped(*args, **kwargs)
return wrapper
@log_migration
def migrate_facts(apps, schema_editor):
Fact = apps.get_model('main', "Fact")
Host = apps.get_model('main', "Host")
@ -52,7 +35,7 @@ def migrate_facts(apps, schema_editor):
migrated_count = 0
not_migrated_count = 0
transform = KeyTransform([('.', '\uff0E'), ('$', '\uff04')])
for factver in FactVersion.objects.all():
for factver in FactVersion.objects.all().no_cache():
try:
host = Host.objects.only('id').get(inventory__id=factver.host.inventory_id, name=factver.host.hostname)
fact_obj = transform.replace_outgoing(factver.fact)

View File

@ -2,25 +2,8 @@
import logging
from django.utils.encoding import smart_text
logger = logging.getLogger(__name__)
logger = logging.getLogger('rbac_migrations')
def log_migration(wrapped):
'''setup the logging mechanism for each migration method
as it runs, Django resets this, so we use a decorator
to re-add the handler for each method.
'''
handler = logging.FileHandler("/tmp/tower_rbac_migrations.log", mode="a", encoding="UTF-8")
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
handler.setLevel(logging.DEBUG)
handler.setFormatter(formatter)
def wrapper(*args, **kwargs):
logger.handlers = []
logger.addHandler(handler)
return wrapped(*args, **kwargs)
return wrapper
@log_migration
def migrate_team(apps, schema_editor):
'''If an orphan team exists that is still active, delete it.'''
Team = apps.get_model('main', 'Team')

View File

@ -873,7 +873,7 @@ class UnifiedJob(PolymorphicModel, PasswordFieldsModel, CommonModelNameNotUnique
if not self.cancel_flag:
self.cancel_flag = True
cancel_fields = ['cancel_flag']
if self.status in ('pending', 'waiting'):
if self.status in ('pending', 'waiting', 'new'):
self.status = 'canceled'
cancel_fields.append('status')
self.save(update_fields=cancel_fields)

View File

@ -3,7 +3,6 @@
import logging
import requests
import json
from django.utils.encoding import smart_text
@ -32,7 +31,7 @@ class WebhookBackend(TowerBaseEmailBackend):
self.headers['User-Agent'] = "Tower {}".format(get_awx_version())
for m in messages:
r = requests.post("{}".format(m.recipients()[0]),
data=json.dumps(m.body),
json=m.body,
headers=self.headers)
if r.status_code >= 400:
logger.error(smart_text("Error sending notification webhook: {}".format(r.text)))

View File

@ -47,7 +47,6 @@ from django.contrib.auth.models import User
from awx.main.constants import CLOUD_PROVIDERS
from awx.main.models import * # noqa
from awx.main.models import UnifiedJob
from awx.main.models.label import Label
from awx.main.queue import FifoQueue
from awx.main.conf import tower_settings
from awx.main.task_engine import TaskSerializer, TASK_TIMEOUT_INTERVAL
@ -123,13 +122,6 @@ def run_administrative_checks(self):
tower_admin_emails,
fail_silently=True)
@task(bind=True)
def run_label_cleanup(self):
qs = Label.get_orphaned_labels()
labels_count = qs.count()
qs.delete()
return labels_count
@task(bind=True)
def cleanup_authtokens(self):
AuthToken.objects.filter(expires__lt=now()).delete()
@ -1307,9 +1299,11 @@ class RunInventoryUpdate(BaseTask):
cp.set(section, 'password', decrypt_field(credential, 'password'))
section = 'ansible'
cp.add_section(section)
cp.set(section, 'group_patterns', '["{app}-{tier}-{color}", "{app}-{color}", "{app}", "{tier}"]')
section = 'cache'
cp.add_section(section)
cp.set(section, 'path', '/tmp')
cp.set(section, 'max_age', '0')

View File

@ -12,7 +12,7 @@ def mock_feature_enabled(feature, bypass_database=None):
@pytest.fixture
def role():
return Role.objects.create()
return Role.objects.create(role_field='admin_role')
#
@ -210,33 +210,33 @@ def test_get_teams_roles_list(get, team, organization, admin):
@pytest.mark.django_db
def test_add_role_to_teams(team, role, post, admin):
assert team.member_role.children.filter(id=role.id).count() == 0
def test_add_role_to_teams(team, post, admin):
assert team.member_role.children.filter(id=team.member_role.id).count() == 0
url = reverse('api:team_roles_list', args=(team.id,))
response = post(url, {'id': role.id}, admin)
response = post(url, {'id': team.member_role.id}, admin)
assert response.status_code == 204
assert team.member_role.children.filter(id=role.id).count() == 1
assert team.member_role.children.filter(id=team.member_role.id).count() == 1
response = post(url, {'id': role.id}, admin)
response = post(url, {'id': team.member_role.id}, admin)
assert response.status_code == 204
assert team.member_role.children.filter(id=role.id).count() == 1
assert team.member_role.children.filter(id=team.member_role.id).count() == 1
response = post(url, {}, admin)
assert response.status_code == 400
assert team.member_role.children.filter(id=role.id).count() == 1
assert team.member_role.children.filter(id=team.member_role.id).count() == 1
@pytest.mark.django_db
def test_remove_role_from_teams(team, role, post, admin):
assert team.member_role.children.filter(id=role.id).count() == 0
def test_remove_role_from_teams(team, post, admin):
assert team.member_role.children.filter(id=team.member_role.id).count() == 0
url = reverse('api:team_roles_list', args=(team.id,))
response = post(url, {'id': role.id}, admin)
response = post(url, {'id': team.member_role.id}, admin)
assert response.status_code == 204
assert team.member_role.children.filter(id=role.id).count() == 1
assert team.member_role.children.filter(id=team.member_role.id).count() == 1
response = post(url, {'disassociate': role.id, 'id': role.id}, admin)
response = post(url, {'disassociate': team.member_role.id, 'id': team.member_role.id}, admin)
assert response.status_code == 204
assert team.member_role.children.filter(id=role.id).count() == 0
assert team.member_role.children.filter(id=team.member_role.id).count() == 0

View File

@ -10,17 +10,17 @@ def test_team_attach_unattach(team, user):
access = TeamAccess(u)
team.member_role.members.add(u)
assert not access.can_attach(team, u.admin_role, 'member_role.children', None)
assert not access.can_unattach(team, u.admin_role, 'member_role.children')
assert not access.can_attach(team, team.member_role, 'member_role.children', None)
assert not access.can_unattach(team, team.member_role, 'member_role.children')
team.admin_role.members.add(u)
assert access.can_attach(team, u.admin_role, 'member_role.children', None)
assert access.can_unattach(team, u.admin_role, 'member_role.children')
assert access.can_attach(team, team.member_role, 'member_role.children', None)
assert access.can_unattach(team, team.member_role, 'member_role.children')
u2 = user('non-member', False)
access = TeamAccess(u2)
assert not access.can_attach(team, u2.admin_role, 'member_role.children', None)
assert not access.can_unattach(team, u2.admin_role, 'member_role.chidlren')
assert not access.can_attach(team, team.member_role, 'member_role.children', None)
assert not access.can_unattach(team, team.member_role, 'member_role.chidlren')
@pytest.mark.django_db
def test_team_access_superuser(team, user):

View File

@ -75,3 +75,16 @@ def test_org_user_removed(user, organization):
organization.member_role.members.remove(member)
assert admin not in member.admin_role
@pytest.mark.django_db
def test_org_admin_create_sys_auditor(org_admin):
access = UserAccess(org_admin)
assert not access.can_add(data=dict(
username='new_user', password="pa$$sowrd", email="asdf@redhat.com",
is_system_auditor='true'))
@pytest.mark.django_db
def test_org_admin_edit_sys_auditor(org_admin, alice, organization):
organization.member_role.members.add(alice)
access = UserAccess(org_admin)
assert not access.can_change(obj=alice, data=dict(is_system_auditor='true'))

View File

@ -4,7 +4,6 @@ from django.conf import settings
from datetime import timedelta
@pytest.mark.parametrize("job_name,function_path", [
('label_cleanup', 'awx.main.tasks.run_label_cleanup'),
('admin_checks', 'awx.main.tasks.run_administrative_checks'),
('tower_scheduler', 'awx.main.tasks.tower_periodic_scheduler'),
])

View File

@ -7,7 +7,6 @@ from awx.main.models import (
)
from awx.main.tasks import (
run_label_cleanup,
send_notifications,
run_administrative_checks,
)
@ -21,16 +20,6 @@ def apply_patches(_patches):
yield
[p.stop() for p in _patches]
def test_run_label_cleanup(mocker):
qs = mocker.Mock(**{'count.return_value': 3, 'delete.return_value': None})
mock_label = mocker.patch('awx.main.models.label.Label.get_orphaned_labels',return_value=qs)
ret = run_label_cleanup()
mock_label.assert_called_with()
qs.delete.assert_called_with()
assert 3 == ret
def test_send_notifications_not_list():
with pytest.raises(TypeError):
send_notifications(None)

0
awx/plugins/inventory/cloudforms.py Normal file → Executable file
View File

3
awx/plugins/inventory/foreman.py Normal file → Executable file
View File

@ -1,9 +1,8 @@
#!/usr/bin/python
# vim: set fileencoding=utf-8 :
#
# NOTE FOR TOWER: change foreman_ to sattelite_ for the group prefix
#
# vim: set fileencoding=utf-8 :
#
# Copyright (C) 2016 Guido Günther <agx@sigxcpu.org>
#
# This script is free software: you can redistribute it and/or modify

View File

@ -345,10 +345,6 @@ CELERYBEAT_SCHEDULE = {
'task': 'awx.main.tasks.run_administrative_checks',
'schedule': timedelta(days=30)
},
'label_cleanup': {
'task': 'awx.main.tasks.run_label_cleanup',
'schedule': timedelta(days=7)
},
'authtoken_cleanup': {
'task': 'awx.main.tasks.cleanup_authtokens',
'schedule': timedelta(days=30)
@ -676,6 +672,16 @@ OPENSTACK_HOST_FILTER = r'^.+$'
OPENSTACK_EXCLUDE_EMPTY_GROUPS = True
OPENSTACK_INSTANCE_ID_VAR = 'openstack.id'
# ---------------------
# ----- Foreman -----
# ---------------------
SATELLITE6_ENABLED_VAR = 'foreman.enabled'
SATELLITE6_ENABLED_VALUE = 'true'
SATELLITE6_GROUP_FILTER = r'^.+$'
SATELLITE6_HOST_FILTER = r'^.+$'
SATELLITE6_EXCLUDE_EMPTY_GROUPS = True
SATELLITE6_INSTANCE_ID_VAR = 'foreman.id'
# ---------------------
# -- Activity Stream --
# ---------------------
@ -941,7 +947,34 @@ LOGGING = {
'maxBytes': 1024 * 1024 * 5, # 5 MB
'backupCount': 5,
'formatter':'simple',
}
},
'fact_receiver': {
'level': 'WARNING',
'class':'logging.handlers.RotatingFileHandler',
'filters': ['require_debug_false'],
'filename': os.path.join(LOG_ROOT, 'fact_receiver.log'),
'maxBytes': 1024 * 1024 * 5, # 5 MB
'backupCount': 5,
'formatter':'simple',
},
'system_tracking_migrations': {
'level': 'WARNING',
'class':'logging.handlers.RotatingFileHandler',
'filters': ['require_debug_false'],
'filename': os.path.join(LOG_ROOT, 'tower_system_tracking_migrations.log'),
'maxBytes': 1024 * 1024 * 5, # 5 MB
'backupCount': 5,
'formatter':'simple',
},
'rbac_migrations': {
'level': 'WARNING',
'class':'logging.handlers.RotatingFileHandler',
'filters': ['require_debug_false'],
'filename': os.path.join(LOG_ROOT, 'tower_rbac_migrations.log'),
'maxBytes': 1024 * 1024 * 5, # 5 MB
'backupCount': 5,
'formatter':'simple',
},
},
'loggers': {
'django': {
@ -1000,6 +1033,14 @@ LOGGING = {
'handlers': ['console', 'file', 'tower_warnings'],
'level': 'DEBUG',
},
'system_tracking_migrations': {
'handlers': ['console', 'file', 'tower_warnings'],
'level': 'DEBUG',
},
'rbac_migrations': {
'handlers': ['console', 'file', 'tower_warnings'],
'level': 'DEBUG',
},
}
}

View File

@ -49,56 +49,13 @@ ANSIBLE_VENV_PATH = "/var/lib/awx/venv/ansible"
TOWER_USE_VENV = True
TOWER_VENV_PATH = "/var/lib/awx/venv/tower"
LOGGING['handlers']['tower_warnings'] = {
'level': 'WARNING',
'class':'logging.handlers.RotatingFileHandler',
'filters': ['require_debug_false'],
'filename': '/var/log/tower/tower.log',
'maxBytes': 1024 * 1024 * 5, # 5 MB
'backupCount': 5,
'formatter':'simple',
}
LOGGING['handlers']['callback_receiver'] = {
'level': 'WARNING',
'class':'logging.handlers.RotatingFileHandler',
'filters': ['require_debug_false'],
'filename': '/var/log/tower/callback_receiver.log',
'maxBytes': 1024 * 1024 * 5, # 5 MB
'backupCount': 5,
'formatter':'simple',
}
LOGGING['handlers']['socketio_service'] = {
'level': 'WARNING',
'class':'logging.handlers.RotatingFileHandler',
'filters': ['require_debug_false'],
'filename': '/var/log/tower/socketio_service.log',
'maxBytes': 1024 * 1024 * 5, # 5 MB
'backupCount': 5,
'formatter':'simple',
}
LOGGING['handlers']['task_system'] = {
'level': 'INFO',
'class':'logging.handlers.RotatingFileHandler',
'filters': ['require_debug_false'],
'filename': '/var/log/tower/task_system.log',
'maxBytes': 1024 * 1024 * 5, # 5 MB
'backupCount': 5,
'formatter':'simple',
}
LOGGING['handlers']['fact_receiver'] = {
'level': 'WARNING',
'class':'logging.handlers.RotatingFileHandler',
'filters': ['require_debug_false'],
'filename': '/var/log/tower/fact_receiver.log',
'maxBytes': 1024 * 1024 * 5, # 5 MB
'backupCount': 5,
'formatter':'simple',
}
LOGGING['handlers']['tower_warnings']['filename'] = '/var/log/tower/tower.log'
LOGGING['handlers']['callback_receiver']['filename'] = '/var/log/tower/callback_receiver.log'
LOGGING['handlers']['socketio_service']['filename'] = '/var/log/tower/socketio_service.log'
LOGGING['handlers']['task_system']['filename'] = '/var/log/tower/task_system.log'
LOGGING['handlers']['fact_receiver']['filename'] = '/var/log/tower/fact_receiver.log'
LOGGING['handlers']['system_tracking_migrations']['filename'] = '/var/log/tower/tower_system_tracking_migrations.log'
LOGGING['handlers']['rbac_migrations']['filename'] = '/var/log/tower/tower_rbac_migrations.log'
# Load settings from any .py files in the global conf.d directory specified in
# the environment, defaulting to /etc/tower/conf.d/.

View File

@ -872,7 +872,7 @@ var tower = angular.module('Tower', [
} else {
var lastUser = $cookieStore.get('current_user'),
timestammp = Store('sessionTime');
if(lastUser && lastUser.id && timestammp && timestammp[lastUser.id]){
if(lastUser && lastUser.id && timestammp && timestammp[lastUser.id] && timestammp[lastUser.id].loggedIn){
var stime = timestammp[lastUser.id].time,
now = new Date().getTime();
if ((stime - now) <= 0) {

View File

@ -67,7 +67,7 @@ export function JobsListController ($rootScope, $log, $scope, $compile, $statePa
list: AllJobsList,
id: 'active-jobs',
pageSize: 20,
url: GetBasePath('unified_jobs') + '?status__in=pending,waiting,running,completed,failed,successful,error,canceled&order_by=-finished',
url: GetBasePath('unified_jobs') + '?status__in=pending,waiting,running,completed,failed,successful,error,canceled,new&order_by=-finished',
searchParams: search_params,
spinner: false
});

View File

@ -1 +1,4 @@
import sys
if sys.prefix != '/var/lib/awx/venv/tower':
raise RuntimeError('Tower virtualenv not activated. Check WSGIPythonHome in Apache configuration.')
from awx.wsgi import application # NOQA

View File

@ -3,11 +3,6 @@
# All Rights Reserved
import os
import sys
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "awx.settings.development") # noqa
import django
django.setup() # noqa
# Python
from collections import defaultdict
@ -15,7 +10,7 @@ from optparse import make_option, OptionParser
# Django
import django
from django.utils.timezone import now
from django.contrib.auth.models import User
from django.db import transaction
@ -23,7 +18,8 @@ from django.db import transaction
# awx
from awx.main.models import * # noqa
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "awx.settings.development") # noqa
django.setup() # noqa
option_list = [