Commit 9c6fd5e3 by Szeberényi Imre

Merge branch 'python3.6' into 'master'

Python3.6

See merge request !1
parents 2e952ddb b504e3e6
......@@ -8,6 +8,11 @@ from django.core.exceptions import ImproperlyConfigured
from ..models import Level, AclBase
try:
# Python 2: "unicode" is built-in
unicode
except NameError:
unicode = str
def create_levels(app_config, verbosity=False, using=DEFAULT_DB_ALIAS,
**kwargs):
......@@ -21,8 +26,8 @@ def create_levels(app_config, verbosity=False, using=DEFAULT_DB_ALIAS,
app_models = [k for k in apps.get_models(app_config)
if AclBase in k.__bases__]
print "Creating levels for models: %s." % ", ".join(
[m.__name__ for m in app_models])
print(("Creating levels for models: %s." % ", ".join(
[m.__name__ for m in app_models])))
# This will hold the levels we're looking for as
# (content_type, (codename, name))
......@@ -61,10 +66,10 @@ def create_levels(app_config, verbosity=False, using=DEFAULT_DB_ALIAS,
]
Level.objects.using(using).bulk_create(levels)
if verbosity >= 2:
print("Adding levels [%s]." % ", ".join(unicode(l) for l in levels))
print("Searched: [%s]." % ", ".join(
unicode(l) for l in searched_levels))
print("All: [%s]." % ", ".join(unicode(l) for l in all_levels))
print(("Adding levels [%s]." % ", ".join(unicode(l) for l in levels)))
print(("Searched: [%s]." % ", ".join(
unicode(l) for l in searched_levels)))
print(("All: [%s]." % ", ".join(unicode(l) for l in all_levels)))
# set weights
for ctype, codename, weight in level_weights:
......
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
from django.conf import settings
......@@ -21,7 +21,7 @@ class Migration(migrations.Migration):
('name', models.CharField(max_length=50, verbose_name=b'name')),
('codename', models.CharField(max_length=100, verbose_name=b'codename')),
('weight', models.IntegerField(null=True, verbose_name=b'weight')),
('content_type', models.ForeignKey(to='contenttypes.ContentType')),
('content_type', models.ForeignKey(to='contenttypes.ContentType', on_delete=models.CASCADE)),
],
options={
},
......@@ -32,9 +32,9 @@ class Migration(migrations.Migration):
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('object_id', models.IntegerField()),
('content_type', models.ForeignKey(to='contenttypes.ContentType')),
('content_type', models.ForeignKey(to='contenttypes.ContentType', on_delete=models.CASCADE)),
('groups', models.ManyToManyField(to='auth.Group')),
('level', models.ForeignKey(to='acl.Level')),
('level', models.ForeignKey(to='acl.Level', on_delete=models.CASCADE)),
('users', models.ManyToManyField(to=settings.AUTH_USER_MODEL)),
],
options={
......
# Generated by Django 3.2.8 on 2021-11-02 13:31
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('acl', '0001_initial'),
]
operations = [
migrations.AlterField(
model_name='level',
name='codename',
field=models.CharField(max_length=100, verbose_name='codename'),
),
migrations.AlterField(
model_name='level',
name='name',
field=models.CharField(max_length=50, verbose_name='name'),
),
migrations.AlterField(
model_name='level',
name='weight',
field=models.IntegerField(null=True, verbose_name='weight'),
),
]
......@@ -25,6 +25,14 @@ from django.contrib.contenttypes.models import ContentType
from django.db.models import (
ManyToManyField, ForeignKey, CharField, Model, IntegerField, Q
)
from django.db import models
try:
# Python 2: "unicode" is built-in
unicode
except NameError:
unicode = str
logger = logging.getLogger(__name__)
......@@ -35,11 +43,11 @@ class Level(Model):
Instances are automatically populated based on AclBase."""
name = CharField('name', max_length=50)
content_type = ForeignKey(ContentType)
content_type = ForeignKey(ContentType, on_delete=models.CASCADE)
codename = CharField('codename', max_length=100)
weight = IntegerField('weight', null=True)
def __unicode__(self):
def __str__(self):
return "<%s/%s>" % (unicode(self.content_type), self.name)
class Meta:
......@@ -53,14 +61,14 @@ class Level(Model):
class ObjectLevel(Model):
"""Permission level for a specific object."""
level = ForeignKey(Level)
content_type = ForeignKey(ContentType)
level = ForeignKey(Level, on_delete=models.CASCADE)
content_type = ForeignKey(ContentType, on_delete=models.CASCADE)
object_id = IntegerField()
content_object = GenericForeignKey()
users = ManyToManyField(User)
groups = ManyToManyField(Group)
def __unicode__(self):
def __str__(self):
return "<%s: %s>" % (unicode(self.content_object), unicode(self.level))
class Meta:
......@@ -117,11 +125,11 @@ class AclBase(Model):
:type level: Level or str or unicode or NoneType
"""
logger.info('%s.set_user_level(%s, %s) called',
*[unicode(p) for p in [self, user, level]])
*[str(p) for p in [self, user, level]])
if level is None:
pk = None
else:
if isinstance(level, basestring):
if isinstance(level, str):
level = self.get_level_object(level)
if not self.object_level_set.filter(level_id=level.pk).exists():
self.object_level_set.create(level=level)
......@@ -147,7 +155,7 @@ class AclBase(Model):
if level is None:
pk = None
else:
if isinstance(level, basestring):
if isinstance(level, str):
level = self.get_level_object(level)
if not self.object_level_set.filter(level_id=level.pk).exists():
self.object_level_set.create(level=level)
......@@ -160,14 +168,13 @@ class AclBase(Model):
i.save()
def has_level(self, user, level, group_also=True):
logger.debug('%s.has_level(%s, %s, %s) called',
*[unicode(p) for p in [self, user, level, group_also]])
if user is None or not user.is_authenticated():
# logger.debug('%s.has_level(%s, %s, %s) called', *[unicode(p) for p in [self, user, level, group_also]])
if user is None or not user.is_authenticated:
return False
if getattr(user, 'is_superuser', False):
logger.debug('- superuser granted')
return True
if isinstance(level, basestring):
if isinstance(level, str):
level = self.get_level_object(level)
logger.debug("- level set by str: %s", unicode(level))
......@@ -182,7 +189,7 @@ class AclBase(Model):
return False
def get_users_with_level(self, **kwargs):
logger.debug('%s.get_users_with_level() called', unicode(self))
# logger.debug('%s.get_users_with_level() called', unicode(self))
object_levels = (self.object_level_set.filter(**kwargs).select_related(
'level').prefetch_related('users').all())
users = []
......@@ -194,7 +201,7 @@ class AclBase(Model):
return users
def get_groups_with_level(self):
logger.debug('%s.get_groups_with_level() called', unicode(self))
# logger.debug('%s.get_groups_with_level() called', unicode(self))
object_levels = (self.object_level_set.select_related(
'level').prefetch_related('groups').all())
groups = []
......@@ -209,16 +216,15 @@ class AclBase(Model):
def get_objects_with_level(cls, level, user,
group_also=True, owner_also=False,
disregard_superuser=False):
logger.debug('%s.get_objects_with_level(%s,%s) called',
unicode(cls), unicode(level), unicode(user))
if user is None or not user.is_authenticated():
# logger.debug('%s.get_objects_with_level(%s,%s) called', str(cls), unicode(level), unicode(user))
if user is None or not user.is_authenticated:
return cls.objects.none()
if getattr(user, 'is_superuser', False) and not disregard_superuser:
logger.debug('- superuser granted')
return cls.objects.all()
if isinstance(level, basestring):
if isinstance(level, str):
level = cls.get_level_object(level)
logger.debug("- level set by str: %s", unicode(level))
# logger.debug("- level set by str: %s", unicode(level))
ct = ContentType.objects.get_for_model(cls)
levelfilter = Q(users=user)
......@@ -234,7 +240,7 @@ class AclBase(Model):
@classmethod
def get_objects_with_group_level(cls, level, group):
if isinstance(level, basestring):
if isinstance(level, str):
level = cls.get_level_object(level)
ct = ContentType.objects.get_for_model(cls)
levelfilter = Q(groups=group)
......
......@@ -152,11 +152,11 @@ class AclUserTest(TestCase):
i1.set_level(self.u1, 'bravo')
i1.set_level(self.u2, 'charlie')
i2.set_level(self.u1, 'one')
i2.set_level(self.us, u'three')
i2.set_level(self.us, 'three')
res1 = i1.get_users_with_level()
self.assertEqual([(self.u1, u'bravo'), (self.u2, u'charlie')], res1)
self.assertEqual([(self.u1, 'bravo'), (self.u2, 'charlie')], res1)
res2 = i2.get_users_with_level()
self.assertEqual([(self.u1, u'one'), (self.us, u'three')], res2)
self.assertEqual([(self.u1, 'one'), (self.us, 'three')], res2)
def test_get_groups_with_level(self):
i1 = TestModel.objects.create(normal_field='Hello')
......@@ -164,16 +164,16 @@ class AclUserTest(TestCase):
i1.set_level(self.g1, 'bravo')
i1.set_level(self.u2, 'charlie')
i2.set_level(self.g1, 'one')
i2.set_level(self.us, u'three')
i2.set_level(self.us, 'three')
res1 = i1.get_groups_with_level()
self.assertEqual([(self.g1, u'bravo')], res1)
self.assertEqual([(self.g1, 'bravo')], res1)
res2 = i2.get_groups_with_level()
self.assertEqual([(self.g1, u'one')], res2)
self.assertEqual([(self.g1, 'one')], res2)
def test_object_level_unicode(self):
i1 = TestModel.objects.create(normal_field='Hello')
i1.set_level(self.g1, 'bravo')
unicode(ObjectLevel.objects.all()[0])
str(ObjectLevel.objects.all()[0])
def test_set_user_level_none(self):
i = TestModel.objects.create(normal_field='Hello')
......
CELERY_RESULT_BACKEND = 'amqp://'
CELERY_TASK_RESULT_EXPIRES = 300
CELERY_TIMEZONE = 'UTC'
CELERY_ENABLE_UTC = True
CELERY_ACCEPT_CONTENT = ['pickle', 'json', 'msgpack', 'yaml']
......@@ -14,8 +14,8 @@ def update_permissions_after_migration(sender, **kwargs):
from django.conf import settings
from django.apps import apps
from django.contrib.auth.management import create_permissions
create_permissions(sender, apps.get_models(), 2 if settings.DEBUG else 0)
v = 2 if settings.DEBUG else 0
create_permissions(sender, v, apps.get_models())
post_migrate.connect(update_permissions_after_migration)
......@@ -111,7 +111,7 @@ try:
except:
systz = None
TIME_ZONE = get_env_variable('DJANGO_TIME_ZONE', default=systz)
TIME_ZONE = 'UTC' #get_env_variable('DJANGO_TIME_ZONE', default=systz)
# See: https://docs.djangoproject.com/en/dev/ref/settings/#language-code
LANGUAGE_CODE = get_env_variable("DJANGO_LANGUAGE_CODE", "en")
......@@ -150,6 +150,19 @@ MEDIA_URL = get_env_variable('DJANGO_MEDIA_URL', default='/media/')
STATIC_ROOT = normpath(join(SITE_ROOT, 'static_collected'))
# See: https://docs.djangoproject.com/en/dev/ref/settings/#static-url
STATIC_URL = get_env_variable('DJANGO_STATIC_URL', default='/static_collected/')
# See: https://docs.djangoproject.com/en/dev/ref/contrib/staticfiles/#staticfiles-finders
STATICFILES_FINDERS = (
'django.contrib.staticfiles.finders.FileSystemFinder',
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
'pipeline.finders.PipelineFinder',
)
########## STATIC FILE CONFIGURATION
# See: https://docs.djangoproject.com/en/dev/ref/settings/#static-root
STATIC_ROOT = normpath(join(SITE_ROOT, 'static_collected'))
# See: https://docs.djangoproject.com/en/dev/ref/settings/#static-url
STATIC_URL = get_env_variable('DJANGO_STATIC_URL', default='/static/')
# See: https://docs.djangoproject.com/en/dev/ref/contrib/staticfiles/#staticfiles-finders
......@@ -165,7 +178,7 @@ p = normpath(join(SITE_ROOT, '../../site-circle/static'))
if exists(p):
STATICFILES_DIRS.append(p)
STATICFILES_STORAGE = 'pipeline.storage.PipelineCachedStorage'
STATICFILES_STORAGE = 'pipeline.storage.PipelineStorage'
PIPELINE = {
'COMPILERS' : ('pipeline.compilers.less.LessCompiler',),
......@@ -255,6 +268,8 @@ PIPELINE = {
}
DEFAULT_AUTO_FIELD = 'django.db.models.AutoField'
########## SECRET CONFIGURATION
# See: https://docs.djangoproject.com/en/dev/ref/settings/#secret-key
# Note: This key should only be used for development and testing.
......@@ -308,7 +323,7 @@ TEMPLATES = [{
########## MIDDLEWARE CONFIGURATION
# See: https://docs.djangoproject.com/en/dev/ref/settings/#middleware-classes
MIDDLEWARE_CLASSES = (
MIDDLEWARE = (
# Default Django middleware.
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
......@@ -333,7 +348,7 @@ DJANGO_APPS = (
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
#'django.contrib.sites',
'django.contrib.messages',
'django.contrib.staticfiles',
......@@ -355,7 +370,7 @@ THIRD_PARTY_APPS = (
'sizefield',
'taggit',
'statici18n',
'django_sshkey',
'simplesshkey',
'pipeline',
)
......@@ -407,10 +422,10 @@ LOGGING = {
'class': 'django.utils.log.AdminEmailHandler'
},
'syslog': {
'level': 'INFO',
'class': 'logging.handlers.SysLogHandler',
'formatter': 'simple',
'address': '/dev/log',
'level': 'INFO',
'class': 'logging.handlers.SysLogHandler',
'formatter': 'simple',
'address': '/var/run/syslog',
# 'socktype': SOCK_STREAM,
# 'address': ('host', '514'),
}
......@@ -529,8 +544,10 @@ if get_env_variable('DJANGO_SAML', 'FALSE') == 'TRUE':
LOGIN_REDIRECT_URL = "/"
AGENT_DIR = get_env_variable(
'DJANGO_AGENT_DIR', join(unicode(expanduser("~")), 'agent'))
'DJANGO_AGENT_DIR', join(str(expanduser("~")), 'agent'))
# AGENT_DIR is the root directory for the agent.
# The directory structure SHOULD be:
# /home/username/agent
......@@ -541,6 +558,8 @@ AGENT_DIR = get_env_variable(
# | +-- agent-win-%(version).exe
#
try:
git_env = {'GIT_DIR': join(join(AGENT_DIR, "agent-linux"), '.git')}
AGENT_VERSION = check_output(
......
......@@ -18,8 +18,7 @@
"""Development settings and globals."""
# flake8: noqa
from base import * # noqa
from .base import * # noqa
########## DEBUG CONFIGURATION
......@@ -54,19 +53,27 @@ EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
########## CACHE CONFIGURATION
# See: https://docs.djangoproject.com/en/dev/ref/settings/#caches
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',
'LOCATION': '127.0.0.1:11211',
}
}
# See: https://docs.djangoproject.com/en/dev/ref/settings/#caches
#CACHES = {
# 'default': {
# 'BACKEND': 'django.core.cache.backends.dummy.DummyCache',
# 'LOCATION': '127.0.0.1:11211',
# }
#}
########## END CACHE CONFIGURATION
########## ROSETTA CONFIGURATION
INSTALLED_APPS += (
'rosetta',
'template_debug',
)
########## END ROSETTA CONFIGURATION
......@@ -84,7 +91,7 @@ if get_env_variable('DJANGO_TOOLBAR', 'FALSE') == 'TRUE':
)
# https://github.com/django-debug-toolbar/django-debug-toolbar#installation
MIDDLEWARE_CLASSES += (
MIDDLEWARE += (
'debug_toolbar.middleware.DebugToolbarMiddleware',
)
......@@ -114,6 +121,8 @@ PIPELINE["COMPILERS"] = (
'dashboard.compilers.DummyLessCompiler',
)
ADMIN_ENABLED = True
ADMIN_ENABLED = False
TEMPLATE_DEBUG = True
ALLOWED_HOSTS = ['*']
......@@ -22,7 +22,7 @@
from os import environ
from sys import argv
from base import * # noqa
from .base import * # noqa
if 'runserver' in argv:
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTOCOL', 'https')
......@@ -66,7 +66,7 @@ SERVER_EMAIL = get_env_variable('SERVER_EMAIL', DEFAULT_FROM_EMAIL)
########## CACHE CONFIGURATION
# See: https://docs.djangoproject.com/en/dev/ref/settings/#caches
from urlparse import urlsplit
from urllib.parse import urlsplit
CACHES = {
'default': {
......
......@@ -20,10 +20,10 @@ from django.views.generic import TemplateView
from django.conf import settings
from django.contrib import admin
from django.core.urlresolvers import reverse
from django.urls import reverse
from django.shortcuts import redirect
from django.contrib.auth.views import (
password_reset_confirm, password_reset
PasswordResetView
)
......@@ -37,6 +37,7 @@ from firewall.views import add_blacklist_item
admin.autodiscover()
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^$', lambda x: redirect(reverse("dashboard.index"))),
url(r'^network/', include('network.urls')),
url(r'^blacklist-add/', add_blacklist_item),
......@@ -46,11 +47,11 @@ urlpatterns = [
# django/contrib/auth/urls.py (care when new version)
url((r'^accounts/reset/(?P<uidb64>[0-9A-Za-z_\-]+)/'
r'(?P<token>[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$'),
password_reset_confirm,
PasswordResetView,
{'set_password_form': CircleSetPasswordForm},
name='accounts.password_reset_confirm'
name='accounts.PasswordResetView'
),
url(r'^accounts/password/reset/$', password_reset,
url(r'^accounts/password/reset/$', PasswordResetView,
{'password_reset_form': CirclePasswordResetForm},
name="accounts.password-reset",
),
......@@ -75,18 +76,16 @@ urlpatterns = [
name="info.resize"),
]
if 'rosetta' in settings.INSTALLED_APPS:
urlpatterns += [
url(r'^rosetta/', include('rosetta.urls')),
]
if settings.ADMIN_ENABLED:
urlpatterns += [
url(r'^admin/', include(admin.site.urls)),
urlpatterns = [
url('admin/', admin.site.urls),
]
if get_env_variable('DJANGO_SAML', 'FALSE') == 'TRUE':
urlpatterns += [
url(r'^saml2/', include('djangosaml2.urls')),
......
......@@ -53,7 +53,7 @@ _application = get_wsgi_application()
def application(environ, start_response):
# copy DJANGO_* wsgi-env vars to process-env
for i in environ.keys():
for i in list(environ.keys()):
if i.startswith('DJANGO_'):
os.environ[i] = environ[i]
......
......@@ -27,15 +27,15 @@ logger = logging.getLogger(__name__)
class Saml2Backend(Saml2BackendBase):
u"""
"""
>>> b = Saml2Backend()
>>> b.clean_user_main_attribute(u'Ékezetes Enikő')
>>> b.clean_user_main_attribute('Ékezetes Enikő')
u'+00c9kezetes+0020Enik+0151'
>>> b.clean_user_main_attribute(u'Cé++')
>>> b.clean_user_main_attribute('Cé++')
u'C+00e9+002b+002b'
>>> b.clean_user_main_attribute(u'test')
>>> b.clean_user_main_attribute('test')
u'test'
>>> b.clean_user_main_attribute(u'3+4')
>>> b.clean_user_main_attribute('3+4')
u'3+002b4'
"""
def clean_user_main_attribute(self, main_attribute):
......@@ -45,7 +45,7 @@ class Saml2Backend(Saml2BackendBase):
if isinstance(main_attribute, str):
main_attribute = main_attribute.decode('UTF-8')
assert isinstance(main_attribute, unicode)
assert isinstance(main_attribute, str)
attr = re.sub(r'[^\w.@-]', replace, main_attribute)
max_length = settings.SAML_MAIN_ATTRIBUTE_MAX_LENGTH
if max_length > 0 and len(attr) > max_length:
......@@ -59,3 +59,4 @@ class Saml2Backend(Saml2BackendBase):
if attr == 'username':
value = self.clean_user_main_attribute(value)
return super(Saml2Backend, self)._set_attribute(obj, attr, value)
......@@ -22,7 +22,7 @@ import pyinotify
from django.core.management.base import BaseCommand
from django.conf import settings
STATIC_FILES = u'--include-path={}'.format(':'.join(settings.STATICFILES_DIRS))
STATIC_FILES = '--include-path={}'.format(':'.join(settings.STATICFILES_DIRS))
IGNORED_FOLDERS = ("static_collected", "bower_components", )
......@@ -35,16 +35,16 @@ class LessUtils(object):
def compile_less(less_pathname, css_pathname):
cmd = ["lessc", STATIC_FILES, less_pathname, css_pathname]
print("\n%s" % ("=" * 30))
print("Compiling: %s" % os.path.basename(less_pathname))
print(("\n%s" % ("=" * 30)))
print(("Compiling: %s" % os.path.basename(less_pathname)))
try:
subprocess.check_output(cmd)
except subprocess.CalledProcessError as e:
print(e.output)
print((e.output))
else:
print("Successfully compiled:\n%s\n->\n%s" % (
less_pathname, css_pathname))
print(("Successfully compiled:\n%s\n->\n%s" % (
less_pathname, css_pathname)))
@staticmethod
def initial_compile():
......@@ -96,7 +96,7 @@ class Command(BaseCommand):
# for first run compile everything
print("Initial LESS compiles")
LessUtils.initial_compile()
print("\n%s\n" % ("=" * 30))
print(("\n%s\n" % ("=" * 30)))
print("End of initial LESS compiles\n")
# after first run watch less files
......
......@@ -60,7 +60,7 @@ class Operation(object):
"""
self.subject = subject
def __unicode__(self):
def __str__(self):
return self.name
def __prelude(self, kwargs):
......@@ -106,7 +106,7 @@ class Operation(object):
if argspec.keywords is not None: # _operation takes ** args
arguments = allargs.copy()
else: # _operation doesn't take ** args
arguments = {k: v for (k, v) in allargs.iteritems()
arguments = {k: v for (k, v) in list(allargs.items())
if k in argspec.args}
arguments.update(auxargs)
......@@ -114,7 +114,7 @@ class Operation(object):
on_commit=self.on_commit) as act:
retval = self._operation(**arguments)
if (act.result is None and isinstance(
retval, (basestring, int, HumanReadableObject))):
retval, (str, int, HumanReadableObject))):
act.result = retval
return retval
......@@ -125,7 +125,7 @@ class Operation(object):
"""
raise NotImplementedError
def async(self, **kwargs):
def _async(self, **kwargs):
"""Execute the operation asynchronously.
Only a quick, preliminary check is ran before creating the associated
......@@ -254,7 +254,7 @@ class OperatedMixin(object):
:returns: A bound instance of an operation, or None if no matching
operation could be found.
"""
for op in getattr(self, operation_registry_name, {}).itervalues():
for op in getattr(self, operation_registry_name, {}).values():
if has_suffix(activity_code, op.get_activity_code_suffix()):
return op(self)
else:
......
......@@ -60,14 +60,14 @@ class TestHumanSortField(TestCase):
values = {(lambda s: s.isdigit(), "1234abc56"): ("1234", "abc", "56"),
(lambda s: s.isalpha(), "abc567"): ("abc", "567", ""),
(lambda s: s == "a", "aaababaa"): ("aaa", "b", "abaa"),
(lambda s: s == "a", u"aaababaa"): ("aaa", "b", "abaa"),
(lambda s: s == "a", "aaababaa"): ("aaa", "b", "abaa"),
}
for (pred, val), result in values.iteritems():
for (pred, val), result in list(values.items()):
a, b, c = HumanSortField._partition(deque(val), pred)
assert isinstance(c, deque)
c = ''.join(c)
# print "%s, %s => %s" % (val, str(pred), str((a, b, c)))
self.assertEquals((a, b, c), result)
self.assertEqual((a, b, c), result)
def test_get_normalized(self):
values = {("1234abc56", 4): "1234abc0056",
......@@ -76,12 +76,12 @@ class TestHumanSortField(TestCase):
("aa4ababaa", 2): "aa04ababaa",
("aa4aba24baa4", 4): "aa0004aba0024baa0004",
}
for (val, length), result in values.iteritems():
for (val, length), result in list(values.items()):
obj = MagicMock(spec=HumanSortField, maximum_number_length=length,
_partition=HumanSortField._partition)
test_result = HumanSortField.get_normalized_value(obj, val)
self.assertEquals(test_result, result)
self.assertEqual(test_result, result)
class ActivityContextTestCase(TestCase):
......@@ -91,13 +91,13 @@ class ActivityContextTestCase(TestCase):
def test_unicode(self):
act = MagicMock()
gen = activitycontextimpl(act)
gen.next()
next(gen)
with self.assertRaises(self.MyException):
gen.throw(self.MyException(u'test\xe1'))
gen.throw(self.MyException('test\xe1'))
def test_str(self):
act = MagicMock()
gen = activitycontextimpl(act)
gen.next()
next(gen)
with self.assertRaises(self.MyException):
gen.throw(self.MyException('test\xbe'))
......@@ -19,7 +19,7 @@ from sys import exc_info
import logging
from django.shortcuts import render_to_response
from django.shortcuts import render
from django.template import RequestContext
from .models import HumanReadableException
......@@ -45,17 +45,17 @@ def handler500(request):
logger.exception("unhandled exception")
ctx = get_context(request, exception)
try:
resp = render_to_response("500.html", ctx,
resp = render("500.html", ctx,
RequestContext(request).flatten())
except:
resp = render_to_response("500.html", ctx)
resp = render("500.html", ctx)
resp.status_code = 500
return resp
def handler403(request):
def handler403(request, *args, **argv):
cls, exception, traceback = exc_info()
ctx = get_context(request, exception)
resp = render_to_response("403.html", ctx)
resp = render("403.html", ctx)
resp.status_code = 403
return resp
return resp(request)
......@@ -22,7 +22,7 @@ from .models import Message
def notifications(request):
count = (request.user.notification_set.filter(status="new").count()
if request.user.is_authenticated() else None)
if request.user.is_authenticated else None)
return {
'NEW_NOTIFICATIONS_COUNT': count
}
......
......@@ -15,9 +15,9 @@
# You should have received a copy of the GNU General Public License along
# with CIRCLE. If not, see <http://www.gnu.org/licenses/>.
from __future__ import absolute_import
from urlparse import urlparse
from urllib.parse import urlparse
import os
import pyotp
......@@ -39,16 +39,16 @@ from django.contrib.auth.forms import UserCreationForm as OrgUserCreationForm
from django.contrib.auth.models import Permission
from django.contrib.auth.models import User, Group
from django.core.exceptions import PermissionDenied, ValidationError
from django.core.urlresolvers import reverse_lazy
from django.urls import reverse_lazy
from django.core.validators import URLValidator
from django.forms import ModelForm
from django.forms.widgets import TextInput, HiddenInput
from django.template.loader import render_to_string
from django.utils.html import escape, format_html
from django.utils.safestring import mark_safe
from django.utils.translation import string_concat
from django.utils.translation import ugettext_lazy
from django.utils.translation import ugettext_lazy as _
from django_sshkey.models import UserKey
from simplesshkey.models import UserKey
from sizefield.widgets import FileSizeWidget
from circle.settings.base import LANGUAGES, MAX_NODE_RAM, MAX_NODE_CPU_CORE
......@@ -62,7 +62,7 @@ from vm.models import (
from .models import Profile, GroupProfile, Message
from .validators import domain_validator
LANGUAGES_WITH_CODE = ((l[0], string_concat(l[1], " (", l[0], ")"))
LANGUAGES_WITH_CODE = ((l[0], ugettext_lazy(l[1], " (", l[0], ")"))
for l in LANGUAGES)
priority_choices = (
......@@ -73,6 +73,7 @@ priority_choices = (
)
class NoFormTagMixin(object):
@property
......@@ -131,7 +132,7 @@ class VmCustomizeForm(forms.Form):
)
cpu_priority = forms.ChoiceField(
priority_choices, widget=forms.Select(attrs={
choices=priority_choices, widget=forms.Select(attrs={
'class': "form-control input-tags cpu-priority-input",
})
)
......@@ -192,7 +193,7 @@ class VmCustomizeForm(forms.Form):
self.initial['customized'] = True
def _clean_fields(self):
for name, field in self.fields.items():
for name, field in list(self.fields.items()):
if name in self.allowed_fields:
value = field.widget.value_from_datadict(
self.data, self.files, self.add_prefix(name))
......@@ -265,7 +266,7 @@ class GroupImportForm(NoFormTagMixin, forms.Form):
os.path.basename(item) for item in exported_group_paths
]
self.choices = zip(exported_group_paths, exported_group_names)
self.choices = list(zip(exported_group_paths, exported_group_names))
self.fields["group_path"] = forms.ChoiceField(
label=_("Group to import"),
choices=self.choices
......@@ -518,7 +519,7 @@ class TemplateForm(forms.ModelForm):
min_value=128, max_value=MAX_NODE_RAM,
)
priority = forms.ChoiceField(priority_choices, widget=forms.Select(attrs={
priority = forms.ChoiceField(choices=priority_choices, widget=forms.Select(attrs={
'class': "form-control input-tags cpu-priority-input",
}))
......@@ -550,7 +551,7 @@ class TemplateForm(forms.ModelForm):
set(['raw_data']))
if self.user.is_superuser:
self.allowed_fields += ('raw_data',)
for name, field in self.fields.items():
for name, field in list(self.fields.items()):
if name not in self.allowed_fields:
field.widget.attrs['disabled'] = 'disabled'
......@@ -581,7 +582,7 @@ class TemplateForm(forms.ModelForm):
old = InstanceTemplate.objects.get(pk=self.instance.pk)
except InstanceTemplate.DoesNotExist:
old = None
for name, field in self.fields.items():
for name, field in list(self.fields.items()):
if name in self.allowed_fields:
value = field.widget.value_from_datadict(
self.data, self.files, self.add_prefix(name))
......@@ -723,7 +724,7 @@ class LeaseForm(forms.ModelForm):
Field('name'),
Field("suspend_interval_seconds", type="hidden", value="0"),
Field("delete_interval_seconds", type="hidden", value="0"),
HTML(string_concat("<label>", _("Suspend in"), "</label>")),
# HTML(ugettext_lazy("<label>", _("Suspend in"), "</label>")),
Div(
NumberField("suspend_hours", css_class="form-control"),
Div(
......@@ -747,7 +748,7 @@ class LeaseForm(forms.ModelForm):
),
css_class="input-group interval-input",
),
HTML(string_concat("<label>", _("Delete in"), "</label>")),
# HTML(ugettext_lazy("<label>", _("Delete in"), "</label>")),
Div(
NumberField("delete_hours", css_class="form-control"),
Div(
......@@ -824,7 +825,7 @@ class VmStateChangeForm(OperationForm):
"Forcibly interrupt all running activities."),
help_text=_("Set all activities to finished state, "
"but don't interrupt any tasks."))
new_state = forms.ChoiceField(Instance.STATUS, label=_(
new_state = forms.ChoiceField(widget=Instance.STATUS, label=_(
"New status"))
reset_node = forms.BooleanField(required=False, label=_("Reset node"))
......@@ -977,7 +978,7 @@ class VmImportDiskForm(OperationForm):
[f[0] for f in Disk.EXPORT_FORMATS]
)
disk_filenames = [os.path.basename(item) for item in disk_paths]
self.choices = zip(disk_paths, disk_filenames)
self.choices = list(zip(disk_paths, disk_filenames))
self.fields['name'] = forms.CharField(max_length=100, label=_('Name'))
self.fields['disk_path'] = forms.ChoiceField(label=_('Disk image'),
......@@ -1060,7 +1061,7 @@ class DeployChoiceField(forms.ModelChoiceField):
)
if subset:
missing_traits = ", ".join(map(lambda x: escape(x.name), subset))
missing_traits = ", ".join([escape(x.name) for x in subset])
label += _(" (missing_traits: %s)") % missing_traits
return mark_safe(label)
......@@ -1102,7 +1103,7 @@ class VmPortRemoveForm(OperationForm):
class VmPortAddForm(OperationForm):
port = forms.IntegerField(required=True, label=_('Port'),
min_value=1, max_value=65535)
proto = forms.ChoiceField((('tcp', 'tcp'), ('udp', 'udp')),
proto = forms.ChoiceField(initial=(('tcp', 'tcp'), ('udp', 'udp')),
required=True, label=_('Protocol'))
def __init__(self, *args, **kwargs):
......@@ -1302,7 +1303,7 @@ class TraitForm(forms.ModelForm):
class MyProfileForm(forms.ModelForm):
preferred_language = forms.ChoiceField(
LANGUAGES_WITH_CODE,
initial=LANGUAGES_WITH_CODE,
label=_("Preferred language"),
)
......@@ -1614,7 +1615,7 @@ class VmResourcesForm(forms.ModelForm):
min_value=128, max_value=MAX_NODE_RAM,
)
priority = forms.ChoiceField(priority_choices, widget=forms.Select(attrs={
priority = forms.ChoiceField(choices=priority_choices, widget=forms.Select(attrs={
'class': "form-control input-tags cpu-priority-input",
}))
......@@ -1623,7 +1624,7 @@ class VmResourcesForm(forms.ModelForm):
super(VmResourcesForm, self).__init__(*args, **kwargs)
if not self.can_edit:
for name, field in self.fields.items():
for name, field in list(self.fields.items()):
field.widget.attrs['disabled'] = "disabled"
class Meta:
......@@ -1651,7 +1652,7 @@ class VmListSearchForm(forms.Form):
'placeholder': _("Search...")
}))
stype = forms.ChoiceField(vm_search_choices, widget=forms.Select(attrs={
stype = forms.ChoiceField(initial=vm_search_choices, widget=forms.Select(attrs={
'class': "btn btn-default form-control input-tags",
'style': "min-width: 80px;",
}))
......@@ -1677,7 +1678,7 @@ class TemplateListSearchForm(forms.Form):
'placeholder': _("Search...")
}))
stype = forms.ChoiceField(vm_search_choices, widget=forms.Select(attrs={
stype = forms.ChoiceField(initial=vm_search_choices, widget=forms.Select(attrs={
'class': "btn btn-default input-tags",
}))
......@@ -1729,7 +1730,7 @@ class DiskForm(ModelForm):
def __init__(self, *args, **kwargs):
super(DiskForm, self).__init__(*args, **kwargs)
for k, v in self.fields.iteritems():
for k, v in list(self.fields.items()):
v.widget.attrs['readonly'] = True
self.fields['created'].initial = self.instance.created
self.fields['modified'].initial = self.instance.modified
......
......@@ -15,7 +15,7 @@
# You should have received a copy of the GNU General Public License along
# with CIRCLE. If not, see <http://www.gnu.org/licenses/>.
from __future__ import unicode_literals, absolute_import
import logging
......
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
import dashboard.validators
......@@ -25,9 +25,9 @@ class Migration(migrations.Migration):
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('access_method', models.CharField(help_text='Type of the remote access method.', max_length=10, verbose_name='access method', choices=[('nx', 'NX'), ('rdp', 'RDP'), ('ssh', 'SSH')])),
('name', models.CharField(help_text='Name of your custom command.', max_length=b'128', verbose_name='name')),
('name', models.CharField(help_text='Name of your custom command.', max_length='128', verbose_name='name')),
('template', models.CharField(validators=[dashboard.validators.connect_command_template_validator], max_length=256, blank=True, help_text='Template for connection command string. Available parameters are: username, password, host, port.', null=True, verbose_name='command template')),
('user', models.ForeignKey(related_name='command_set', to=settings.AUTH_USER_MODEL)),
('user', models.ForeignKey(related_name='command_set', on_delete=models.CASCADE, to=settings.AUTH_USER_MODEL)),
],
options={
},
......@@ -37,8 +37,8 @@ class Migration(migrations.Migration):
name='Favourite',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('instance', models.ForeignKey(to='vm.Instance')),
('user', models.ForeignKey(to=settings.AUTH_USER_MODEL)),
('instance', models.ForeignKey(to='vm.Instance', on_delete=models.CASCADE,)),
('user', models.ForeignKey(to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE,)),
],
options={
},
......@@ -49,7 +49,7 @@ class Migration(migrations.Migration):
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('org_id', models.CharField(help_text='Unique identifier of the person, e.g. a student number.', max_length=64)),
('group', models.ForeignKey(to='auth.Group')),
('group', models.ForeignKey(to='auth.Group', on_delete=models.CASCADE,)),
],
options={
},
......@@ -61,7 +61,7 @@ class Migration(migrations.Migration):
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('org_id', models.CharField(help_text='Unique identifier of the group at the organization.', max_length=64, unique=True, null=True, blank=True)),
('description', models.TextField(blank=True)),
('group', models.OneToOneField(to='auth.Group')),
('group', models.OneToOneField(to='auth.Group', on_delete=models.CASCADE)),
],
options={
'abstract': False,
......@@ -78,7 +78,7 @@ class Migration(migrations.Migration):
('subject_data', jsonfield.fields.JSONField(null=True)),
('message_data', jsonfield.fields.JSONField(null=True)),
('valid_until', models.DateTimeField(default=None, null=True)),
('to', models.ForeignKey(to=settings.AUTH_USER_MODEL)),
('to', models.ForeignKey(to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE)),
],
options={
'ordering': ['-created'],
......@@ -96,7 +96,7 @@ class Migration(migrations.Migration):
('email_notifications', models.BooleanField(default=True, help_text='Whether user wants to get digested email notifications.', verbose_name='Email notifications')),
('smb_password', models.CharField(default=dashboard.models.pwgen, help_text='Generated password for accessing store from virtual machines.', max_length=20, verbose_name='Samba password')),
('disk_quota', sizefield.models.FileSizeField(default=2147483648, help_text='Disk quota in mebibytes.', verbose_name='disk quota')),
('user', models.OneToOneField(to=settings.AUTH_USER_MODEL)),
('user', models.OneToOneField(to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE,)),
],
options={
'permissions': (('use_autocomplete', 'Can use autocomplete.'),),
......
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
......
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
import django.utils.timezone
......
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
......
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
......
# -*- coding: utf-8 -*-
# Generated by Django 1.11.3 on 2017-07-07 19:09
from __future__ import unicode_literals
from django.db import migrations, models
......
# -*- coding: utf-8 -*-
# Generated by Django 1.11.25 on 2020-04-24 20:00
from __future__ import unicode_literals
from django.db import migrations
import sizefield.models
......
# -*- coding: utf-8 -*-
# Generated by Django 1.11.25 on 2020-11-06 13:33
from __future__ import unicode_literals
from django.db import migrations, models
......
# -*- coding: utf-8 -*-
# Generated by Django 1.11.25 on 2021-02-01 17:30
from __future__ import unicode_literals
from django.db import migrations, models
......
# Generated by Django 3.2.8 on 2021-11-02 13:31
import common.models
from django.db import migrations, models
import jsonfield.fields
import model_utils.fields
class Migration(migrations.Migration):
dependencies = [
('dashboard', '0009_auto_20210201_1730'),
]
operations = [
migrations.AlterField(
model_name='message',
name='effect',
field=models.CharField(choices=[('success', 'success'), ('info', 'info'), ('warning', 'warning'), ('danger', 'danger')], default='info', max_length=10, verbose_name='effect'),
),
migrations.AlterField(
model_name='notification',
name='message_data',
field=jsonfield.fields.JSONField(dump_kwargs={'cls': common.models.Encoder}, null=True),
),
migrations.AlterField(
model_name='notification',
name='status',
field=model_utils.fields.StatusField(choices=[(0, 'dummy')], default='new', max_length=100, no_check_for_status=True),
),
migrations.AlterField(
model_name='notification',
name='subject_data',
field=jsonfield.fields.JSONField(dump_kwargs={'cls': common.models.Encoder}, null=True),
),
migrations.AlterField(
model_name='profile',
name='preferred_language',
field=models.CharField(choices=[('en', 'English'), ('hu', 'Hungarian')], default='en', max_length=32, verbose_name='preferred language'),
),
]
......@@ -15,7 +15,7 @@
# You should have received a copy of the GNU General Public License along
# with CIRCLE. If not, see <http://www.gnu.org/licenses/>.
from __future__ import absolute_import
import json
from hashlib import md5
......@@ -26,17 +26,18 @@ from django.conf import settings
from django.contrib.auth.models import User, Group, Permission
from django.contrib.auth.signals import user_logged_in
from django.core.exceptions import ObjectDoesNotExist
from django.core.urlresolvers import reverse
from django.urls import reverse
from django.db.models import (
Model, ForeignKey, OneToOneField, CharField, IntegerField, TextField,
DateTimeField, BooleanField
)
from django.db import models
from django.db.models.signals import post_save, pre_delete, post_delete
from django.templatetags.static import static
from django.utils import timezone
from django.utils.html import escape
from django.utils.translation import ugettext_lazy as _
from django_sshkey.models import UserKey
from simplesshkey.models import UserKey
from itertools import chain
from jsonfield import JSONField
from model_utils import Choices
......@@ -50,6 +51,14 @@ from vm.models.instance import ACCESS_METHODS
from .store_api import Store, NoStoreException, NotOkException
from .validators import connect_command_template_validator
try:
# Python 2: "unicode" is built-in
unicode
except NameError:
unicode = str
logger = getLogger(__name__)
......@@ -70,7 +79,7 @@ class Message(TimeStampedModel, TimeFramedModel):
verbose_name = _('message')
verbose_name_plural = _('messages')
def __unicode__(self):
def __str__(self):
return self.message
def get_absolute_url(self):
......@@ -79,8 +88,8 @@ class Message(TimeStampedModel, TimeFramedModel):
class Favourite(Model):
instance = ForeignKey("vm.Instance")
user = ForeignKey(User)
instance = ForeignKey("vm.Instance", on_delete=models.CASCADE)
user = ForeignKey(User, on_delete=models.CASCADE)
class Notification(TimeStampedModel):
......@@ -89,7 +98,7 @@ class Notification(TimeStampedModel):
('read', _('read')))
status = StatusField()
to = ForeignKey(User)
to = ForeignKey(User, on_delete=models.CASCADE)
subject_data = JSONField(null=True, dump_kwargs={"cls": Encoder})
message_data = JSONField(null=True, dump_kwargs={"cls": Encoder})
valid_until = DateTimeField(null=True, default=None)
......@@ -122,8 +131,8 @@ class Notification(TimeStampedModel):
self.escape_dict(self.message_data))
def escape_dict(self, data):
for k, v in data['params'].items():
if isinstance(v, basestring):
for k, v in list(data['params'].items()):
if isinstance(v, str):
data['params'][k] = escape(v)
return data
......@@ -144,7 +153,7 @@ class Notification(TimeStampedModel):
class ConnectCommand(Model):
user = ForeignKey(User, related_name='command_set')
user = ForeignKey(User, related_name='command_set', on_delete=models.CASCADE)
access_method = CharField(max_length=10, choices=ACCESS_METHODS,
verbose_name=_('access method'),
help_text=_('Type of the remote access method.'))
......@@ -161,12 +170,12 @@ class ConnectCommand(Model):
class Meta:
ordering = ('id',)
def __unicode__(self):
def __str__(self):
return self.template
class Profile(Model):
user = OneToOneField(User)
user = OneToOneField(User, on_delete=models.CASCADE)
preferred_language = CharField(verbose_name=_('preferred language'),
choices=settings.LANGUAGES,
max_length=32,
......@@ -236,7 +245,7 @@ class Profile(Model):
def get_avatar_url(self):
if self.use_gravatar:
gravatar_hash = md5(self.user.email).hexdigest()
gravatar_hash = md5(self.user.email.encode('utf-8')).hexdigest()
return ("https://secure.gravatar.com/avatar/%s"
"?s=200" % gravatar_hash)
else:
......@@ -252,7 +261,7 @@ class Profile(Model):
name = "%s (%s)" % (name, self.org_id)
return name
def __unicode__(self):
def __str__(self):
return self.get_display_name()
def save(self, *args, **kwargs):
......@@ -270,14 +279,14 @@ class Profile(Model):
class FutureMember(Model):
org_id = CharField(max_length=64, help_text=_(
'Unique identifier of the person, e.g. a student number.'))
group = ForeignKey(Group)
group = ForeignKey(Group, on_delete=models.CASCADE)
class Meta:
ordering = ('id',)
unique_together = ('org_id', 'group')
def __unicode__(self):
return u"%s (%s)" % (self.org_id, self.group)
def __str__(self):
return "%s (%s)" % (self.org_id, self.group)
class GroupProfile(AclBase):
......@@ -286,7 +295,7 @@ class GroupProfile(AclBase):
('owner', _('owner')),
)
group = OneToOneField(Group)
group = OneToOneField(Group, on_delete=models.CASCADE)
org_id = CharField(
unique=True, blank=True, null=True, max_length=64,
help_text=_('Unique identifier of the group at the organization.'))
......@@ -301,7 +310,7 @@ class GroupProfile(AclBase):
class Meta:
ordering = ('id',)
def __unicode__(self):
def __str__(self):
return self.group.name
def save(self, *args, **kwargs):
......@@ -334,7 +343,7 @@ class GroupProfile(AclBase):
profile.org_id = data["org_id"]
profile.instance_limit = int(data["instance_limit"])
profile.template_instance_limit = int(data["template_instance_limit"])
profile.disk_quota = long(data["disk_quota"])
profile.disk_quota = int(data["disk_quota"])
profile.save()
for org_id in data["users"]:
......@@ -397,7 +406,7 @@ def create_profile(user):
max_quota = max(quotas)
store.create_user(profile.smb_password, None, max_quota)
except:
logger.exception("Can't create user %s", unicode(user))
logger.exception("Can't create user %s", str(user))
return created
......
......@@ -361,7 +361,6 @@ function addSliderMiscs() {
$(".vm-slider").simpleSlider();
$(".cpu-priority-slider").bind("slider:changed", function (event, data) {
var value = data.value + 0;
$('.cpu-priority-input option[value="' + value + '"]').attr("selected", "selected");
});
......
......@@ -16,7 +16,7 @@
# with CIRCLE. If not, see <http://www.gnu.org/licenses/>.
import json
import logging
from urlparse import urljoin
from urllib.parse import urlparse
import os
from datetime import datetime
......@@ -28,6 +28,12 @@ from sizefield.utils import filesizeformat
from storage.models import Disk
try:
# Python 2: "unicode" is built-in
unicode
except NameError:
unicode = str
logger = logging.getLogger(__name__)
......
......@@ -15,7 +15,7 @@
# You should have received a copy of the GNU General Public License along
# with CIRCLE. If not, see <http://www.gnu.org/licenses/>.
from __future__ import absolute_import
from django.contrib.auth.models import Group, User
from django.utils.translation import ugettext_lazy as _, ugettext
......@@ -25,7 +25,7 @@ from django_tables2 import Table, A
from django_tables2.columns import (
TemplateColumn, Column, LinkColumn, BooleanColumn
)
from django_sshkey.models import UserKey
from simplesshkey.models import UserKey
from storage.models import Disk
from vm.models import Node, InstanceTemplate, Lease
......@@ -287,6 +287,9 @@ class UserKeyListTable(Table):
orderable=False,
)
def get_table_pagination(self, table):
return False
class Meta:
model = UserKey
attrs = {'class': ('table table-bordered table-striped table-hover'),
......
......@@ -18,7 +18,7 @@
import logging
from django.conf import settings
from django.core.mail import send_mail
from django.core.urlresolvers import reverse
from django.urls import reverse
from django.db.models import Q
from django.template.loader import render_to_string
from django.utils import timezone
......@@ -28,6 +28,13 @@ from manager.mancelery import celery
from ..models import Notification
from ..views import UnsubscribeFormView
try:
# Python 2: "unicode" is built-in
unicode
except NameError:
unicode = str
logger = logging.getLogger(__name__)
......@@ -43,7 +50,7 @@ def send_email_notifications():
recipients[i.to].append(i)
logger.info("Delivering notifications to %d users", len(recipients))
for user, msgs in recipients.iteritems():
for user, msgs in list(recipients.items()):
if (not user.profile or not user.email or not
user.profile.email_notifications):
logger.debug("%s gets no notifications", unicode(user))
......
{% load i18n %}
{% load staticfiles %}
{% load static %}
{% load cache %}
{% load pipeline %}
<!DOCTYPE html>
......
{% load staticfiles %}
{% load static %}
<img src="{% static "dashboard/img/logo.png" %}" alt="circle logo" style="height: 25px;"/>
<img src="{% static "local-logo.png" %}" alt="local logo" style="padding-left: 2px; height: 25px;"/>
......@@ -21,6 +21,7 @@
</div>
</div>
</div>
<div class="row">
<div class="col-sm-3" style="font-weight: bold;">
<i class="fa fa-cogs"></i> {% trans "CPU count" %}
......
{% extends "dashboard/operate.html" %}
{% load i18n %}
{% load crispy_forms_tags %}
{% block formbuttons %}
<div class="pull-right">
<a class="btn btn-default" href="{{object.get_absolute_url}}" data-dismiss="modal">
{% trans "Cancel" %}
</a>
{% if object.active and lease_types and not request.token_user %}
<a class="btn btn-primary" id="vm-renew-request-lease-button"
href="{% url "request.views.request-lease" vm_pk=object.pk %}">
<i class="fa fa-forward"></i>
{% trans "Request longer lease" %}
</a>
{% endif %}
<button class="btn btn-{{ opview.effect }} btn-op-form-send" type="submit" id="op-form-send">
{% if opview.icon %}<i class="fa fa-fw fa-{{opview.icon}}"></i> {% endif %}{{ op.name|capfirst }}
</button>
</div>
{% endblock %}
{% block extra %}
<div class="clearfix"></div>
<div id="vm-renew-request-lease">
<hr />
{% include "request/_request-lease-form.html" with form=lease_request_form vm=object %}
</div>
{% endblock %}
{% extends "base.html" %}
{% load staticfiles %}
{% load static %}
{% load i18n %}
{% block title-site %}Dashboard | CIRCLE{% endblock %}
......@@ -92,7 +92,7 @@
</li>
<li class="hidden-xs">
<a href="{% url "dashboard.views.profile-preferences" %}">
<img class="profile-avatar" src="{{ request.user.profile.get_avatar_url }}" />
<!--<img class="profile-avatar" src="{{ request.user.profile.get_avatar_url }}" /> -->
</a>
</li>
</ul>
......
{% extends "dashboard/base.html" %}
{% load staticfiles %}
{% load static %}
{% load i18n %}
{% load render_table from django_tables2 %}
......
{% extends "dashboard/base.html" %}
{% load staticfiles %}
{% load static %}
{% load i18n %}
{% block title-page %}{% trans "Index" %}{% endblock %}
......
{% extends "dashboard/base.html" %}
{% load staticfiles %}
{% load static %}
{% load i18n %}
{% load render_table from django_tables2 %}
......
{% extends "dashboard/base.html" %}
{% load staticfiles %}
{% load static %}
{% load i18n %}
{% block title-page %}{{ node.name }} | {% trans "Node" %}{% endblock %}
......
{% extends "dashboard/base.html" %}
{% load staticfiles %}
{% load static %}
{% load i18n %}
{% load render_table from django_tables2 %}
......
{% extends "dashboard/base.html" %}
{% load staticfiles %}
{% load static %}
{% block content %}
<div class="body-content">
......
{% extends "dashboard/base.html" %}
{% load staticfiles %}
{% load static %}
{% load i18n %}
{% load crispy_forms_tags %}
{% load arrowfilter %}
......
{% extends "dashboard/base.html" %}
{% load staticfiles %}
{% load static %}
{% load i18n %}
{% load render_table from django_tables2 %}
{% load crispy_forms_tags %}
......
{% extends "dashboard/base.html" %}
{% load staticfiles %}
{% load static %}
{% load i18n %}
{% block title-page %}{% trans "List" %} | {% trans "Store" %}{% endblock %}
......
{% extends "dashboard/base.html" %}
{% load staticfiles %}
{% load static %}
{% load i18n %}
{% load sizefieldtags %}
{% load crispy_forms_tags %}
......
{% extends "dashboard/base.html" %}
{% load staticfiles %}
{% load static %}
{% load i18n %}
{% load render_table from django_tables2 %}
......
{% extends "dashboard/base.html" %}
{% load staticfiles %}
{% load static %}
{% load i18n %}
{% load render_table from django_tables2 %}
......
{% extends "dashboard/base.html" %}
{% load staticfiles %}
{% load static %}
{% load i18n %}
{% load pipeline %}
......
{% load i18n %}
{% load staticfiles %}
{% load static %}
{% if not perms.vm.access_console %}
<div class="alert alert-warning">
......
{% extends "dashboard/base.html" %}
{% load staticfiles %}
{% load static %}
{% load i18n %}
{% block title-page %}{% trans "Virtual machines" %}{% endblock %}
......
......@@ -24,6 +24,6 @@ register = Library()
@register.filter
def get_text(human_readable, user):
if human_readable is None:
return u""
return ""
else:
return human_readable.get_text(user)
......@@ -36,7 +36,7 @@ def display_pf6(ports):
def display_pf(ports, proto):
data = ports[proto]
if ports['private'] in LINKABLE_PORTS.keys():
if ports['private'] in list(LINKABLE_PORTS.keys()):
href = "%s:%d" % (data['host'], data['port'])
return '<a href="%s://%s">%s</a>' % (
LINKABLE_PORTS.get(ports['private']), href, href)
......
......@@ -36,16 +36,16 @@ class SeleniumConfig(object):
log_backup = 5
# Accented letters from which selenium can choose to name stuff
accents = u"áéíöóúűÁÉÍÖÓÜÚŰ"
accents = "áéíöóúűÁÉÍÖÓÜÚŰ"
# Non accented letters from which selenium can choose to name stuff
valid_chars = "0123456789abcdefghijklmnopqrstvwxyz"
# First we choose 10 random normal letters
random_pass = "".join([random.choice(
valid_chars) for n in xrange(10)])
valid_chars) for n in range(10)])
# Then we append it with 5 random accented one
random_pass += "".join([random.choice(
accents) for n in xrange(5)])
accents) for n in range(5)])
# Then we name our client as test_%(password)s
client_name = 'test_%s' % random_pass
......
......@@ -22,7 +22,7 @@ import logging
import random
import re
import time
import urlparse
import urllib.parse
from selenium.common.exceptions import (
NoSuchElementException, StaleElementReferenceException,
......@@ -45,10 +45,10 @@ class SeleniumMixin(object):
self.driver.save_screenshot(name)
def get_url(self, fragment_needed=False, fragment=None):
url_base = urlparse.urlparse(self.driver.current_url)
url_base = urllib.parse.urlparse(self.driver.current_url)
url_save = ("%(host)s%(url)s" % {
'host': self.conf.host,
'url': urlparse.urljoin(url_base.path, url_base.query)})
'url': urllib.parse.urljoin(url_base.path, url_base.query)})
if fragment is None:
fragment = url_base.fragment
else:
......@@ -86,7 +86,7 @@ class SeleniumMixin(object):
options = self.list_options(select)
select = Select(select)
if what is not None:
for key, value in options.iteritems():
for key, value in list(options.items()):
if what in key:
my_choice = key
else:
......@@ -98,7 +98,7 @@ class SeleniumMixin(object):
if what in value:
my_choice = key
if my_choice is None:
my_choose_list = options.keys()
my_choose_list = list(options.keys())
my_choice = my_choose_list[random.randint(
0, len(my_choose_list) - 1)]
select.select_by_value(my_choice)
......@@ -117,7 +117,7 @@ class SeleniumMixin(object):
if target_href in href:
perfect_fit = True
if isinstance(attributes, dict):
for key, target_value in attributes.iteritems():
for key, target_value in list(attributes.items()):
attr_check = link.get_attribute(key)
if attr_check is not None and attr_check:
if target_value not in attr_check:
......@@ -193,7 +193,7 @@ class CircleSeleniumMixin(SeleniumMixin):
location = '/dashboard/'
driver.get('%s%s' % (self.conf.host, location))
# Only if we aren't logged in already
if location not in urlparse.urlparse(self.driver.current_url).path:
if location not in urllib.parse.urlparse(self.driver.current_url).path:
try:
name_input = driver.find_element_by_id("id_username")
password_input = driver.find_element_by_id("id_password")
......@@ -508,7 +508,7 @@ class CircleSeleniumMixin(SeleniumMixin):
try:
if isinstance(timeline_dict, dict):
recent = None
for key, value in timeline_dict.iteritems():
for key, value in list(timeline_dict.items()):
if recent is None or int(key) > int(recent):
recent = key
if len(timeline_dict) > 1:
......@@ -652,7 +652,7 @@ class CircleSeleniumMixin(SeleniumMixin):
WebDriverWait(self.driver, self.conf.wait_max_sec).until(
ec.visibility_of_element_located((
By.CLASS_NAME, 'alert-success')))
url = urlparse.urlparse(self.driver.current_url)
url = urllib.parse.urlparse(self.driver.current_url)
if "/template/list/" not in url.path:
logger.warning('CIRCLE does not redirect to /template/list/')
raise Exception(
......@@ -686,7 +686,7 @@ class CircleSeleniumMixin(SeleniumMixin):
WebDriverWait(self.driver, self.conf.wait_max_sec).until(
ec.visibility_of_element_located((
By.CLASS_NAME, 'alert-success')))
url = urlparse.urlparse(self.driver.current_url)
url = urllib.parse.urlparse(self.driver.current_url)
pk = re.search(r'\d+', url.path).group()
return pk
except:
......
......@@ -56,7 +56,7 @@ class ViewUserTestCase(unittest.TestCase):
activity_code='test.test')
go.return_value._meta.object_name = "InstanceActivity"
view = InstanceActivityDetail.as_view()
self.assertEquals(view(request, pk=1234).status_code, 200)
self.assertEqual(view(request, pk=1234).status_code, 200)
def test_found(self):
request = FakeRequestFactory(superuser=True)
......@@ -68,7 +68,7 @@ class ViewUserTestCase(unittest.TestCase):
act.user.pk = 1
go.return_value = act
view = InstanceActivityDetail.as_view()
self.assertEquals(view(request, pk=1234).render().status_code, 200)
self.assertEqual(view(request, pk=1234).render().status_code, 200)
class ExpiredSigner(TimestampSigner):
......@@ -93,7 +93,7 @@ class SubscribeTestCase(unittest.TestCase):
gq.return_value.get.return_value = p
token = UnsubscribeFormView.get_token(MagicMock(pk=1))
request = FakeRequestFactory(POST={})
self.assertEquals(view(request, token=token), iv.return_value)
self.assertEqual(view(request, token=token), iv.return_value)
gq.return_value.get.assert_called_with(user_id=1)
@patch.object(views.UnsubscribeFormView, 'get_queryset')
......@@ -104,7 +104,7 @@ class SubscribeTestCase(unittest.TestCase):
gq.return_value.get.return_value = p
token = UnsubscribeFormView.get_token(MagicMock(pk=1))
request = FakeRequestFactory(POST={'email_notifications': 'on'})
self.assertEquals(view(request, token=token), iv.return_value)
self.assertEqual(view(request, token=token), iv.return_value)
gq.return_value.get.assert_called_with(user_id=1)
def test_404_for_invalid_token(self):
......@@ -137,7 +137,7 @@ class VmOperationViewTestCase(unittest.TestCase):
inst._meta.object_name = "Instance"
inst.destroy = Instance._ops['destroy'](inst)
go.return_value = inst
self.assertEquals(
self.assertEqual(
view.as_view()(request, pk=1234).render().status_code, 200)
def test_unpermitted(self):
......@@ -226,7 +226,7 @@ class VmOperationViewTestCase(unittest.TestCase):
inst.migrate = Instance._ops['migrate'](inst)
inst.has_level.return_value = True
go.return_value = inst
self.assertEquals(
self.assertEqual(
view.as_view()(request, pk=1234).render().status_code, 200)
def test_save_as_wo_name(self):
......@@ -274,7 +274,7 @@ class VmOperationViewTestCase(unittest.TestCase):
inst.has_level.return_value = True
go.return_value = inst
rend = view.as_view()(request, pk=1234).render()
self.assertEquals(rend.status_code, 200)
self.assertEqual(rend.status_code, 200)
class VmMassOperationViewTestCase(unittest.TestCase):
......@@ -288,7 +288,7 @@ class VmMassOperationViewTestCase(unittest.TestCase):
inst._meta.object_name = "Instance"
inst.destroy = Instance._ops['destroy'](inst)
go.return_value = [inst]
self.assertEquals(
self.assertEqual(
view.as_view()(request, pk=1234).render().status_code, 200)
def test_unpermitted_choice(self):
......@@ -377,7 +377,7 @@ class VmMassOperationViewTestCase(unittest.TestCase):
inst.migrate = Instance._ops['migrate'](inst)
inst.has_level.return_value = True
go.return_value = [inst]
self.assertEquals(
self.assertEqual(
view.as_view()(request, pk=1234).render().status_code, 200)
......@@ -396,7 +396,7 @@ class RenewViewTest(unittest.TestCase):
inst.has_level.return_value = True
go.return_value = inst
rend = view.as_view()(request, pk=1234).render()
self.assertEquals(rend.status_code, 200)
self.assertEqual(rend.status_code, 200)
def test_renew_by_owner_wo_param(self):
request = FakeRequestFactory(POST={}, has_perms_mock=True)
......@@ -554,7 +554,7 @@ class AclUpdateViewTest(unittest.TestCase):
def test_has_next_level(self):
data = {None: 'user', 'user': 'operator', 'operator': 'owner',
'owner': 'owner'}
for k, v in data.items():
for k, v in list(data.items()):
inst = MagicMock(spec=Instance)
inst.has_level.return_value = True
inst.ACL_LEVELS = Instance.ACL_LEVELS
......@@ -650,7 +650,7 @@ def FakeRequestFactory(user=None, **kwargs):
request.GET.update(kwargs.pop('GET', {}))
if len(kwargs):
warnings.warn("FakeRequestFactory kwargs unused: " + unicode(kwargs),
warnings.warn("FakeRequestFactory kwargs unused: " + str(kwargs),
stacklevel=2)
return request
......
......@@ -22,6 +22,11 @@ from django.test import TestCase
from ..models import Profile
from ..views import search_user
try:
# Python 2: "unicode" is built-in
unicode
except NameError:
unicode = str
class NotificationTestCase(TestCase):
......
......@@ -34,7 +34,7 @@ class EmailNotificationTestCase(unittest.TestCase):
self.nextpk += 1
if user is None:
user = MagicMock(spec=User, pk=self.nextpk)
user.profile.__unicode__.return_value = "user"
user.profile.__str__.return_value = "user"
user.email = "mail"
user.profile.email_notifications = True
user.profile.preferred_language = "en"
......@@ -62,7 +62,7 @@ class EmailNotificationTestCase(unittest.TestCase):
fake.append(self.get_fake_notification(fake[0].to))
no.filter.return_value = fake
local_periodic_tasks.send_email_notifications()
self.assertEquals(sm.call_count, 2)
self.assertEqual(sm.call_count, 2)
assert all(i.status == i.STATUS.delivered for i in fake)
def test_sending_some(self, no, sm):
......@@ -71,7 +71,7 @@ class EmailNotificationTestCase(unittest.TestCase):
fake[1].to.profile.email_notifications = False
no.filter.return_value = fake
local_periodic_tasks.send_email_notifications()
self.assertEquals(
self.assertEqual(
[i.status == i.STATUS.delivered for i in fake],
[True, False, True])
self.assertEquals(sm.call_count, 1)
self.assertEqual(sm.call_count, 1)
......@@ -21,7 +21,7 @@ import unittest
from django.template import Template, Context, VariableDoesNotExist
from django.template.engine import Engine
from django.core.urlresolvers import NoReverseMatch
from django.urls import NoReverseMatch
class TemplateSyntaxTestCase(unittest.TestCase):
......@@ -38,7 +38,7 @@ class TemplateSyntaxTestCase(unittest.TestCase):
if isfile(i):
self._test_template(join(path, i))
elif isdir(i):
print("%s:" % i)
print(("%s:" % i))
self._test_dir(listdir(i), i)
def _test_template(self, path):
......
......@@ -25,16 +25,16 @@ from django.test.client import Client
from django.contrib.auth.models import User, Group, Permission
from django.contrib.auth import authenticate
from common.tests.celery_mock import MockCeleryMixin
from dashboard.views import VmAddInterfaceView
from vm.models import Instance, InstanceTemplate, Lease, Node, Trait
from vm.operations import (WakeUpOperation, AddInterfaceOperation,
from circle.common.tests.celery_mock import MockCeleryMixin
from circle.dashboard.views import VmAddInterfaceView
from circle.vm.models import Instance, InstanceTemplate, Lease, Node, Trait
from circle.vm.operations import (WakeUpOperation, AddInterfaceOperation,
AddPortOperation, RemoveInterfaceOperation,
DeployOperation, RenameOperation)
from ..models import Profile
from firewall.models import Vlan, Host, VlanGroup
from circle.firewall.models import Vlan, Host, VlanGroup
from mock import Mock, patch
from django_sshkey.models import UserKey
from simplesshkey.models import UserKey
import django.conf
settings = django.conf.settings.FIREWALL_SETTINGS
......@@ -137,15 +137,15 @@ class VmDetailTest(LoginMixin, MockCeleryMixin, TestCase):
inst.set_level(self.u2, 'owner')
interface_count = inst.interface_set.count()
with patch.object(AddInterfaceOperation, 'async') as async:
async.side_effect = inst.add_interface.call
with patch.object(AddInterfaceOperation, 'async') as _async:
_async.side_effect = inst.add_interface.call
with patch.object(VmAddInterfaceView, 'get_form_kwargs',
autospec=True) as get_form_kwargs:
get_form_kwargs.return_value = {'choices': Vlan.objects.all()}
response = c.post("/dashboard/vm/1/op/add_interface/",
{'vlan': 1})
self.assertEqual(response.status_code, 302)
assert async.called
assert _async.called
self.assertEqual(inst.interface_set.count(), interface_count)
def test_permitted_network_add(self):
......@@ -222,25 +222,25 @@ class VmDetailTest(LoginMixin, MockCeleryMixin, TestCase):
self.login(c, 'user1')
InstanceTemplate.objects.get(id=1).set_level(self.u1, 'user')
Vlan.objects.get(id=1).set_level(self.u1, 'user')
with patch.object(DeployOperation, 'async') as async:
with patch.object(DeployOperation, 'async') as _async:
response = c.post('/dashboard/vm/create/',
{'template': 1,
'system': "bubi",
'cpu_priority': 1, 'cpu_count': 1,
'ram_size': 1000})
assert async.called
assert _async.called
self.assertEqual(response.status_code, 302)
def test_use_permitted_template_superuser(self):
c = Client()
self.login(c, 'superuser')
with patch.object(DeployOperation, 'async') as async:
with patch.object(DeployOperation, 'async') as _async:
response = c.post('/dashboard/vm/create/',
{'template': 1,
'system': "bubi",
'cpu_priority': 1, 'cpu_count': 1,
'ram_size': 1000})
assert async.called
assert _async.called
self.assertEqual(response.status_code, 302)
def test_edit_unpermitted_template(self):
......@@ -531,7 +531,7 @@ class VmDetailTest(LoginMixin, MockCeleryMixin, TestCase):
self.login(c, "superuser")
instance_count = Instance.objects.all().count()
with patch.object(DeployOperation, 'async') as async:
with patch.object(DeployOperation, 'async') as _async:
response = c.post("/dashboard/vm/create/", {
'name': 'vm',
'amount': 1,
......@@ -541,7 +541,7 @@ class VmDetailTest(LoginMixin, MockCeleryMixin, TestCase):
'network': [],
})
assert async.called
assert _async.called
self.assertEqual(response.status_code, 302)
self.assertEqual(instance_count + 1, Instance.objects.all().count())
......@@ -775,8 +775,8 @@ class GroupCreateTest(LoginMixin, MockCeleryMixin, TestCase):
self.u0.save()
permlist = Permission.objects.all()
self.u0.user_permissions.add(
filter(lambda element: 'group' in element.name and
'add' in element.name, permlist)[0])
[element for element in permlist if 'group' in element.name and
'add' in element.name][0])
# u1 simple user without permissions
self.u1 = User.objects.create(username='user1')
self.u1.set_password('password')
......@@ -877,8 +877,8 @@ class GroupDeleteTest(LoginMixin, MockCeleryMixin, TestCase):
self.u0.save()
permlist = Permission.objects.all()
self.u0.user_permissions.add(
filter(lambda element: 'group' in element.name and
'delete' in element.name, permlist)[0])
[element for element in permlist if 'group' in element.name and
'delete' in element.name][0])
# u1 simple user without permissions
self.u1 = User.objects.create(username='user1')
self.u1.set_password('password')
......@@ -1350,8 +1350,8 @@ class GroupListTest(LoginMixin, MockCeleryMixin, TestCase):
self.u1.save()
permlist = Permission.objects.all()
self.u1.user_permissions.add(
filter(lambda element: 'group' in element.name and
'add' in element.name, permlist)[0])
[element for element in permlist if 'group' in element.name and
'add' in element.name][0])
self.u2 = User.objects.create(username='user2')
self.u2.set_password('password')
self.u2.save()
......
......@@ -15,7 +15,7 @@
# You should have received a copy of the GNU General Public License along
# with CIRCLE. If not, see <http://www.gnu.org/licenses/>.
from __future__ import absolute_import
from django.conf.urls import url
......@@ -272,15 +272,15 @@ urlpatterns = [
urlpatterns += [
url(r'^vm/(?P<pk>\d+)/op/%s/$' % op, v.as_view(), name=v.get_urlname())
for op, v in vm_ops.iteritems()
for op, v in list(vm_ops.items())
]
urlpatterns += [
url(r'^vm/mass_op/%s/$' % op, v.as_view(), name=v.get_urlname())
for op, v in vm_mass_ops.iteritems()
for op, v in list(vm_mass_ops.items())
]
urlpatterns += [
url(r'^node/(?P<pk>\d+)/op/%s/$' % op, v.as_view(), name=v.get_urlname())
for op, v in node_ops.iteritems()
for op, v in list(node_ops.items())
]
......@@ -54,12 +54,12 @@ def connect_command_template_validator(value):
"""Validate value as a connect command template.
>>> try: connect_command_template_validator("%(host)s")
... except ValidationError as e: print e
...
... except ValidationError as e: print(e)
...
>>> connect_command_template_validator("%(host)s")
>>> try: connect_command_template_validator("%(host)s %s")
... except ValidationError as e: print e
...
... except ValidationError as e: print(e)
...
[u'Invalid template string.']
"""
......@@ -72,3 +72,4 @@ def connect_command_template_validator(value):
}
except (KeyError, TypeError, ValueError):
raise ValidationError(_("Invalid template string."))
......@@ -3,16 +3,16 @@
# __all__ = [ ]
from group import *
from index import *
from node import *
from store import *
from template import *
from user import *
from util import *
from vm import *
from graph import *
from storage import *
from .group import *
from .index import *
from .node import *
from .store import *
from .template import *
from .user import *
from .util import *
from .vm import *
from .graph import *
from .storage import *
from request import *
from message import *
from autocomplete import *
from .message import *
from .autocomplete import *
......@@ -26,6 +26,11 @@ from django.http import HttpResponse
from ..views import AclUpdateView
from ..models import Profile
try:
# Python 2: "unicode" is built-in
unicode
except NameError:
unicode = str
def highlight(field, q, none_wo_match=True):
"""
......
......@@ -15,7 +15,7 @@
# You should have received a copy of the GNU General Public License along
# with CIRCLE. If not, see <http://www.gnu.org/licenses/>.
from __future__ import absolute_import, unicode_literals
import logging
import requests
......
......@@ -14,7 +14,7 @@
#
# You should have received a copy of the GNU General Public License along
# with CIRCLE. If not, see <http://www.gnu.org/licenses/>.
from __future__ import unicode_literals, absolute_import
import json
import logging
......@@ -26,7 +26,7 @@ from django.contrib import messages
from django.contrib.auth.models import User, Group
from django.contrib.messages.views import SuccessMessageMixin
from django.core.exceptions import PermissionDenied, SuspiciousOperation
from django.core.urlresolvers import reverse, reverse_lazy
from django.urls import reverse, reverse_lazy
from django.http import HttpResponse, Http404
from django.shortcuts import redirect
from django.utils.translation import ugettext as _
......@@ -46,6 +46,12 @@ from ..models import FutureMember, GroupProfile
from ..store_api import Store, NoStoreException
from ..tables import GroupListTable
try:
# Python 2: "unicode" is built-in
unicode
except NameError:
unicode = str
logger = logging.getLogger(__name__)
......@@ -217,8 +223,7 @@ class GroupList(LoginRequiredMixin, SingleTableView):
return super(GroupList, self).get(*args, **kwargs)
def get_queryset(self):
logger.debug('GroupList.get_queryset() called. User: %s',
unicode(self.request.user))
# logger.debug('GroupList.get_queryset() called. User: %s', unicode(self.request.user))
profiles = GroupProfile.get_objects_with_level(
'operator', self.request.user)
groups = Group.objects.filter(groupprofile__in=profiles)
......@@ -239,7 +244,8 @@ class GroupRemoveUserView(DeleteViewBase):
def check_auth(self):
if not self.get_object().profile.has_level(
self.request.user, self.level):
raise PermissionDenied()
# self.request.user, self.level:
raise PermissionDenied()
def get_context_data(self, **kwargs):
context = super(GroupRemoveUserView, self).get_context_data(**kwargs)
......
......@@ -14,12 +14,12 @@
#
# You should have received a copy of the GNU General Public License along
# with CIRCLE. If not, see <http://www.gnu.org/licenses/>.
from __future__ import unicode_literals, absolute_import
import logging
from django.core.cache import cache
from django.core.urlresolvers import reverse
from django.urls import reverse
from django.conf import settings
from django.contrib.auth.models import Group, User
from django.views.generic import TemplateView
......@@ -112,7 +112,7 @@ class IndexView(LoginRequiredMixin, TemplateView):
files = {'toplist': toplist, 'quota': quota}
except Exception:
logger.exception("Unable to get tolist for %s",
unicode(self.request.user))
str(self.request.user))
files = {'toplist': []}
cache.set(cache_key, files, 300)
......@@ -128,7 +128,7 @@ class HelpView(TemplateView):
def get_context_data(self, *args, **kwargs):
ctx = super(HelpView, self).get_context_data(*args, **kwargs)
operations = [(o, Instance._ops[o.op])
for o in vm_ops.values() if o.show_in_toolbar]
for o in list(vm_ops.values()) if o.show_in_toolbar]
ctx.update({"saml": hasattr(settings, "SAML_CONFIG"),
"operations": operations,
"store": settings.STORE_URL})
......
......@@ -18,7 +18,7 @@
from django.contrib.messages.views import SuccessMessageMixin
from django.core.cache import cache
from django.core.cache.utils import make_template_fragment_key
from django.core.urlresolvers import reverse
from django.urls import reverse
from django.utils.translation import ugettext as _
from django.views.generic import CreateView, DeleteView, UpdateView
......
......@@ -14,7 +14,7 @@
#
# You should have received a copy of the GNU General Public License along
# with CIRCLE. If not, see <http://www.gnu.org/licenses/>.
from __future__ import unicode_literals, absolute_import
import json
from collections import OrderedDict
......@@ -22,7 +22,7 @@ from collections import OrderedDict
from django.conf import settings
from django.contrib import messages
from django.core.exceptions import PermissionDenied
from django.core.urlresolvers import reverse_lazy
from django.urls import reverse_lazy
from django.db.models import Count
from django.forms.models import inlineformset_factory
from django.http import HttpResponse, JsonResponse
......@@ -48,7 +48,7 @@ from manager.mancelery import crontab_parser
def get_operations(instance, user):
ops = []
for k, v in node_ops.iteritems():
for k, v in list(node_ops.items()):
try:
op = v.get_op_by_object(instance)
op.check_auth(user)
......@@ -175,9 +175,9 @@ class NodeDetailView(LoginRequiredMixin,
if not trait.in_use:
trait.delete()
message = u"Success"
message = "Success"
except: # note this won't really happen
message = u"Not success"
message = "Not success"
if request.is_ajax():
return HttpResponse(
......@@ -267,7 +267,7 @@ class NodeCreate(LoginRequiredMixin, SuperuserRequiredMixin, TemplateView):
# TODO handle not ajax posts
def post(self, request, *args, **kwargs):
if not self.request.user.is_authenticated():
if not self.request.user.is_authenticated:
raise PermissionDenied()
hostform = self.form_class(request.POST)
......
......@@ -14,10 +14,10 @@
#
# You should have received a copy of the GNU General Public License along
# with CIRCLE. If not, see <http://www.gnu.org/licenses/>.
from __future__ import unicode_literals, absolute_import
from django.contrib import messages
from django.core.urlresolvers import reverse
from django.urls import reverse
from django.db.models import Q
from django.utils.translation import ugettext_lazy as _
from django.views.generic import UpdateView
......@@ -52,7 +52,7 @@ class StorageDetail(SuperuserRequiredMixin, UpdateView):
context['disk_table'] = DiskListTable(
self.get_table_data(), request=self.request,
template="django_tables2/with_pagination.html")
template_name="django_tables2/with_pagination.html")
context['filter_names'] = (
('vm', _("virtual machine")),
('template', _("template")),
......
......@@ -14,7 +14,7 @@
#
# You should have received a copy of the GNU General Public License along
# with CIRCLE. If not, see <http://www.gnu.org/licenses/>.
from __future__ import unicode_literals, absolute_import
import json
import logging
......@@ -26,9 +26,9 @@ from django.contrib.auth.decorators import login_required
from django.template.defaultfilters import urlencode
from django.core.cache import cache
from django.core.exceptions import SuspiciousOperation
from django.core.urlresolvers import reverse
from django.urls import reverse
from django.http import HttpResponse
from django.shortcuts import redirect, render_to_response, render
from django.shortcuts import redirect, render
from django.utils.translation import ugettext as _
from django.views.decorators.http import require_GET, require_POST
from django.views.generic import TemplateView
......@@ -38,6 +38,14 @@ from braces.views import LoginRequiredMixin
from ..store_api import (Store, NoStoreException,
NotOkException)
try:
# Python 2: "unicode" is built-in
unicode
except NameError:
unicode = str
logger = logging.getLogger(__name__)
......
......@@ -14,7 +14,7 @@
#
# You should have received a copy of the GNU General Public License along
# with CIRCLE. If not, see <http://www.gnu.org/licenses/>.
from __future__ import unicode_literals, absolute_import
from datetime import timedelta
import json
......@@ -23,7 +23,7 @@ import logging
from django.contrib import messages
from django.contrib.auth.models import User
from django.contrib.messages.views import SuccessMessageMixin
from django.core.urlresolvers import reverse, reverse_lazy
from django.urls import reverse, reverse_lazy
from django.core.exceptions import PermissionDenied, SuspiciousOperation
from django.db.models import Count
from django.http import HttpResponse, HttpResponseRedirect
......@@ -56,6 +56,18 @@ from .util import (
GraphMixin
)
try:
# Python 2: "unicode" is built-in
unicode
except NameError:
unicode = str
try:
# Python 2: "unicode" is built-in
unicode
except NameError:
unicode = str
logger = logging.getLogger(__name__)
......@@ -199,7 +211,7 @@ class TemplateList(LoginRequiredMixin, FilterMixin, SingleTableView):
leases_w_operator = Lease.get_objects_with_level("operator", user)
context['lease_table'] = LeaseListTable(
leases_w_operator, request=self.request,
template="django_tables2/table_no_page.html",
template_name="django_tables2/table_no_page.html",
)
context['show_lease_table'] = (
leases_w_operator.count() > 0 or
......@@ -272,8 +284,7 @@ class TemplateList(LoginRequiredMixin, FilterMixin, SingleTableView):
return queryset
def get_queryset(self):
logger.debug('TemplateList.get_queryset() called. User: %s',
unicode(self.request.user))
logger.debug('TemplateList.get_queryset() called. User: %s', unicode(self.request.user))
qs = self.create_acl_queryset(InstanceTemplate)
self.create_fake_get()
......
......@@ -14,7 +14,7 @@
#
# You should have received a copy of the GNU General Public License along
# with CIRCLE. If not, see <http://www.gnu.org/licenses/>.
from __future__ import unicode_literals, absolute_import
import json
import logging
......@@ -28,7 +28,7 @@ from django.contrib.auth.models import User, Group
from django.contrib.messages.views import SuccessMessageMixin
from django.core import signing
from django.core.exceptions import PermissionDenied, SuspiciousOperation
from django.core.urlresolvers import reverse, reverse_lazy
from django.urls import reverse, reverse_lazy
from django.core.paginator import Paginator, InvalidPage
from django.db.models import Q
from django.http import HttpResponse, HttpResponseRedirect, Http404
......@@ -39,7 +39,7 @@ from django.views.decorators.http import require_POST
from django.views.generic import (
TemplateView, View, UpdateView, CreateView, FormView
)
from django_sshkey.models import UserKey
from simplesshkey.models import UserKey
from braces.views import LoginRequiredMixin, PermissionRequiredMixin
......@@ -59,6 +59,11 @@ from ..tables import (
from .util import saml_available, DeleteViewBase, LoginView
try:
# Python 2: "unicode" is built-in
unicode
except NameError:
unicode = str
logger = logging.getLogger(__name__)
......@@ -137,7 +142,7 @@ class TokenLogin(View):
@classmethod
def get_salt(cls):
return unicode(cls)
return str(cls)
@classmethod
def get_token(cls, user, sudoer):
......@@ -198,7 +203,7 @@ class MyPreferencesView(UpdateView):
return context
def get_object(self, queryset=None):
if self.request.user.is_anonymous():
if self.request.user.is_anonymous:
raise PermissionDenied()
try:
return self.request.user.profile
......@@ -561,8 +566,7 @@ class UserList(LoginRequiredMixin, PermissionRequiredMixin, SingleTableView):
return super(UserList, self).get(*args, **kwargs)
def get_queryset(self):
logger.debug('UserList.get_queryset() called. User: %s',
unicode(self.request.user))
# logger.debug('UserList.get_queryset() called. User: %s', unicode(self.request.user))
qs = User.objects.all().order_by("-pk")
q = self.search_form.cleaned_data.get('s')
......
......@@ -14,13 +14,13 @@
#
# You should have received a copy of the GNU General Public License along
# with CIRCLE. If not, see <http://www.gnu.org/licenses/>.
from __future__ import unicode_literals, absolute_import
import json
import logging
import re
from collections import OrderedDict
from urlparse import urljoin
from urllib.parse import urljoin
from django.conf import settings
from django.contrib import messages
......@@ -31,7 +31,7 @@ from django.contrib.auth.views import redirect_to_login
from django.contrib.sites.shortcuts import get_current_site
from django.core import signing
from django.core.exceptions import PermissionDenied, SuspiciousOperation
from django.core.urlresolvers import reverse
from django.urls import reverse
from django.db.models import Q, Count, Sum
from django.http import (
HttpResponse, Http404, HttpResponseRedirect, JsonResponse
......@@ -56,6 +56,13 @@ from ..models import GroupProfile, Profile
from ..forms import TransferOwnershipForm
try:
# Python 2: "unicode" is built-in
unicode
except NameError:
unicode = str
logger = logging.getLogger(__name__)
saml_available = hasattr(settings, "SAML_CONFIG")
......@@ -93,7 +100,7 @@ class FilterMixin(object):
filters = {}
excludes = {}
for key, value in self.request.GET.items():
for key, value in list(self.request.GET.items()):
if not key:
continue
exclude = key.startswith('!')
......@@ -133,16 +140,16 @@ class FilterMixin(object):
The final dict looks like this: {'name': xy, 'node':1}
>>> f = FilterMixin()
>>> o = f._parse_get({'s': "hello"}).items()
>>> o = list(f._parse_get({'s': "hello"}).items())
>>> sorted(o) # doctest: +ELLIPSIS
[(u'name', u'hello'), (...)]
>>> o = f._parse_get({'s': "name:hello owner:test"}).items()
>>> o = list(f._parse_get({'s': "name:hello owner:test"}).items())
>>> sorted(o) # doctest: +ELLIPSIS
[(u'name', u'hello'), (u'owner', u'test'), (...)]
>>> o = f._parse_get({'s': "name:hello ws node:node 3 oh"}).items()
>>> o = list(f._parse_get({'s': "name:hello ws node:node 3 oh"}).items())
>>> sorted(o) # doctest: +ELLIPSIS
[(u'name', u'hello ws'), (u'node', u'node 3 oh'), (...)]
>>> o = f._parse_get({'s': "!hello:szia"}).items()
>>> o = list(f._parse_get({'s': "!hello:szia"}).items())
>>> sorted(o) # doctest: +ELLIPSIS
[(u'!hello', u'szia'), (...)]
"""
......@@ -162,7 +169,7 @@ class FilterMixin(object):
got[latest] = s[-1]
# generate a new GET request, that is kinda fake
for k, v in got.iteritems():
for k, v in list(got.items()):
fake[k] = v
return fake
......@@ -305,7 +312,7 @@ class OperationView(RedirectToLoginMixin, DetailView):
result = None
done = False
try:
task = self.get_op().async(user=request.user, **extra)
task = self.get_op()._async(user=request.user, **extra)
except HumanReadableException as e:
e.send_message(request)
logger.exception("Could not start operation")
......@@ -356,7 +363,7 @@ class OperationView(RedirectToLoginMixin, DetailView):
def bind_to_object(cls, instance, **kwargs):
me = cls()
me.get_object = lambda: instance
for key, value in kwargs.iteritems():
for key, value in list(kwargs.items()):
setattr(me, key, value)
return me
......@@ -374,7 +381,7 @@ class AjaxOperationMixin(object):
store = []
return JsonResponse({'success': True,
'with_reload': self.with_reload,
'messages': [unicode(m) for m in store]})
'messages': [str(m) for m in store]})
else:
return resp
......@@ -464,8 +471,8 @@ class AclUpdateView(LoginRequiredMixin, View, SingleObjectMixin):
@classmethod
def has_next_level(self, user, instance, level):
levels = OrderedDict(instance.ACL_LEVELS).keys()
next_levels = dict(zip([None] + levels, levels + levels[-1:]))
levels = list(OrderedDict(instance.ACL_LEVELS).keys())
next_levels = dict(list(zip([None] + levels, levels + levels[-1:])))
# {None: 'user', 'user': 'operator', 'operator: 'owner',
# 'owner: 'owner'}
next_level = next_levels[level]
......@@ -518,19 +525,19 @@ class AclUpdateView(LoginRequiredMixin, View, SingleObjectMixin):
messages.warning(self.request, msg)
elif self.check_auth(whom, old_level, new_level):
logger.info(
u"Set %s's acl level for %s to %s by %s.", unicode(whom),
"Set %s's acl level for %s to %s by %s.", unicode(whom),
unicode(self.instance), new_level, unicode(user))
if not getattr(self, 'hide_messages', False):
self.send_success_message(whom, old_level, new_level)
self.instance.set_level(whom, new_level)
else:
logger.warning(
u"Tried to set %s's acl_level for %s (%s->%s) by %s.",
"Tried to set %s's acl_level for %s (%s->%s) by %s.",
unicode(whom), unicode(self.instance), old_level, new_level,
unicode(user))
def set_or_remove_levels(self):
for key, value in self.request.POST.items():
for key, value in list(self.request.POST.items()):
m = re.match('(perm|remove)-([ug])-(\d+)', key)
if m:
cmd, typ, id = m.groups()
......@@ -809,7 +816,7 @@ class LoginView(FormView):
self.redirect_field_name,
self.request.GET.get(self.redirect_field_name, '')
)
if not is_safe_url(url=redirect_to, host=self.request.get_host()):
if not is_safe_url(url=redirect_to, allowed_hosts=self.request.get_host()):
return resolve_url(settings.LOGIN_REDIRECT_URL)
return redirect_to
......@@ -832,3 +839,4 @@ class LoginView(FormView):
if self.extra_context is not None:
context.update(self.extra_context)
return context
......@@ -14,7 +14,7 @@
#
# You should have received a copy of the GNU General Public License along
# with CIRCLE. If not, see <http://www.gnu.org/licenses/>.
from __future__ import unicode_literals, absolute_import
import json
import logging
......@@ -27,7 +27,7 @@ from django.contrib.auth.models import User
from django.contrib.auth.decorators import login_required
from django.core import signing
from django.core.exceptions import PermissionDenied, SuspiciousOperation
from django.core.urlresolvers import reverse, reverse_lazy
from django.urls import reverse, reverse_lazy
from django.http import (
HttpResponse, Http404, HttpResponseRedirect, JsonResponse
)
......@@ -75,6 +75,13 @@ from request.forms import LeaseRequestForm, TemplateRequestForm
from ..models import Favourite
from manager.scheduler import has_traits
try:
# Python 2: "unicode" is built-in
unicode
except NameError:
unicode = str
logger = logging.getLogger(__name__)
......@@ -97,6 +104,7 @@ class VmDetailVncTokenView(CheckedDetailView):
host = str(self.object.node.host.ipv4)
value = signing.dumps({'host': host, 'port': port},
key=getenv("PROXY_SECRET", 'asdasd')),
logger.debug('vnc host: %s vnc port: %s value: %s', host, port, value)
return HttpResponse('vnc/?d=%s' % value)
else:
raise Http404()
......@@ -205,7 +213,7 @@ class VmDetailView(GraphMixin, CheckedDetailView):
'to_remove': self.__remove_tag,
'abort_operation': self.__abort_operation,
}
for k, v in options.iteritems():
for k, v in list(options.items()):
if request.POST.get(k) is not None:
return v(request)
raise Http404()
......@@ -240,9 +248,9 @@ class VmDetailView(GraphMixin, CheckedDetailView):
raise PermissionDenied()
if len(new_tag) < 1:
message = u"Please input something."
message = "Please input something."
elif len(new_tag) > 20:
message = u"Tag name is too long."
message = "Tag name is too long."
else:
self.object.tags.add(new_tag)
......@@ -262,9 +270,9 @@ class VmDetailView(GraphMixin, CheckedDetailView):
raise PermissionDenied()
self.object.tags.remove(to_remove)
message = u"Success"
message = "Success"
except: # note this won't really happen
message = u"Not success"
message = "Not success"
if request.is_ajax():
return JsonResponse({'message': message})
......@@ -308,14 +316,14 @@ class VmOperationView(AjaxOperationMixin, OperationView):
def get_operations(instance, user):
ops = []
for k, v in vm_ops.iteritems():
for k, v in list(vm_ops.items()):
try:
op = v.get_op_by_object(instance)
op.check_auth(user)
op.check_precond()
except PermissionDenied as e:
logger.debug('Not showing operation %s for %s: %s',
k, instance, unicode(e))
pass
# logger.debug('Not showing operation %s for %s: %s', k, instance, unicode(e))
except Exception:
ops.append(v.bind_to_object(instance, disabled=True))
else:
......@@ -560,7 +568,7 @@ class VmResourcesChangeView(VmOperationView):
store = messages.get_messages(request)
store.used = True
return JsonResponse({'success': False,
'messages': [unicode(m) for m in store]})
'messages': [str(m) for m in store]})
else:
return HttpResponseRedirect(instance.get_absolute_url() +
"#resources")
......@@ -581,7 +589,7 @@ class TokenOperationView(OperationView):
@classmethod
def get_salt(cls):
return unicode(cls)
return str(cls)
@classmethod
def get_token(cls, instance, user):
......@@ -624,20 +632,20 @@ class TokenOperationView(OperationView):
"""
try:
data = signing.loads(key, salt=self.get_salt())
logger.debug('Token data: %s', unicode(data))
logger.debug('Token data: %s', str(data))
instance, user = data
logger.debug('Extracted token data: instance: %s, user: %s',
unicode(instance), unicode(user))
str(instance), str(user))
except (signing.BadSignature, ValueError, TypeError) as e:
logger.warning('Tried invalid token. Token: %s, user: %s. %s',
key, unicode(self.request.user), unicode(e))
key, str(self.request.user), str(e))
raise SuspiciousOperation()
try:
instance, user = signing.loads(key, max_age=self.token_max_age,
salt=self.get_salt())
logger.debug('Extracted non-expired token data: %s, %s',
unicode(instance), unicode(user))
str(instance), str(user))
except signing.BadSignature as e:
raise signing.SignatureExpired()
......@@ -672,7 +680,7 @@ class VmRenewView(FormOperationMixin, TokenOperationView, VmOperationView):
def get_response_data(self, result, done, extra=None, **kwargs):
extra = super(VmRenewView, self).get_response_data(result, done,
extra, **kwargs)
extra["new_suspend_time"] = unicode(self.get_op().
extra["new_suspend_time"] = str(self.get_op().
instance.time_of_suspend)
return extra
......@@ -811,7 +819,7 @@ def _get_activity_icon(act):
op = act.get_operation()
if op and op.id in vm_ops:
return vm_ops[op.id].icon
elif split_activity_code(act.activity_code)[-1] == u'console-accessed':
elif split_activity_code(act.activity_code)[-1] == 'console-accessed':
return "terminal"
else:
return "cog"
......@@ -861,7 +869,7 @@ class MassOperationView(OperationView):
instances = self.get_object()
for i in instances:
try:
self.get_op(i).async(user=user, **extra)
self.get_op(i)._async(user=user, **extra)
except HumanReadableException as e:
e.send_message(request)
except Exception as e:
......@@ -908,7 +916,7 @@ class MassOperationView(OperationView):
store = messages.get_messages(request)
store.used = True
return HttpResponse(
json.dumps({'messages': [unicode(m) for m in store]}),
json.dumps({'messages': [str(m) for m in store]}),
content_type="application/json"
)
else:
......@@ -953,7 +961,7 @@ class VmList(LoginRequiredMixin, FilterMixin, ListView):
def get_context_data(self, *args, **kwargs):
context = super(VmList, self).get_context_data(*args, **kwargs)
context['ops'] = []
for k, v in vm_mass_ops.iteritems():
for k, v in list(vm_mass_ops.items()):
try:
v.check_perms(user=self.request.user)
except PermissionDenied:
......@@ -1017,7 +1025,7 @@ class VmList(LoginRequiredMixin, FilterMixin, ListView):
def get_queryset(self):
logger.debug('VmList.get_queryset() called. User: %s',
unicode(self.request.user))
str(self.request.user))
queryset = self.create_acl_queryset(Instance)
self.create_fake_get()
......@@ -1144,7 +1152,7 @@ class VmCreate(LoginRequiredMixin, TemplateView):
# workaround EncodeError: dictionary changed size during iteration
user = User.objects.get(pk=request.user.pk)
for i in instances:
i.deploy.async(user=user)
i.deploy._async(user=user)
if len(instances) > 1:
messages.success(request, ungettext_lazy(
......
......@@ -24,6 +24,11 @@ from fabric.api import env, run, settings, sudo, prefix, cd, execute
from fabric.context_managers import shell_env
from fabric.decorators import roles, parallel
try:
# Python 2: "unicode" is built-in
unicode
except NameError:
unicode = str
env.roledefs['portal'] = ['localhost']
......@@ -33,7 +38,7 @@ try:
from vm.models import Node as _Node
from storage.models import DataStore as _DataStore
except Exception as e:
print e
print(e)
else:
env.roledefs['node'] = [unicode(n.host.ipv4)
for n in _Node.objects.filter(enabled=True)]
......
......@@ -23,6 +23,12 @@ from firewall.models import (Rule, Host, Vlan, Group, VlanGroup, Firewall,
SwitchPort, EthernetDevice)
from django import contrib
try:
# Python 2: "unicode" is built-in
unicode
except NameError:
unicode = str
class RuleInline(contrib.admin.TabularInline):
model = Rule
......@@ -50,7 +56,7 @@ class HostAdmin(admin.ModelAdmin):
def list_groups(instance):
"""Returns instance's groups' names as a comma-separated list."""
names = [group.name for group in instance.groups.all()]
return u', '.join(names)
return ', '.join(names)
class HostInline(contrib.admin.TabularInline):
......@@ -82,7 +88,7 @@ class RuleAdmin(admin.ModelAdmin):
if instance.direction == '1' else instance.r_type),
'dst': (instance.r_type if instance.direction == '1'
else instance.foreign_network.name),
'para': (u'<span style="color: #00FF00;">' +
'para': ('<span style="color: #00FF00;">' +
(('proto=%s ' % instance.proto)
if instance.proto else '') +
(('sport=%s ' % instance.sport)
......@@ -91,16 +97,16 @@ class RuleAdmin(admin.ModelAdmin):
if instance.dport else '') +
'</span>'),
'desc': instance.description}
return (u'<span style="color: #FF0000;">[%(type)s]</span> '
u'%(src)s<span style="color: #0000FF;"> ▸ </span>%(dst)s '
u'%(para)s %(desc)s') % data
return ('<span style="color: #FF0000;">[%(type)s]</span> '
'%(src)s<span style="color: #0000FF;"> ▸ </span>%(dst)s '
'%(para)s %(desc)s') % data
color_desc.allow_tags = True
@staticmethod
def vlan_l(instance):
"""Returns instance's VLANs' names as a comma-separated list."""
names = [vlan.name for vlan in instance.foreign_network.vlans.all()]
return u', '.join(names)
return ', '.join(names)
@staticmethod
def used_in(instance):
......
......@@ -25,6 +25,11 @@ from netaddr import (IPAddress, IPNetwork, AddrFormatError, ZEROFILL,
EUI, mac_unix, AddrConversionError)
import re
try:
# Python 2: "unicode" is built-in
unicode
except NameError:
unicode = str
alfanum_re = re.compile(r'^[A-Za-z0-9_-]+$')
domain_re = re.compile(r'^([A-Za-z0-9_/-]\.?)+$')
......@@ -39,12 +44,12 @@ class mac_custom(mac_unix):
class MACAddressFormField(forms.Field):
default_error_messages = {
'invalid': _(u'Enter a valid MAC address. %s'),
'invalid': _('Enter a valid MAC address. %s'),
}
def validate(self, value):
try:
return MACAddressField.to_python.im_func(None, value)
return MACAddressField.to_python
except (AddrFormatError, TypeError, ValidationError) as e:
raise ValidationError(self.default_error_messages['invalid']
% unicode(e))
......@@ -62,7 +67,7 @@ class MACAddressField(models.Field):
del kwargs['max_length']
return name, path, args, kwargs
def from_db_value(self, value, expression, connection, context):
def from_db_value(self, value, expression, connection, context=None):
return self.to_python(value)
def to_python(self, value):
......@@ -94,7 +99,7 @@ class MACAddressField(models.Field):
class IPAddressFormField(forms.Field):
default_error_messages = {
'invalid': _(u'Enter a valid IP address. %s'),
'invalid': _('Enter a valid IP address. %s'),
}
def validate(self, value):
......@@ -102,7 +107,7 @@ class IPAddressFormField(forms.Field):
IPAddressField(version=self.version).to_python(value)
except (AddrFormatError, TypeError, ValueError) as e:
raise ValidationError(self.default_error_messages['invalid']
% unicode(e))
% str(e))
def __init__(self, *args, **kwargs):
self.version = kwargs['version']
......@@ -128,7 +133,7 @@ class IPAddressField(models.Field):
def get_internal_type(self):
return "CharField"
def from_db_value(self, value, expression, connection, context):
def from_db_value(self, value, expression, connection, context=None):
return self.to_python(value)
def to_python(self, value):
......@@ -161,7 +166,7 @@ class IPAddressField(models.Field):
class IPNetworkFormField(forms.Field):
default_error_messages = {
'invalid': _(u'Enter a valid IP network. %s'),
'invalid': _('Enter a valid IP network. %s'),
}
def validate(self, value):
......@@ -192,7 +197,7 @@ class IPNetworkField(models.Field):
kwargs['version'] = self.version
return name, path, args, kwargs
def from_db_value(self, value, expression, connection, context):
def from_db_value(self, value, expression, connection, context=None):
return self.to_python(value)
def to_python(self, value):
......@@ -230,7 +235,7 @@ class IPNetworkField(models.Field):
def val_alfanum(value):
"""Validate whether the parameter is a valid alphanumeric value."""
if not alfanum_re.match(value):
raise ValidationError(_(u'%s - only letters, numbers, underscores '
raise ValidationError(_('%s - only letters, numbers, underscores '
'and hyphens are allowed!') % value)
......@@ -247,13 +252,13 @@ def is_valid_domain_wildcard(value):
def val_domain(value):
"""Validate whether the parameter is a valid domin name."""
if not is_valid_domain(value):
raise ValidationError(_(u'%s - invalid domain name') % value)
raise ValidationError(_('%s - invalid domain name') % value)
def val_domain_wildcard(value):
"""Validate whether the parameter is a valid domin name."""
if not is_valid_domain_wildcard(value):
raise ValidationError(_(u'%s - invalid domain name') % value)
raise ValidationError(_('%s - invalid domain name') % value)
def is_valid_reverse_domain(value):
......@@ -264,7 +269,7 @@ def is_valid_reverse_domain(value):
def val_reverse_domain(value):
"""Validate whether the parameter is a valid reverse domain name."""
if not is_valid_reverse_domain(value):
raise ValidationError(u'%s - invalid reverse domain name' % value)
raise ValidationError('%s - invalid reverse domain name' % value)
def val_ipv6_template(value):
......@@ -274,7 +279,7 @@ def val_ipv6_template(value):
>>> val_ipv6_template("123::%(a)d:%(b)d:%(c)d:%(d)d")
>>> val_ipv6_template("::%(a)x:%(b)x:%(c)d:%(d)d")
Don't have to use all bytes from the left (no a):
Don't have to use all unicode from the left (no a):
>>> val_ipv6_template("::%(b)x:%(c)d:%(d)d")
But have to use all ones to the right (a, but no b):
......@@ -331,13 +336,13 @@ def is_valid_ipv4_address(value):
def val_ipv4(value):
"""Validate whether the parameter is a valid IPv4 address."""
if not is_valid_ipv4_address(value):
raise ValidationError(_(u'%s - not an IPv4 address') % value)
raise ValidationError(_('%s - not an IPv4 address') % value)
def val_ipv6(value):
"""Validate whether the parameter is a valid IPv6 address."""
if not is_valid_ipv6_address(value):
raise ValidationError(_(u'%s - not an IPv6 address') % value)
raise ValidationError(_('%s - not an IPv6 address') % value)
def val_mx(value):
......
......@@ -29,6 +29,12 @@ from django.template import loader
from django.utils import timezone
try:
# Python 2: "unicode" is built-in
unicode
except NameError:
unicode = str
settings = django.conf.settings.FIREWALL_SETTINGS
logger = logging.getLogger(__name__)
......@@ -39,7 +45,7 @@ class BuildFirewall:
self.chains = OrderedDict()
def add_rules(self, *args, **kwargs):
for chain_name, ipt_rule in kwargs.items():
for chain_name, ipt_rule in list(kwargs.items()):
if chain_name not in self.chains:
self.create_chain(chain_name)
self.chains[chain_name].add(ipt_rule)
......@@ -115,7 +121,7 @@ class BuildFirewall:
def ipt_filter_vlan_drop(self):
"""Close intra-VLAN chains."""
for chain in self.chains.values():
for chain in list(self.chains.values()):
close_chain_rule = IptRule(priority=1, action='LOG_DROP')
chain.add(close_chain_rule)
......@@ -145,9 +151,9 @@ class BuildFirewall:
self.build_ipt_nat()
context = {
'filter': lambda: (chain for name, chain in self.chains.iteritems()
'filter': lambda: (chain for name, chain in list(self.chains.items())
if chain.name not in IptChain.nat_chains),
'nat': lambda: (chain for name, chain in self.chains.iteritems()
'nat': lambda: (chain for name, chain in list(self.chains.items())
if chain.name in IptChain.nat_chains)}
template = loader.get_template('firewall/iptables.conf')
......
......@@ -64,7 +64,7 @@ class IptRule(object):
self.comment = comment
def __hash__(self):
return hash(frozenset(self.__dict__.items()))
return hash(frozenset(list(self.__dict__.items())))
def __eq__(self, other):
return self.__dict__ == other.__dict__
......@@ -75,7 +75,7 @@ class IptRule(object):
def __repr__(self):
return '<IptRule: @%d %s >' % (self.priority, self.compile())
def __unicode__(self):
def __str__(self):
return self.__repr__()
def compile(self, proto='ipv4'):
......@@ -114,7 +114,7 @@ class IptChain(object):
def __repr__(self):
return '<IptChain: %s %s>' % (self.name, self.rules)
def __unicode__(self):
def __str__(self):
return self.__repr__()
def compile(self, proto='ipv4'):
......
......@@ -12,7 +12,7 @@
# You should have received a copy of the GNU General Public License along
# with CIRCLE. If not, see <http://www.gnu.org/licenses/>.
from __future__ import unicode_literals, absolute_import
from django.core.management.base import BaseCommand, CommandError
import logging
......@@ -121,7 +121,7 @@ class Command(BaseCommand):
rules = []
for port in xrange(lower, higher+1):
for port in range(lower, higher+1):
try:
rule = self.make_rule(port, proto, action, dir,
owner, firewall, fnet)
......@@ -137,7 +137,7 @@ class Command(BaseCommand):
if not created:
raise Warning(('Rule does exist: %s' %
unicode(rule)).encode('utf-8'))
str(rule)).encode('utf-8'))
rule.full_clean()
......
......@@ -15,7 +15,7 @@
# You should have received a copy of the GNU General Public License along
# with CIRCLE. If not, see <http://www.gnu.org/licenses/>.
from __future__ import unicode_literals, absolute_import
from django.core.management.base import BaseCommand
......
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
import firewall.fields
......
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
......@@ -30,7 +30,7 @@ class Migration(migrations.Migration):
migrations.AlterField(
model_name='blacklistitem',
name='ipv4',
field=models.GenericIPAddressField(protocol=b'ipv4', unique=True, verbose_name=b'IPv4 address'),
field=models.GenericIPAddressField(protocol='ipv4', unique=True, verbose_name='IPv4 address'),
preserve_default=True,
),
migrations.AlterField(
......
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
......
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
......
# -*- coding: utf-8 -*-
# Generated by Django 1.11.3 on 2017-07-07 19:09
from __future__ import unicode_literals
from django.db import migrations
import firewall.fields
......
# Generated by Django 3.2.8 on 2021-11-02 13:31
import common.models
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('firewall', '0006_auto_20170707_1909'),
]
operations = [
migrations.AlterField(
model_name='host',
name='normalized_hostname',
field=common.models.HumanSortField(blank=True, default='', max_length=80, monitor='hostname'),
),
migrations.AlterField(
model_name='record',
name='type',
field=models.CharField(choices=[('A', 'A'), ('CNAME', 'CNAME'), ('AAAA', 'AAAA'), ('MX', 'MX'), ('NS', 'NS'), ('PTR', 'PTR'), ('TXT', 'TXT')], max_length=6, verbose_name='type'),
),
migrations.AlterField(
model_name='rule',
name='action',
field=models.CharField(choices=[('accept', 'accept'), ('drop', 'drop'), ('ignore', 'ignore')], default='drop', help_text='Accept, drop or ignore the matching packets.', max_length=10, verbose_name='action'),
),
migrations.AlterField(
model_name='rule',
name='direction',
field=models.CharField(choices=[('out', 'out'), ('in', 'in')], help_text='If the rule matches egress or ingress packets.', max_length=3, verbose_name='direction'),
),
migrations.AlterField(
model_name='rule',
name='proto',
field=models.CharField(blank=True, choices=[('tcp', 'tcp'), ('udp', 'udp'), ('icmp', 'icmp')], help_text='Protocol of packets that match.', max_length=10, null=True, verbose_name='protocol'),
),
]
......@@ -63,22 +63,22 @@ def get_firewall_queues():
@celery.task
def reloadtask_worker():
from firewall.fw import BuildFirewall, dhcp, dns, ipset, vlan
from remote_tasks import (reload_dns, reload_dhcp, reload_firewall,
from firewall.tasks.remote_tasks import (reload_dns, reload_dhcp, reload_firewall,
reload_firewall_vlan, reload_blacklist)
tasks = []
for i in ('dns', 'dhcp', 'firewall', 'firewall_vlan', 'blacklist'):
lockname = "%s_lock" % i
if cache.get(lockname):
tasks.append(i)
cache.delete(lockname)
# if cache.get(lockname):
tasks.append(i)
# cache.delete(lockname)
logger.info("reloadtask_worker: Reload %s", ", ".join(tasks))
firewall_queues = get_firewall_queues()
dns_queues = settings.get('dns_queues', [gethostname()])
if isinstance(dns_queues, (str, unicode)):
if isinstance(dns_queues, str):
dns_queues = [dns_queues]
dns_queues = [("%s.dns" % i) for i in dns_queues]
......
......@@ -31,7 +31,7 @@ def check_queue(firewall, queue_id, priority):
if active_queues is None:
return False
queue_names = (queue['name'] for worker in active_queues.itervalues()
queue_names = (queue['name'] for worker in active_queues.values()
for queue in worker)
return queue_name in queue_names
......
......@@ -135,7 +135,7 @@ class HostGetHostnameTestCase(MockCeleryMixin, TestCase):
def test_issue_93_wo_record(self):
self.assertEqual(self.h.get_hostname(proto='ipv4', public=True),
unicode(self.h.external_ipv4))
str(self.h.external_ipv4))
def test_issue_93_w_record(self):
self.r = Record(name='vm', type='A', domain=self.d, owner=self.u1,
......@@ -176,7 +176,7 @@ class IptablesTestCase(TestCase):
self.assertEqual(len(ch), len(self.r) - 1)
def test_rule_compile_ok(self):
assert unicode(self.r[5])
assert str(self.r[5])
self.assertEqual(self.r[5].compile(),
'-d 127.0.0.5 -p tcp --dport 443 -g ACCEPT')
......@@ -193,7 +193,7 @@ class IptablesTestCase(TestCase):
ch.add(*self.r)
compiled = ch.compile()
compiled_v6 = ch.compile_v6()
assert unicode(ch)
assert str(ch)
self.assertEqual(len(compiled.splitlines()), len(ch))
self.assertEqual(len(compiled_v6.splitlines()), 0)
......
......@@ -15,7 +15,7 @@
# You should have received a copy of the GNU General Public License along
# with CIRCLE. If not, see <http://www.gnu.org/licenses/>.
from __future__ import absolute_import, unicode_literals
from datetime import timedelta
from json import dumps
......@@ -36,6 +36,13 @@ from .models import BlacklistItem, Host
from django.conf import settings
try:
# Python 2: "unicode" is built-in
unicode
except NameError:
unicode = str
logger = logging.getLogger(__name__)
......
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment