Commit 9d40ae4f by Csók Tamás

Merge remote-tracking branch 'origin/master' into issue-218

Conflicts:
	requirements/test.txt
parents 82870d16 082389aa
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import datetime from __future__ import unicode_literals
from south.db import db
from south.v2 import SchemaMigration from django.db import models, migrations
from django.db import models from django.conf import settings
class Migration(SchemaMigration): class Migration(migrations.Migration):
def forwards(self, orm): dependencies = [
# Adding model 'Level' ('auth', '0001_initial'),
db.create_table(u'acl_level', ( migrations.swappable_dependency(settings.AUTH_USER_MODEL),
(u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), ('contenttypes', '0001_initial'),
('name', self.gf('django.db.models.fields.CharField')(max_length=50)), ]
('content_type', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['contenttypes.ContentType'])),
('codename', self.gf('django.db.models.fields.CharField')(max_length=100)), operations = [
('weight', self.gf('django.db.models.fields.IntegerField')(null=True)), migrations.CreateModel(
)) name='Level',
db.send_create_signal(u'acl', ['Level']) fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
# Adding unique constraint on 'Level', fields ['content_type', 'codename'] ('name', models.CharField(max_length=50, verbose_name=b'name')),
db.create_unique(u'acl_level', ['content_type_id', 'codename']) ('codename', models.CharField(max_length=100, verbose_name=b'codename')),
('weight', models.IntegerField(null=True, verbose_name=b'weight')),
# Adding model 'ObjectLevel' ('content_type', models.ForeignKey(to='contenttypes.ContentType')),
db.create_table(u'acl_objectlevel', ( ],
(u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), options={
('level', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['acl.Level'])), },
('content_type', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['contenttypes.ContentType'])), bases=(models.Model,),
('object_id', self.gf('django.db.models.fields.CharField')(max_length=255)), ),
)) migrations.CreateModel(
db.send_create_signal(u'acl', ['ObjectLevel']) name='ObjectLevel',
fields=[
# Adding unique constraint on 'ObjectLevel', fields ['content_type', 'object_id', 'level'] ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
db.create_unique(u'acl_objectlevel', ['content_type_id', 'object_id', 'level_id']) ('object_id', models.IntegerField()),
('content_type', models.ForeignKey(to='contenttypes.ContentType')),
# Adding M2M table for field users on 'ObjectLevel' ('groups', models.ManyToManyField(to='auth.Group')),
m2m_table_name = db.shorten_name(u'acl_objectlevel_users') ('level', models.ForeignKey(to='acl.Level')),
db.create_table(m2m_table_name, ( ('users', models.ManyToManyField(to=settings.AUTH_USER_MODEL)),
('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), ],
('objectlevel', models.ForeignKey(orm[u'acl.objectlevel'], null=False)), options={
('user', models.ForeignKey(orm[u'auth.user'], null=False)) },
)) bases=(models.Model,),
db.create_unique(m2m_table_name, ['objectlevel_id', 'user_id']) ),
migrations.AlterUniqueTogether(
# Adding M2M table for field groups on 'ObjectLevel' name='objectlevel',
m2m_table_name = db.shorten_name(u'acl_objectlevel_groups') unique_together=set([('content_type', 'object_id', 'level')]),
db.create_table(m2m_table_name, ( ),
('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), migrations.AlterUniqueTogether(
('objectlevel', models.ForeignKey(orm[u'acl.objectlevel'], null=False)), name='level',
('group', models.ForeignKey(orm[u'auth.group'], null=False)) unique_together=set([('content_type', 'codename')]),
)) ),
db.create_unique(m2m_table_name, ['objectlevel_id', 'group_id']) ]
def backwards(self, orm):
# Removing unique constraint on 'ObjectLevel', fields ['content_type', 'object_id', 'level']
db.delete_unique(u'acl_objectlevel', ['content_type_id', 'object_id', 'level_id'])
# Removing unique constraint on 'Level', fields ['content_type', 'codename']
db.delete_unique(u'acl_level', ['content_type_id', 'codename'])
# Deleting model 'Level'
db.delete_table(u'acl_level')
# Deleting model 'ObjectLevel'
db.delete_table(u'acl_objectlevel')
# Removing M2M table for field users on 'ObjectLevel'
db.delete_table(db.shorten_name(u'acl_objectlevel_users'))
# Removing M2M table for field groups on 'ObjectLevel'
db.delete_table(db.shorten_name(u'acl_objectlevel_groups'))
models = {
u'acl.level': {
'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Level'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
'weight': ('django.db.models.fields.IntegerField', [], {'null': 'True'})
},
u'acl.objectlevel': {
'Meta': {'unique_together': "(('content_type', 'object_id', 'level'),)", 'object_name': 'ObjectLevel'},
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'level': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['acl.Level']"}),
'object_id': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'users': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.User']", 'symmetrical': 'False'})
},
u'auth.group': {
'Meta': {'object_name': 'Group'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
u'auth.permission': {
'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
u'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
u'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
}
}
complete_apps = ['acl']
\ No newline at end of file
# -*- coding: utf-8 -*-
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Adding model 'Level'
db.create_table(u'acl_level', (
(u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('name', self.gf('django.db.models.fields.CharField')(max_length=50)),
('content_type', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['contenttypes.ContentType'])),
('codename', self.gf('django.db.models.fields.CharField')(max_length=100)),
('weight', self.gf('django.db.models.fields.IntegerField')(null=True)),
))
db.send_create_signal(u'acl', ['Level'])
# Adding unique constraint on 'Level', fields ['content_type', 'codename']
db.create_unique(u'acl_level', ['content_type_id', 'codename'])
# Adding model 'ObjectLevel'
db.create_table(u'acl_objectlevel', (
(u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('level', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['acl.Level'])),
('content_type', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['contenttypes.ContentType'])),
('object_id', self.gf('django.db.models.fields.CharField')(max_length=255)),
))
db.send_create_signal(u'acl', ['ObjectLevel'])
# Adding unique constraint on 'ObjectLevel', fields ['content_type', 'object_id', 'level']
db.create_unique(u'acl_objectlevel', ['content_type_id', 'object_id', 'level_id'])
# Adding M2M table for field users on 'ObjectLevel'
m2m_table_name = db.shorten_name(u'acl_objectlevel_users')
db.create_table(m2m_table_name, (
('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
('objectlevel', models.ForeignKey(orm[u'acl.objectlevel'], null=False)),
('user', models.ForeignKey(orm[u'auth.user'], null=False))
))
db.create_unique(m2m_table_name, ['objectlevel_id', 'user_id'])
# Adding M2M table for field groups on 'ObjectLevel'
m2m_table_name = db.shorten_name(u'acl_objectlevel_groups')
db.create_table(m2m_table_name, (
('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
('objectlevel', models.ForeignKey(orm[u'acl.objectlevel'], null=False)),
('group', models.ForeignKey(orm[u'auth.group'], null=False))
))
db.create_unique(m2m_table_name, ['objectlevel_id', 'group_id'])
def backwards(self, orm):
# Removing unique constraint on 'ObjectLevel', fields ['content_type', 'object_id', 'level']
db.delete_unique(u'acl_objectlevel', ['content_type_id', 'object_id', 'level_id'])
# Removing unique constraint on 'Level', fields ['content_type', 'codename']
db.delete_unique(u'acl_level', ['content_type_id', 'codename'])
# Deleting model 'Level'
db.delete_table(u'acl_level')
# Deleting model 'ObjectLevel'
db.delete_table(u'acl_objectlevel')
# Removing M2M table for field users on 'ObjectLevel'
db.delete_table(db.shorten_name(u'acl_objectlevel_users'))
# Removing M2M table for field groups on 'ObjectLevel'
db.delete_table(db.shorten_name(u'acl_objectlevel_groups'))
models = {
u'acl.level': {
'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Level'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
'weight': ('django.db.models.fields.IntegerField', [], {'null': 'True'})
},
u'acl.objectlevel': {
'Meta': {'unique_together': "(('content_type', 'object_id', 'level'),)", 'object_name': 'ObjectLevel'},
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'level': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['acl.Level']"}),
'object_id': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'users': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.User']", 'symmetrical': 'False'})
},
u'auth.group': {
'Meta': {'object_name': 'Group'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
u'auth.permission': {
'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
u'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
u'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
}
}
complete_apps = ['acl']
\ No newline at end of file
...@@ -15,29 +15,4 @@ ...@@ -15,29 +15,4 @@
# You should have received a copy of the GNU General Public License along # You should have received a copy of the GNU General Public License along
# with CIRCLE. If not, see <http://www.gnu.org/licenses/>. # with CIRCLE. If not, see <http://www.gnu.org/licenses/>.
from django.db.models import TextField, ForeignKey from .test_acl import TestModel, Test2Model # noqa
from django.contrib.auth.models import User
from ..models import AclBase
class TestModel(AclBase):
normal_field = TextField()
ACL_LEVELS = (
('alfa', 'Alfa'),
('bravo', 'Bravo'),
('charlie', 'Charlie'),
)
class Test2Model(AclBase):
normal2_field = TextField()
owner = ForeignKey(User, null=True)
ACL_LEVELS = (
('one', 'One'),
('two', 'Two'),
('three', 'Three'),
('owner', 'owner'),
)
...@@ -17,9 +17,31 @@ ...@@ -17,9 +17,31 @@
from django.test import TestCase from django.test import TestCase
from django.contrib.auth.models import User, Group, AnonymousUser from django.contrib.auth.models import User, Group, AnonymousUser
from django.db.models import TextField, ForeignKey
from ..models import ObjectLevel from ..models import ObjectLevel, AclBase
from .models import TestModel, Test2Model
class TestModel(AclBase):
normal_field = TextField()
ACL_LEVELS = (
('alfa', 'Alfa'),
('bravo', 'Bravo'),
('charlie', 'Charlie'),
)
class Test2Model(AclBase):
normal2_field = TextField()
owner = ForeignKey(User, null=True)
ACL_LEVELS = (
('one', 'One'),
('two', 'Two'),
('three', 'Three'),
('owner', 'owner'),
)
class AclUserTest(TestCase): class AclUserTest(TestCase):
......
...@@ -18,6 +18,8 @@ ...@@ -18,6 +18,8 @@
"jquery-knob": "~1.2.9", "jquery-knob": "~1.2.9",
"jquery-simple-slider": "https://github.com/BME-IK/jquery-simple-slider.git", "jquery-simple-slider": "https://github.com/BME-IK/jquery-simple-slider.git",
"bootbox": "~4.3.0", "bootbox": "~4.3.0",
"intro.js": "0.9.0" "intro.js": "0.9.0",
"favico.js": "~0.3.5",
"datatables": "~1.10.4"
} }
} }
...@@ -50,20 +50,20 @@ def get_env_variable(var_name, default=None): ...@@ -50,20 +50,20 @@ def get_env_variable(var_name, default=None):
########## PATH CONFIGURATION ########## PATH CONFIGURATION
# Absolute filesystem path to the Django project directory: # Absolute filesystem path to the Django project directory:
DJANGO_ROOT = dirname(dirname(abspath(__file__))) BASE_DIR = dirname(dirname(abspath(__file__)))
# Absolute filesystem path to the top-level project folder: # Absolute filesystem path to the top-level project folder:
SITE_ROOT = dirname(DJANGO_ROOT) SITE_ROOT = dirname(BASE_DIR)
# Site name: # Site name:
SITE_NAME = basename(DJANGO_ROOT) SITE_NAME = basename(BASE_DIR)
# Url to site: (e.g. http://localhost:8080/) # Url to site: (e.g. http://localhost:8080/)
DJANGO_URL = get_env_variable('DJANGO_URL', '/') DJANGO_URL = get_env_variable('DJANGO_URL', '/')
# Add our project to our pythonpath, this way we don't need to type our project # Add our project to our pythonpath, this way we don't need to type our project
# name in our dotted import paths: # name in our dotted import paths:
path.append(DJANGO_ROOT) path.append(BASE_DIR)
########## END PATH CONFIGURATION ########## END PATH CONFIGURATION
...@@ -78,14 +78,9 @@ TEMPLATE_DEBUG = DEBUG ...@@ -78,14 +78,9 @@ TEMPLATE_DEBUG = DEBUG
########## MANAGER CONFIGURATION ########## MANAGER CONFIGURATION
# See: https://docs.djangoproject.com/en/dev/ref/settings/#admins # See: https://docs.djangoproject.com/en/dev/ref/settings/#admins
ADMINS = (
('Root', 'root@localhost'),
)
EMAIL_SUBJECT_PREFIX = get_env_variable('DJANGO_SUBJECT_PREFIX', '[CIRCLE] ') EMAIL_SUBJECT_PREFIX = get_env_variable('DJANGO_SUBJECT_PREFIX', '[CIRCLE] ')
# See: https://docs.djangoproject.com/en/dev/ref/settings/#managers
MANAGERS = ADMINS
########## END MANAGER CONFIGURATION ########## END MANAGER CONFIGURATION
...@@ -197,7 +192,10 @@ PIPELINE_JS = { ...@@ -197,7 +192,10 @@ PIPELINE_JS = {
"intro.js/intro.js", "intro.js/intro.js",
"jquery-knob/dist/jquery.knob.min.js", "jquery-knob/dist/jquery.knob.min.js",
"jquery-simple-slider/js/simple-slider.js", "jquery-simple-slider/js/simple-slider.js",
"favico.js/favico.js",
"datatables/media/js/jquery.dataTables.js",
"dashboard/dashboard.js", "dashboard/dashboard.js",
"dashboard/activity.js",
"dashboard/group-details.js", "dashboard/group-details.js",
"dashboard/group-list.js", "dashboard/group-list.js",
"dashboard/js/stupidtable.min.js", # no bower file "dashboard/js/stupidtable.min.js", # no bower file
...@@ -213,6 +211,7 @@ PIPELINE_JS = { ...@@ -213,6 +211,7 @@ PIPELINE_JS = {
"js/host.js", "js/host.js",
"js/network.js", "js/network.js",
"js/switch-port.js", "js/switch-port.js",
"js/host-list.js",
"autocomplete_light/autocomplete.js", "autocomplete_light/autocomplete.js",
"autocomplete_light/widget.js", "autocomplete_light/widget.js",
"autocomplete_light/addanother.js", "autocomplete_light/addanother.js",
...@@ -281,12 +280,6 @@ TEMPLATE_CONTEXT_PROCESSORS = ( ...@@ -281,12 +280,6 @@ TEMPLATE_CONTEXT_PROCESSORS = (
'dashboard.context_processors.extract_settings', 'dashboard.context_processors.extract_settings',
) )
# See: https://docs.djangoproject.com/en/dev/ref/settings/#template-loaders
TEMPLATE_LOADERS = (
'django.template.loaders.filesystem.Loader',
'django.template.loaders.app_directories.Loader',
)
# See: https://docs.djangoproject.com/en/dev/ref/settings/#template-dirs # See: https://docs.djangoproject.com/en/dev/ref/settings/#template-dirs
TEMPLATE_DIRS = ( TEMPLATE_DIRS = (
normpath(join(SITE_ROOT, '../../site-circle/templates')), normpath(join(SITE_ROOT, '../../site-circle/templates')),
...@@ -335,7 +328,6 @@ DJANGO_APPS = ( ...@@ -335,7 +328,6 @@ DJANGO_APPS = (
) )
THIRD_PARTY_APPS = ( THIRD_PARTY_APPS = (
'south',
'django_tables2', 'django_tables2',
'crispy_forms', 'crispy_forms',
'djcelery', 'djcelery',
...@@ -347,6 +339,11 @@ THIRD_PARTY_APPS = ( ...@@ -347,6 +339,11 @@ THIRD_PARTY_APPS = (
'pipeline', 'pipeline',
) )
import django
if django.get_version() < '1.7':
THIRD_PARTY_APPS += 'south',
# Apps specific for this project go here. # Apps specific for this project go here.
LOCAL_APPS = ( LOCAL_APPS = (
'common', 'common',
...@@ -531,8 +528,14 @@ LOCALE_PATHS = (join(SITE_ROOT, 'locale'), ) ...@@ -531,8 +528,14 @@ LOCALE_PATHS = (join(SITE_ROOT, 'locale'), )
COMPANY_NAME = "BME IK 2014" COMPANY_NAME = "BME IK 2014"
SOUTH_MIGRATION_MODULES = { SOUTH_MIGRATION_MODULES = {
'taggit': 'taggit.south_migrations', 'taggit': 'taggit.south_migrations',
'vm': 'vm.south_migrations',
'firewall': 'firewall.south_migrations',
'acl': 'acl.south_migrations',
'dashboard': 'dashboard.south_migrations',
'storage': 'storage.south_migrations',
} }
graphite_host = environ.get("GRAPHITE_HOST", None) graphite_host = environ.get("GRAPHITE_HOST", None)
graphite_port = environ.get("GRAPHITE_PORT", None) graphite_port = environ.get("GRAPHITE_PORT", None)
if graphite_host and graphite_port: if graphite_host and graphite_port:
......
...@@ -43,7 +43,7 @@ EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' ...@@ -43,7 +43,7 @@ EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
# DATABASES = { # DATABASES = {
# 'default': { # 'default': {
# 'ENGINE': 'django.db.backends.sqlite3', # 'ENGINE': 'django.db.backends.sqlite3',
# 'NAME': normpath(join(DJANGO_ROOT, 'default.db')), # 'NAME': normpath(join(BASE_DIR, 'default.db')),
# 'USER': '', # 'USER': '',
# 'PASSWORD': '', # 'PASSWORD': '',
# 'HOST': '', # 'HOST': '',
......
...@@ -370,6 +370,12 @@ class HumanSortField(CharField): ...@@ -370,6 +370,12 @@ class HumanSortField(CharField):
def get_monitored_value(self, instance): def get_monitored_value(self, instance):
return getattr(instance, self.monitor) return getattr(instance, self.monitor)
def deconstruct(self):
name, path, args, kwargs = super(HumanSortField, self).deconstruct()
if self.monitor is not None:
kwargs['monitor'] = self.monitor
return name, path, args, kwargs
@staticmethod @staticmethod
def _partition(s, pred): def _partition(s, pred):
"""Partition a deque of chars to a tuple of a """Partition a deque of chars to a tuple of a
......
...@@ -282,6 +282,8 @@ def register_operation(op_cls, op_id=None, target_cls=None): ...@@ -282,6 +282,8 @@ def register_operation(op_cls, op_id=None, target_cls=None):
"in the 'target_cls' parameter to this " "in the 'target_cls' parameter to this "
"call.") "call.")
assert not hasattr(target_cls, op_id), (
"target class already has an attribute with this id")
if not issubclass(target_cls, OperatedMixin): if not issubclass(target_cls, OperatedMixin):
raise TypeError("%r is not a subclass of %r" % raise TypeError("%r is not a subclass of %r" %
(target_cls.__name__, OperatedMixin.__name__)) (target_cls.__name__, OperatedMixin.__name__))
......
...@@ -41,6 +41,7 @@ from django.forms.widgets import TextInput, HiddenInput ...@@ -41,6 +41,7 @@ from django.forms.widgets import TextInput, HiddenInput
from django.template import Context from django.template import Context
from django.template.loader import render_to_string from django.template.loader import render_to_string
from django.utils.html import escape, format_html from django.utils.html import escape, format_html
from django.utils.safestring import mark_safe
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from sizefield.widgets import FileSizeWidget from sizefield.widgets import FileSizeWidget
from django.core.urlresolvers import reverse_lazy from django.core.urlresolvers import reverse_lazy
...@@ -58,7 +59,7 @@ from django.utils.translation import string_concat ...@@ -58,7 +59,7 @@ from django.utils.translation import string_concat
from .validators import domain_validator from .validators import domain_validator
from dashboard.models import ConnectCommand from dashboard.models import ConnectCommand, create_profile
LANGUAGES_WITH_CODE = ((l[0], string_concat(l[1], " (", l[0], ")")) LANGUAGES_WITH_CODE = ((l[0], string_concat(l[1], " (", l[0], ")"))
for l in LANGUAGES) for l in LANGUAGES)
...@@ -95,10 +96,10 @@ class VmSaveForm(OperationForm): ...@@ -95,10 +96,10 @@ class VmSaveForm(OperationForm):
if default: if default:
self.fields['name'].initial = default self.fields['name'].initial = default
if clone: if clone:
self.fields.insert(2, "clone", forms.BooleanField( self.fields["clone"] = forms.BooleanField(
required=False, label=_("Clone template permissions"), required=False, label=_("Clone template permissions"),
help_text=_("Clone the access list of parent template. Useful " help_text=_("Clone the access list of parent template. Useful "
"for updating a template."))) "for updating a template."))
class VmCustomizeForm(forms.Form): class VmCustomizeForm(forms.Form):
...@@ -749,9 +750,9 @@ class VmRenewForm(OperationForm): ...@@ -749,9 +750,9 @@ class VmRenewForm(OperationForm):
default = kwargs.pop('default') default = kwargs.pop('default')
super(VmRenewForm, self).__init__(*args, **kwargs) super(VmRenewForm, self).__init__(*args, **kwargs)
self.fields.insert(0, 'lease', forms.ModelChoiceField( self.fields['lease'] = forms.ModelChoiceField(
queryset=choices, initial=default, required=False, queryset=choices, initial=default, required=False,
empty_label=None, label=_('Length'))) empty_label=None, label=_('Length'))
if len(choices) < 2: if len(choices) < 2:
self.fields['lease'].widget = HiddenInput() self.fields['lease'].widget = HiddenInput()
self.fields['save'].widget = HiddenInput() self.fields['save'].widget = HiddenInput()
...@@ -771,9 +772,9 @@ class VmMigrateForm(forms.Form): ...@@ -771,9 +772,9 @@ class VmMigrateForm(forms.Form):
default = kwargs.pop('default') default = kwargs.pop('default')
super(VmMigrateForm, self).__init__(*args, **kwargs) super(VmMigrateForm, self).__init__(*args, **kwargs)
self.fields.insert(0, 'to_node', forms.ModelChoiceField( self.fields['to_node'] = forms.ModelChoiceField(
queryset=choices, initial=default, required=False, queryset=choices, initial=default, required=False,
widget=forms.RadioSelect(), label=_("Node"))) widget=forms.RadioSelect(), label=_("Node"))
class VmStateChangeForm(OperationForm): class VmStateChangeForm(OperationForm):
...@@ -834,9 +835,9 @@ class VmDiskResizeForm(OperationForm): ...@@ -834,9 +835,9 @@ class VmDiskResizeForm(OperationForm):
super(VmDiskResizeForm, self).__init__(*args, **kwargs) super(VmDiskResizeForm, self).__init__(*args, **kwargs)
self.fields.insert(0, 'disk', forms.ModelChoiceField( self.fields['disk'] = forms.ModelChoiceField(
queryset=choices, initial=self.disk, required=True, queryset=choices, initial=self.disk, required=True,
empty_label=None, label=_('Disk'))) empty_label=None, label=_('Disk'))
if self.disk: if self.disk:
self.fields['disk'].widget = HiddenInput() self.fields['disk'].widget = HiddenInput()
self.fields['size'].initial += self.disk.size self.fields['size'].initial += self.disk.size
...@@ -870,9 +871,9 @@ class VmDiskRemoveForm(OperationForm): ...@@ -870,9 +871,9 @@ class VmDiskRemoveForm(OperationForm):
super(VmDiskRemoveForm, self).__init__(*args, **kwargs) super(VmDiskRemoveForm, self).__init__(*args, **kwargs)
self.fields.insert(0, 'disk', forms.ModelChoiceField( self.fields['disk'] = forms.ModelChoiceField(
queryset=choices, initial=self.disk, required=True, queryset=choices, initial=self.disk, required=True,
empty_label=None, label=_('Disk'))) empty_label=None, label=_('Disk'))
if self.disk: if self.disk:
self.fields['disk'].widget = HiddenInput() self.fields['disk'].widget = HiddenInput()
...@@ -898,7 +899,7 @@ class VmDownloadDiskForm(OperationForm): ...@@ -898,7 +899,7 @@ class VmDownloadDiskForm(OperationForm):
def clean(self): def clean(self):
cleaned_data = super(VmDownloadDiskForm, self).clean() cleaned_data = super(VmDownloadDiskForm, self).clean()
if not cleaned_data['name']: if not cleaned_data['name']:
if cleaned_data['url']: if cleaned_data.get('url'):
cleaned_data['name'] = urlparse( cleaned_data['name'] = urlparse(
cleaned_data['url']).path.split('/')[-1] cleaned_data['url']).path.split('/')[-1]
if not cleaned_data['name']: if not cleaned_data['name']:
...@@ -908,6 +909,36 @@ class VmDownloadDiskForm(OperationForm): ...@@ -908,6 +909,36 @@ class VmDownloadDiskForm(OperationForm):
return cleaned_data return cleaned_data
class VmRemoveInterfaceForm(OperationForm):
def __init__(self, *args, **kwargs):
choices = kwargs.pop('choices')
self.interface = kwargs.pop('default')
super(VmRemoveInterfaceForm, self).__init__(*args, **kwargs)
self.fields['interface'] = forms.ModelChoiceField(
queryset=choices, initial=self.interface, required=True,
empty_label=None, label=_('Interface'))
if self.interface:
self.fields['interface'].widget = HiddenInput()
@property
def helper(self):
helper = super(VmRemoveInterfaceForm, self).helper
if self.interface:
helper.layout = Layout(
AnyTag(
"div",
HTML(format_html(
_("<label>Vlan:</label> {0}"),
self.interface.vlan)),
css_class="form-group",
),
Field("interface"),
)
return helper
class VmAddInterfaceForm(OperationForm): class VmAddInterfaceForm(OperationForm):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
choices = kwargs.pop('choices') choices = kwargs.pop('choices')
...@@ -921,18 +952,45 @@ class VmAddInterfaceForm(OperationForm): ...@@ -921,18 +952,45 @@ class VmAddInterfaceForm(OperationForm):
self.fields['vlan'] = field self.fields['vlan'] = field
class DeployChoiceField(forms.ModelChoiceField):
def __init__(self, *args, **kwargs):
self.instance = kwargs.pop("instance")
super(DeployChoiceField, self).__init__(*args, **kwargs)
def label_from_instance(self, obj):
traits = set(obj.traits.all())
req_traits = set(self.instance.req_traits.all())
# if the subset is empty the node satisfies the required traits
subset = req_traits - traits
label = "%s %s" % (
"&#xf071" if subset else "&#xf00c;", escape(obj.name),
)
if subset:
missing_traits = ", ".join(map(lambda x: escape(x.name), subset))
label += _(" (missing_traits: %s)") % missing_traits
return mark_safe(label)
class VmDeployForm(OperationForm): class VmDeployForm(OperationForm):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
choices = kwargs.pop('choices', None) choices = kwargs.pop('choices', None)
instance = kwargs.pop('instance', None)
super(VmDeployForm, self).__init__(*args, **kwargs) super(VmDeployForm, self).__init__(*args, **kwargs)
if choices is not None: if choices is not None:
self.fields.insert(0, 'node', forms.ModelChoiceField( self.fields['node'] = DeployChoiceField(
queryset=choices, required=False, label=_('Node'), help_text=_( queryset=choices, required=False, label=_('Node'), help_text=_(
"Deploy virtual machine to this node " "Deploy virtual machine to this node "
"(blank allows scheduling automatically)."))) "(blank allows scheduling automatically)."),
widget=forms.Select(attrs={
'class': "font-awesome-font",
}), instance=instance
)
class VmPortRemoveForm(OperationForm): class VmPortRemoveForm(OperationForm):
...@@ -942,9 +1000,9 @@ class VmPortRemoveForm(OperationForm): ...@@ -942,9 +1000,9 @@ class VmPortRemoveForm(OperationForm):
super(VmPortRemoveForm, self).__init__(*args, **kwargs) super(VmPortRemoveForm, self).__init__(*args, **kwargs)
self.fields.insert(0, 'rule', forms.ModelChoiceField( self.fields['rule'] = forms.ModelChoiceField(
queryset=choices, initial=self.rule, required=True, queryset=choices, initial=self.rule, required=True,
empty_label=None, label=_('Port'))) empty_label=None, label=_('Port'))
if self.rule: if self.rule:
self.fields['rule'].widget = HiddenInput() self.fields['rule'].widget = HiddenInput()
...@@ -961,9 +1019,9 @@ class VmPortAddForm(OperationForm): ...@@ -961,9 +1019,9 @@ class VmPortAddForm(OperationForm):
super(VmPortAddForm, self).__init__(*args, **kwargs) super(VmPortAddForm, self).__init__(*args, **kwargs)
self.fields.insert(0, 'host', forms.ModelChoiceField( self.fields['host'] = forms.ModelChoiceField(
queryset=choices, initial=self.host, required=True, queryset=choices, initial=self.host, required=True,
empty_label=None, label=_('Host'))) empty_label=None, label=_('Host'))
if self.host: if self.host:
self.fields['host'].widget = HiddenInput() self.fields['host'].widget = HiddenInput()
...@@ -1153,7 +1211,10 @@ class TraitForm(forms.ModelForm): ...@@ -1153,7 +1211,10 @@ class TraitForm(forms.ModelForm):
class MyProfileForm(forms.ModelForm): class MyProfileForm(forms.ModelForm):
preferred_language = forms.ChoiceField(LANGUAGES_WITH_CODE) preferred_language = forms.ChoiceField(
LANGUAGES_WITH_CODE,
label=_("Preferred language"),
)
class Meta: class Meta:
fields = ('preferred_language', 'email_notifications', fields = ('preferred_language', 'email_notifications',
...@@ -1196,10 +1257,19 @@ class CirclePasswordChangeForm(PasswordChangeForm): ...@@ -1196,10 +1257,19 @@ class CirclePasswordChangeForm(PasswordChangeForm):
class UserCreationForm(OrgUserCreationForm): class UserCreationForm(OrgUserCreationForm):
def __init__(self, *args, **kwargs):
choices = kwargs.pop('choices')
group = kwargs.pop('default')
super(UserCreationForm, self).__init__(*args, **kwargs)
self.fields['groups'] = forms.ModelMultipleChoiceField(
queryset=choices, initial=[group], required=False,
label=_('Groups'))
class Meta: class Meta:
model = User model = User
fields = ("username", 'email', 'first_name', 'last_name') fields = ("username", 'email', 'first_name', 'last_name', 'groups')
@property @property
def helper(self): def helper(self):
...@@ -1214,8 +1284,39 @@ class UserCreationForm(OrgUserCreationForm): ...@@ -1214,8 +1284,39 @@ class UserCreationForm(OrgUserCreationForm):
user.set_password(self.cleaned_data["password1"]) user.set_password(self.cleaned_data["password1"])
if commit: if commit:
user.save() user.save()
create_profile(user)
user.groups.add(*self.cleaned_data["groups"])
return user
class UserEditForm(forms.ModelForm):
instance_limit = forms.IntegerField(
label=_('Instance limit'),
min_value=0, widget=NumberInput)
def __init__(self, *args, **kwargs):
super(UserEditForm, self).__init__(*args, **kwargs)
self.fields["instance_limit"].initial = (
self.instance.profile.instance_limit)
class Meta:
model = User
fields = ('email', 'first_name', 'last_name', 'instance_limit',
'is_active')
def save(self, commit=True):
user = super(UserEditForm, self).save()
user.profile.instance_limit = (
self.cleaned_data['instance_limit'] or None)
user.profile.save()
return user return user
@property
def helper(self):
helper = FormHelper()
helper.add_input(Submit("submit", _("Save")))
return helper
class AclUserOrGroupAddForm(forms.Form): class AclUserOrGroupAddForm(forms.Form):
name = forms.CharField(widget=autocomplete_light.TextWidget( name = forms.CharField(widget=autocomplete_light.TextWidget(
...@@ -1436,3 +1537,10 @@ class TemplateListSearchForm(forms.Form): ...@@ -1436,3 +1537,10 @@ class TemplateListSearchForm(forms.Form):
data = self.data.copy() data = self.data.copy()
data['stype'] = "owned" data['stype'] = "owned"
self.data = data self.data = data
class UserListSearchForm(forms.Form):
s = forms.CharField(widget=forms.TextInput(attrs={
'class': "form-control input-tags",
'placeholder': _("Search...")
}))
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import datetime from __future__ import unicode_literals
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
from django.db import models, migrations
import dashboard.validators
import dashboard.models
import model_utils.fields
import sizefield.models
import jsonfield.fields
import django.utils.timezone
from django.conf import settings
class Migration(SchemaMigration):
def forwards(self, orm): class Migration(migrations.Migration):
# Adding model 'Favourite'
db.create_table(u'dashboard_favourite', (
(u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('instance', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['vm.Instance'])),
('user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'])),
))
db.send_create_signal(u'dashboard', ['Favourite'])
dependencies = [
('auth', '0001_initial'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('vm', '__first__'),
]
def backwards(self, orm): operations = [
# Deleting model 'Favourite' migrations.CreateModel(
db.delete_table(u'dashboard_favourite') name='ConnectCommand',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
models = { ('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')])),
u'acl.level': { ('name', models.CharField(help_text='Name of your custom command.', max_length=b'128', verbose_name='name')),
'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Level'}, ('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')),
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), ('user', models.ForeignKey(related_name='command_set', to=settings.AUTH_USER_MODEL)),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}), ],
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), options={
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}), },
'weight': ('django.db.models.fields.IntegerField', [], {'null': 'True'}) bases=(models.Model,),
}, ),
u'acl.objectlevel': { migrations.CreateModel(
'Meta': {'unique_together': "(('content_type', 'object_id', 'level'),)", 'object_name': 'ObjectLevel'}, name='Favourite',
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}), fields=[
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False'}), ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), ('instance', models.ForeignKey(to='vm.Instance')),
'level': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['acl.Level']"}), ('user', models.ForeignKey(to=settings.AUTH_USER_MODEL)),
'object_id': ('django.db.models.fields.IntegerField', [], {}), ],
'users': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.User']", 'symmetrical': 'False'}) options={
}, },
u'auth.group': { bases=(models.Model,),
'Meta': {'object_name': 'Group'}, ),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), migrations.CreateModel(
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), name='FutureMember',
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) fields=[
}, ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
u'auth.permission': { ('org_id', models.CharField(help_text='Unique identifier of the person, e.g. a student number.', max_length=64)),
'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'}, ('group', models.ForeignKey(to='auth.Group')),
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), ],
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}), options={
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), },
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) bases=(models.Model,),
}, ),
u'auth.user': { migrations.CreateModel(
'Meta': {'object_name': 'User'}, name='GroupProfile',
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), fields=[
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), ('org_id', models.CharField(help_text='Unique identifier of the group at the organization.', max_length=64, unique=True, null=True, blank=True)),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), ('description', models.TextField(blank=True)),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), ('group', models.OneToOneField(to='auth.Group')),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), ],
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), options={
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 'abstract': False,
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), },
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), bases=(models.Model,),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), ),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), migrations.CreateModel(
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) name='Notification',
}, fields=[
u'contenttypes.contenttype': { ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, ('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, verbose_name='created', editable=False)),
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), ('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, verbose_name='modified', editable=False)),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), ('status', model_utils.fields.StatusField(default=b'new', max_length=100, no_check_for_status=True, choices=[(b'new', 'new'), (b'delivered', 'delivered'), (b'read', 'read')])),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), ('subject_data', jsonfield.fields.JSONField(null=True)),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) ('message_data', jsonfield.fields.JSONField(null=True)),
}, ('valid_until', models.DateTimeField(default=None, null=True)),
u'dashboard.favourite': { ('to', models.ForeignKey(to=settings.AUTH_USER_MODEL)),
'Meta': {'object_name': 'Favourite'}, ],
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), options={
'instance': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['vm.Instance']"}), 'ordering': ['-created'],
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"}) },
}, bases=(models.Model,),
u'firewall.domain': { ),
'Meta': {'object_name': 'Domain'}, migrations.CreateModel(
'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), name='Profile',
'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}), fields=[
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), ('preferred_language', models.CharField(default=b'en', max_length=32, verbose_name='preferred language', choices=[(b'en', 'English'), (b'hu', 'Hungarian')])),
'name': ('django.db.models.fields.CharField', [], {'max_length': '40'}), ('org_id', models.CharField(help_text='Unique identifier of the person, e.g. a student number.', max_length=64, unique=True, null=True, blank=True)),
'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"}), ('instance_limit', models.IntegerField(default=5)),
'ttl': ('django.db.models.fields.IntegerField', [], {'default': '600'}) ('use_gravatar', models.BooleanField(default=True, help_text='Whether to use email address as Gravatar profile image', verbose_name='Use Gravatar')),
}, ('email_notifications', models.BooleanField(default=True, help_text='Whether user wants to get digested email notifications.', verbose_name='Email notifications')),
u'firewall.group': { ('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')),
'Meta': {'object_name': 'Group'}, ('disk_quota', sizefield.models.FileSizeField(default=2147483648, help_text='Disk quota in mebibytes.', verbose_name='disk quota')),
'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), ('user', models.OneToOneField(to=settings.AUTH_USER_MODEL)),
'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}), ],
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), options={
'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}), 'permissions': (('use_autocomplete', 'Can use autocomplete.'),),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}), },
'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']", 'null': 'True', 'blank': 'True'}) bases=(models.Model,),
}, ),
u'firewall.host': { migrations.AlterUniqueTogether(
'Meta': {'object_name': 'Host'}, name='futuremember',
'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}), unique_together=set([('org_id', 'group')]),
'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), ),
'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}), ]
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': u"orm['firewall.Group']", 'null': 'True', 'blank': 'True'}),
'hostname': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '40'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'ipv4': ('firewall.fields.IPAddressField', [], {'unique': 'True', 'max_length': '100'}),
'ipv6': ('firewall.fields.IPAddressField', [], {'max_length': '100', 'unique': 'True', 'null': 'True', 'blank': 'True'}),
'location': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'mac': ('firewall.fields.MACAddressField', [], {'unique': 'True', 'max_length': '17'}),
'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"}),
'pub_ipv4': ('firewall.fields.IPAddressField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
'reverse': ('django.db.models.fields.CharField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}),
'shared_ip': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'vlan': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['firewall.Vlan']"})
},
u'firewall.vlan': {
'Meta': {'object_name': 'Vlan'},
'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'dhcp_pool': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'domain': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['firewall.Domain']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
'network4': ('firewall.fields.IPNetworkField', [], {'max_length': '100'}),
'network6': ('firewall.fields.IPNetworkField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
'network_type': ('django.db.models.fields.CharField', [], {'max_length': '20'}),
'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']", 'null': 'True', 'blank': 'True'}),
'reverse_domain': ('django.db.models.fields.TextField', [], {'default': "'%(d)d.%(c)d.%(b)d.%(a)d.in-addr.arpa'"}),
'snat_ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}),
'snat_to': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': u"orm['firewall.Vlan']", 'null': 'True', 'blank': 'True'}),
'vid': ('django.db.models.fields.IntegerField', [], {'unique': 'True'})
},
u'storage.datastore': {
'Meta': {'ordering': "['name']", 'object_name': 'DataStore'},
'hostname': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '40'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'}),
'path': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '200'})
},
u'storage.disk': {
'Meta': {'ordering': "['name']", 'object_name': 'Disk'},
'base': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'derivatives'", 'null': 'True', 'to': u"orm['storage.Disk']"}),
'created': ('model_utils.fields.AutoCreatedField', [], {'default': 'datetime.datetime.now'}),
'datastore': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['storage.DataStore']"}),
'destroyed': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True', 'blank': 'True'}),
'dev_num': ('django.db.models.fields.CharField', [], {'default': "'a'", 'max_length': '1'}),
'filename': ('django.db.models.fields.CharField', [], {'max_length': '256'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'modified': ('model_utils.fields.AutoLastModifiedField', [], {'default': 'datetime.datetime.now'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
'ready': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'size': ('sizefield.models.FileSizeField', [], {}),
'type': ('django.db.models.fields.CharField', [], {'max_length': '10'})
},
u'taggit.tag': {
'Meta': {'object_name': 'Tag'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'}),
'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '100'})
},
u'taggit.taggeditem': {
'Meta': {'object_name': 'TaggedItem'},
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'taggit_taggeditem_tagged_items'", 'to': u"orm['contenttypes.ContentType']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'object_id': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'}),
'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'taggit_taggeditem_items'", 'to': u"orm['taggit.Tag']"})
},
u'vm.instance': {
'Meta': {'ordering': "[u'pk']", 'object_name': 'Instance'},
'access_method': ('django.db.models.fields.CharField', [], {'max_length': '10'}),
'active_since': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
'arch': ('django.db.models.fields.CharField', [], {'max_length': '10'}),
'boot_menu': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'created': ('model_utils.fields.AutoCreatedField', [], {'default': 'datetime.datetime.now'}),
'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'destroyed': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
'disks': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "u'instance_set'", 'symmetrical': 'False', 'to': u"orm['storage.Disk']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'lease': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['vm.Lease']"}),
'max_ram_size': ('django.db.models.fields.IntegerField', [], {}),
'modified': ('model_utils.fields.AutoLastModifiedField', [], {'default': 'datetime.datetime.now'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
'node': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "u'instance_set'", 'null': 'True', 'to': u"orm['vm.Node']"}),
'num_cores': ('django.db.models.fields.IntegerField', [], {}),
'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"}),
'priority': ('django.db.models.fields.IntegerField', [], {}),
'pw': ('django.db.models.fields.CharField', [], {'max_length': '20'}),
'ram_size': ('django.db.models.fields.IntegerField', [], {}),
'raw_data': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'req_traits': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['vm.Trait']", 'symmetrical': 'False', 'blank': 'True'}),
'state': ('django.db.models.fields.CharField', [], {'default': "u'NOSTATE'", 'max_length': '20'}),
'template': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "u'instance_set'", 'null': 'True', 'to': u"orm['vm.InstanceTemplate']"}),
'time_of_delete': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True', 'blank': 'True'}),
'time_of_suspend': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True', 'blank': 'True'}),
'vnc_port': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'unique': 'True', 'null': 'True', 'blank': 'True'})
},
u'vm.instancetemplate': {
'Meta': {'ordering': "[u'name']", 'object_name': 'InstanceTemplate'},
'access_method': ('django.db.models.fields.CharField', [], {'max_length': '10'}),
'arch': ('django.db.models.fields.CharField', [], {'max_length': '10'}),
'boot_menu': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'created': ('model_utils.fields.AutoCreatedField', [], {'default': 'datetime.datetime.now'}),
'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'disks': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "u'template_set'", 'symmetrical': 'False', 'to': u"orm['storage.Disk']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'lease': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['vm.Lease']"}),
'max_ram_size': ('django.db.models.fields.IntegerField', [], {}),
'modified': ('model_utils.fields.AutoLastModifiedField', [], {'default': 'datetime.datetime.now'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'}),
'num_cores': ('django.db.models.fields.IntegerField', [], {}),
'parent': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['vm.InstanceTemplate']", 'null': 'True', 'blank': 'True'}),
'priority': ('django.db.models.fields.IntegerField', [], {}),
'ram_size': ('django.db.models.fields.IntegerField', [], {}),
'raw_data': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'req_traits': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['vm.Trait']", 'symmetrical': 'False', 'blank': 'True'}),
'state': ('django.db.models.fields.CharField', [], {'default': "u'NEW'", 'max_length': '10'}),
'system': ('django.db.models.fields.TextField', [], {'blank': 'True'})
},
u'vm.lease': {
'Meta': {'ordering': "[u'name']", 'object_name': 'Lease'},
'delete_interval_seconds': ('django.db.models.fields.IntegerField', [], {}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'}),
'suspend_interval_seconds': ('django.db.models.fields.IntegerField', [], {})
},
u'vm.node': {
'Meta': {'object_name': 'Node'},
'created': ('model_utils.fields.AutoCreatedField', [], {'default': 'datetime.datetime.now'}),
'enabled': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'host': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['firewall.Host']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'modified': ('model_utils.fields.AutoLastModifiedField', [], {'default': 'datetime.datetime.now'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '50'}),
'overcommit': ('django.db.models.fields.FloatField', [], {'default': '1.0'}),
'priority': ('django.db.models.fields.IntegerField', [], {}),
'traits': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['vm.Trait']", 'symmetrical': 'False', 'blank': 'True'})
},
u'vm.trait': {
'Meta': {'object_name': 'Trait'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
}
}
complete_apps = ['dashboard']
\ No newline at end of file
...@@ -31,6 +31,7 @@ from django.db.models import ( ...@@ -31,6 +31,7 @@ from django.db.models import (
) )
from django.db.models.signals import post_save, pre_delete, post_delete from django.db.models.signals import post_save, pre_delete, post_delete
from django.templatetags.static import static from django.templatetags.static import static
from django.utils.html import escape
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from django_sshkey.models import UserKey from django_sshkey.models import UserKey
from django.core.exceptions import ObjectDoesNotExist from django.core.exceptions import ObjectDoesNotExist
...@@ -53,7 +54,9 @@ from .validators import connect_command_template_validator ...@@ -53,7 +54,9 @@ from .validators import connect_command_template_validator
logger = getLogger(__name__) logger = getLogger(__name__)
pwgen = User.objects.make_random_password
def pwgen():
return User.objects.make_random_password()
class Favourite(Model): class Favourite(Model):
...@@ -87,7 +90,8 @@ class Notification(TimeStampedModel): ...@@ -87,7 +90,8 @@ class Notification(TimeStampedModel):
@property @property
def subject(self): def subject(self):
return HumanReadableObject.from_dict(self.subject_data) return HumanReadableObject.from_dict(
self.escape_dict(self.subject_data))
@subject.setter @subject.setter
def subject(self, value): def subject(self, value):
...@@ -95,7 +99,14 @@ class Notification(TimeStampedModel): ...@@ -95,7 +99,14 @@ class Notification(TimeStampedModel):
@property @property
def message(self): def message(self):
return HumanReadableObject.from_dict(self.message_data) return HumanReadableObject.from_dict(
self.escape_dict(self.message_data))
def escape_dict(self, data):
for k, v in data['params'].items():
if isinstance(v, basestring):
data['params'][k] = escape(v)
return data
@message.setter @message.setter
def message(self, value): def message(self, value):
......
# -*- coding: utf-8 -*-
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Adding model 'Favourite'
db.create_table(u'dashboard_favourite', (
(u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('instance', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['vm.Instance'])),
('user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'])),
))
db.send_create_signal(u'dashboard', ['Favourite'])
def backwards(self, orm):
# Deleting model 'Favourite'
db.delete_table(u'dashboard_favourite')
models = {
u'acl.level': {
'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Level'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
'weight': ('django.db.models.fields.IntegerField', [], {'null': 'True'})
},
u'acl.objectlevel': {
'Meta': {'unique_together': "(('content_type', 'object_id', 'level'),)", 'object_name': 'ObjectLevel'},
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'level': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['acl.Level']"}),
'object_id': ('django.db.models.fields.IntegerField', [], {}),
'users': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.User']", 'symmetrical': 'False'})
},
u'auth.group': {
'Meta': {'object_name': 'Group'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
u'auth.permission': {
'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
u'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
u'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
u'dashboard.favourite': {
'Meta': {'object_name': 'Favourite'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'instance': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['vm.Instance']"}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"})
},
u'firewall.domain': {
'Meta': {'object_name': 'Domain'},
'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '40'}),
'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"}),
'ttl': ('django.db.models.fields.IntegerField', [], {'default': '600'})
},
u'firewall.group': {
'Meta': {'object_name': 'Group'},
'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']", 'null': 'True', 'blank': 'True'})
},
u'firewall.host': {
'Meta': {'object_name': 'Host'},
'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': u"orm['firewall.Group']", 'null': 'True', 'blank': 'True'}),
'hostname': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '40'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'ipv4': ('firewall.fields.IPAddressField', [], {'unique': 'True', 'max_length': '100'}),
'ipv6': ('firewall.fields.IPAddressField', [], {'max_length': '100', 'unique': 'True', 'null': 'True', 'blank': 'True'}),
'location': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'mac': ('firewall.fields.MACAddressField', [], {'unique': 'True', 'max_length': '17'}),
'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"}),
'pub_ipv4': ('firewall.fields.IPAddressField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
'reverse': ('django.db.models.fields.CharField', [], {'max_length': '40', 'null': 'True', 'blank': 'True'}),
'shared_ip': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'vlan': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['firewall.Vlan']"})
},
u'firewall.vlan': {
'Meta': {'object_name': 'Vlan'},
'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'dhcp_pool': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'domain': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['firewall.Domain']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'modified_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}),
'network4': ('firewall.fields.IPNetworkField', [], {'max_length': '100'}),
'network6': ('firewall.fields.IPNetworkField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
'network_type': ('django.db.models.fields.CharField', [], {'max_length': '20'}),
'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']", 'null': 'True', 'blank': 'True'}),
'reverse_domain': ('django.db.models.fields.TextField', [], {'default': "'%(d)d.%(c)d.%(b)d.%(a)d.in-addr.arpa'"}),
'snat_ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}),
'snat_to': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': u"orm['firewall.Vlan']", 'null': 'True', 'blank': 'True'}),
'vid': ('django.db.models.fields.IntegerField', [], {'unique': 'True'})
},
u'storage.datastore': {
'Meta': {'ordering': "['name']", 'object_name': 'DataStore'},
'hostname': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '40'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'}),
'path': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '200'})
},
u'storage.disk': {
'Meta': {'ordering': "['name']", 'object_name': 'Disk'},
'base': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'derivatives'", 'null': 'True', 'to': u"orm['storage.Disk']"}),
'created': ('model_utils.fields.AutoCreatedField', [], {'default': 'datetime.datetime.now'}),
'datastore': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['storage.DataStore']"}),
'destroyed': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True', 'blank': 'True'}),
'dev_num': ('django.db.models.fields.CharField', [], {'default': "'a'", 'max_length': '1'}),
'filename': ('django.db.models.fields.CharField', [], {'max_length': '256'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'modified': ('model_utils.fields.AutoLastModifiedField', [], {'default': 'datetime.datetime.now'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
'ready': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'size': ('sizefield.models.FileSizeField', [], {}),
'type': ('django.db.models.fields.CharField', [], {'max_length': '10'})
},
u'taggit.tag': {
'Meta': {'object_name': 'Tag'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'}),
'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '100'})
},
u'taggit.taggeditem': {
'Meta': {'object_name': 'TaggedItem'},
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'taggit_taggeditem_tagged_items'", 'to': u"orm['contenttypes.ContentType']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'object_id': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'}),
'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'taggit_taggeditem_items'", 'to': u"orm['taggit.Tag']"})
},
u'vm.instance': {
'Meta': {'ordering': "[u'pk']", 'object_name': 'Instance'},
'access_method': ('django.db.models.fields.CharField', [], {'max_length': '10'}),
'active_since': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
'arch': ('django.db.models.fields.CharField', [], {'max_length': '10'}),
'boot_menu': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'created': ('model_utils.fields.AutoCreatedField', [], {'default': 'datetime.datetime.now'}),
'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'destroyed': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
'disks': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "u'instance_set'", 'symmetrical': 'False', 'to': u"orm['storage.Disk']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'lease': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['vm.Lease']"}),
'max_ram_size': ('django.db.models.fields.IntegerField', [], {}),
'modified': ('model_utils.fields.AutoLastModifiedField', [], {'default': 'datetime.datetime.now'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
'node': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "u'instance_set'", 'null': 'True', 'to': u"orm['vm.Node']"}),
'num_cores': ('django.db.models.fields.IntegerField', [], {}),
'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']"}),
'priority': ('django.db.models.fields.IntegerField', [], {}),
'pw': ('django.db.models.fields.CharField', [], {'max_length': '20'}),
'ram_size': ('django.db.models.fields.IntegerField', [], {}),
'raw_data': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'req_traits': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['vm.Trait']", 'symmetrical': 'False', 'blank': 'True'}),
'state': ('django.db.models.fields.CharField', [], {'default': "u'NOSTATE'", 'max_length': '20'}),
'template': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "u'instance_set'", 'null': 'True', 'to': u"orm['vm.InstanceTemplate']"}),
'time_of_delete': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True', 'blank': 'True'}),
'time_of_suspend': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True', 'blank': 'True'}),
'vnc_port': ('django.db.models.fields.IntegerField', [], {'default': 'None', 'unique': 'True', 'null': 'True', 'blank': 'True'})
},
u'vm.instancetemplate': {
'Meta': {'ordering': "[u'name']", 'object_name': 'InstanceTemplate'},
'access_method': ('django.db.models.fields.CharField', [], {'max_length': '10'}),
'arch': ('django.db.models.fields.CharField', [], {'max_length': '10'}),
'boot_menu': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'created': ('model_utils.fields.AutoCreatedField', [], {'default': 'datetime.datetime.now'}),
'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'disks': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "u'template_set'", 'symmetrical': 'False', 'to': u"orm['storage.Disk']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'lease': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['vm.Lease']"}),
'max_ram_size': ('django.db.models.fields.IntegerField', [], {}),
'modified': ('model_utils.fields.AutoLastModifiedField', [], {'default': 'datetime.datetime.now'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'}),
'num_cores': ('django.db.models.fields.IntegerField', [], {}),
'parent': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['vm.InstanceTemplate']", 'null': 'True', 'blank': 'True'}),
'priority': ('django.db.models.fields.IntegerField', [], {}),
'ram_size': ('django.db.models.fields.IntegerField', [], {}),
'raw_data': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'req_traits': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['vm.Trait']", 'symmetrical': 'False', 'blank': 'True'}),
'state': ('django.db.models.fields.CharField', [], {'default': "u'NEW'", 'max_length': '10'}),
'system': ('django.db.models.fields.TextField', [], {'blank': 'True'})
},
u'vm.lease': {
'Meta': {'ordering': "[u'name']", 'object_name': 'Lease'},
'delete_interval_seconds': ('django.db.models.fields.IntegerField', [], {}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'}),
'suspend_interval_seconds': ('django.db.models.fields.IntegerField', [], {})
},
u'vm.node': {
'Meta': {'object_name': 'Node'},
'created': ('model_utils.fields.AutoCreatedField', [], {'default': 'datetime.datetime.now'}),
'enabled': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'host': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['firewall.Host']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'modified': ('model_utils.fields.AutoLastModifiedField', [], {'default': 'datetime.datetime.now'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '50'}),
'overcommit': ('django.db.models.fields.FloatField', [], {'default': '1.0'}),
'priority': ('django.db.models.fields.IntegerField', [], {}),
'traits': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['vm.Trait']", 'symmetrical': 'False', 'blank': 'True'})
},
u'vm.trait': {
'Meta': {'object_name': 'Trait'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
}
}
complete_apps = ['dashboard']
\ No newline at end of file
/* for functions in both vm list and vm detail */
$(function() { $(function() {
var in_progress = false;
var activity_hash = 5;
var show_all = false;
var reload_vm_detail = false;
/* do we need to check for new activities */
if(decideActivityRefresh()) {
if(!in_progress) {
checkNewActivity(1);
in_progress = true;
}
}
/* vm operations */ $('a[href="#activity"]').click(function(){
$('a[href="#activity"] i').addClass('fa-spin');
if(!in_progress) {
checkNewActivity(1);
in_progress = true;
}
});
$("#activity-refresh").on("click", "#show-all-activities", function() {
$(this).find("i").addClass("fa-spinner fa-spin");
show_all = !show_all;
$('a[href="#activity"]').trigger("click");
return false;
});
/* operations */
$('#ops, #vm-details-resources-disk, #vm-details-renew-op, #vm-details-pw-reset, #vm-details-add-interface, .operation-wrapper').on('click', '.operation', function(e) { $('#ops, #vm-details-resources-disk, #vm-details-renew-op, #vm-details-pw-reset, #vm-details-add-interface, .operation-wrapper').on('click', '.operation', function(e) {
var icon = $(this).children("i").addClass('fa-spinner fa-spin'); var icon = $(this).children("i").addClass('fa-spinner fa-spin');
...@@ -23,7 +48,7 @@ $(function() { ...@@ -23,7 +48,7 @@ $(function() {
}); });
/* if the operation fails show the modal again */ /* if the operation fails show the modal again */
$("body").on("click", "#op-form-send", function() { $("body").on("click", "#confirmation-modal #op-form-send", function() {
var url = $(this).closest("form").prop("action"); var url = $(this).closest("form").prop("action");
$.ajax({ $.ajax({
...@@ -77,4 +102,91 @@ $(function() { ...@@ -77,4 +102,91 @@ $(function() {
return false; return false;
}); });
function decideActivityRefresh() {
var check = false;
/* if something is still spinning */
if($('.timeline .activity i').hasClass('fa-spin'))
check = true;
return check;
}
function checkNewActivity(runs) {
$.ajax({
type: 'GET',
url: $('a[href="#activity"]').attr('data-activity-url'),
data: {'show_all': show_all},
success: function(data) {
var new_activity_hash = (data.activities + "").hashCode();
if(new_activity_hash != activity_hash) {
$("#activity-refresh").html(data.activities);
}
activity_hash = new_activity_hash;
$("#ops").html(data.ops);
$("#disk-ops").html(data.disk_ops);
$("[title]").tooltip();
/* changing the status text */
var icon = $("#vm-details-state i");
if(data.is_new_state) {
if(!icon.hasClass("fa-spin"))
icon.prop("class", "fa fa-spinner fa-spin");
} else {
icon.prop("class", "fa " + data.icon);
}
var vm_state = $("#vm-details-state");
if (vm_state.length) {
vm_state.data("status", data['status']); // jshint ignore:line
$("#vm-details-state span").html(data.human_readable_status.toUpperCase());
}
if(data['status'] == "RUNNING") { // jshint ignore:line
if(data.connect_uri) {
$("#dashboard-vm-details-connect-button").removeClass('disabled');
}
$("[data-target=#_console]").attr("data-toggle", "pill").attr("href", "#console").parent("li").removeClass("disabled");
} else {
if(data.connect_uri) {
$("#dashboard-vm-details-connect-button").addClass('disabled');
}
$("[data-target=#_console]").attr("data-toggle", "_pill").attr("href", "#").parent("li").addClass("disabled");
}
if(data.status == "STOPPED" || data.status == "PENDING") {
$(".change-resources-button").prop("disabled", false);
$(".change-resources-help").hide();
} else {
$(".change-resources-button").prop("disabled", true);
$(".change-resources-help").show();
}
if(runs > 0 && decideActivityRefresh()) {
setTimeout(
function() {checkNewActivity(runs + 1);},
1000 + Math.exp(runs * 0.05)
);
} else {
in_progress = false;
if(reload_vm_detail) location.reload();
}
$('a[href="#activity"] i').removeClass('fa-spin');
},
error: function() {
in_progress = false;
}
});
}
}); });
String.prototype.hashCode = function() {
var hash = 0, i, chr, len;
if (this.length === 0) return hash;
for (i = 0, len = this.length; i < len; i++) {
chr = this.charCodeAt(i);
hash = ((hash << 5) - hash) + chr;
hash |= 0; // Convert to 32bit integer
}
return hash;
};
$(function () { $(function () {
$('.vm-create').click(function(e) { var favicon= new Favico({
var template = $(this).data("template"); animation:'none'
$.ajax({
type: 'GET',
url: '/dashboard/vm/create/' + (typeof template === "undefined" ? '' : '?template=' + template),
success: function(data) {
$('body').append(data);
vmCreateLoaded();
addSliderMiscs();
$('#create-modal').modal('show');
$('#create-modal').on('hidden.bs.modal', function() {
$('#create-modal').remove();
});
}
});
return false;
}); });
$('.node-create').click(function(e) { var notifications = $("#notification_count").data("notifications");
$.ajax({ if(notifications)
type: 'GET', favicon.badge(notifications);
url: '/dashboard/node/create/',
success: function(data) { $(".not-tab-pane").removeClass("not-tab-pane").addClass("tab-pane");
$('body').append(data);
nodeCreateLoaded();
addSliderMiscs();
$('#create-modal').modal('show');
$('#create-modal').on('hidden.bs.modal', function() {
$('#create-modal').remove();
});
}
});
return false;
});
$('.group-create').click(function(e) { $('.vm-create').click(function(e) {
var template = $(this).data("template");
$.ajax({ $.ajax({
type: 'GET', type: 'GET',
url: '/dashboard/group/create/', url: $(this).attr('href'),
success: function(data) { success: function(data) {
$('body').append(data); $('body').append(data);
vmCreateLoaded();
addSliderMiscs(); addSliderMiscs();
$('#create-modal').modal('show'); var modal = $('#confirmation-modal');
$('#create-modal').on('hidden.bs.modal', function() { modal.modal('show');
$('#create-modal').remove(); modal.on('hidden.bs.modal', function() {
modal.remove();
}); });
} }
}); });
return false; return false;
}); });
$('.tx-tpl-ownership').click(function(e) { $('.group-create, .node-create, .tx-tpl-ownership, .group-delete, .node-delete, .disk-remove, .template-delete, .delete-from-group, .lease-delete').click(function(e) {
$.ajax({ $.ajax({
type: 'GET', type: 'GET',
url: $('.tx-tpl-ownership').attr('href'), url: $(this).prop('href'),
success: function(data) { success: function(data) {
$('body').append(data); $('body').append(data);
$('#confirmation-modal').modal('show'); var modal = $('#confirmation-modal');
$('#confirmation-modal').on('hidden.bs.modal', function() { modal.modal('show');
$('#confirmation-modal').remove(); modal.on('hidden.bs.modal', function() {
modal.remove();
}); });
},
error: function(xhr, textStatus, error) {
if(xhr.status === 403) {
addMessage(gettext("Only the owners can delete the selected object."), "warning");
} else {
addMessage(gettext("An error occurred. (") + xhr.status + ")", 'danger');
}
} }
}); });
return false; return false;
...@@ -68,12 +54,13 @@ $(function () { ...@@ -68,12 +54,13 @@ $(function () {
$('.template-choose').click(function(e) { $('.template-choose').click(function(e) {
$.ajax({ $.ajax({
type: 'GET', type: 'GET',
url: '/dashboard/template/choose/', url: $(this).prop('href'),
success: function(data) { success: function(data) {
$('body').append(data); $('body').append(data);
$('#create-modal').modal('show'); var modal = $('#confirmation-modal');
$('#create-modal').on('hidden.bs.modal', function() { modal.modal('show');
$('#create-modal').remove(); modal.on('hidden.bs.modal', function() {
modal.remove();
}); });
// check if user selected anything // check if user selected anything
$("#template-choose-next-button").click(function() { $("#template-choose-next-button").click(function() {
...@@ -99,6 +86,7 @@ $(function () { ...@@ -99,6 +86,7 @@ $(function () {
e.stopImmediatePropagation(); e.stopImmediatePropagation();
return false; return false;
}); });
$('[href=#index-list-view]').click(function (e) { $('[href=#index-list-view]').click(function (e) {
var box = $(this).data('index-box'); var box = $(this).data('index-box');
$('#' + box + '-graph-view').hide(); $('#' + box + '-graph-view').hide();
...@@ -108,9 +96,10 @@ $(function () { ...@@ -108,9 +96,10 @@ $(function () {
e.stopImmediatePropagation(); e.stopImmediatePropagation();
return false; return false;
}); });
$('body [title]:not(.title-favourite)').tooltip();
$('body .title-favourite').tooltip({'placement': 'right'}); $('body .title-favourite').tooltip({'placement': 'right'});
$('body :input[title]').tooltip({trigger: 'focus', placement: 'auto right'}); $('body :input[title]').tooltip({trigger: 'focus', placement: 'auto right'});
$('body [title]').tooltip();
$(".knob").knob(); $(".knob").knob();
$('[data-toggle="pill"]').click(function() { $('[data-toggle="pill"]').click(function() {
...@@ -165,221 +154,74 @@ $(function () { ...@@ -165,221 +154,74 @@ $(function () {
addSliderMiscs(); addSliderMiscs();
/* for VM removes buttons */ /* search */
$('.vm-delete').click(function() { function register_search(form, list, generateHTML) {
var vm_pk = $(this).data('vm-pk'); var my_vms = [];
var dir = window.location.pathname.indexOf('list') == -1; /* 0 - default state
addModalConfirmation(deleteObject, * 1 - ajax request sent
{ 'url': '/dashboard/vm/delete/' + vm_pk + '/', * 2 - ajax request received, we have our list of vms
'data': [], */
'pk': vm_pk, var search_state = 0;
'type': "vm",
'redirect': dir}); form.find('input').keyup(function(e) {
return false; if (search_state == 1) {
}); return;
}
/* for disk remove buttons */ // if my_vms is empty get a list of our vms
$('.disk-remove').click(function() { if(search_state === 0) {
var disk_pk = $(this).data('disk-pk'); search_state = 1;
addModalConfirmation(deleteObject, var btn = form.find('button');
{ 'url': '/dashboard/disk/' + disk_pk + '/remove/', btn.find('i').addClass("fa-spinner fa-spin");
'data': [],
'pk': disk_pk, $.get(form.prop('action'), function(result) {
'type': "disk", search_state = 3;
}); my_vms = result;
return false; form.find("input").trigger("keyup");
}); btn.find('i').removeClass("fa-spinner fa-spin").addClass("fa-search");
});
/* for Node removes buttons */ return;
$('.node-delete').click(function() { }
var node_pk = $(this).data('node-pk');
var dir = window.location.pathname.indexOf('list') == -1;
addModalConfirmation(deleteObject,
{ 'url': '/dashboard/node/delete/' + node_pk + '/',
'data': [],
'pk': node_pk,
'type': "node",
'redirect': dir});
return false;
});
/* for Node flush buttons */
$('.node-flush').click(function() {
var node_pk = $(this).data('node-pk');
var postto = $(this).attr('href');
var dir = window.location.pathname.indexOf('list') == -1;
addModalConfirmation(function(){},
{ 'url': postto,
'data': [],
'pk': node_pk,
'type': "node",
'redirect': dir});
return false;
});
/* for Group removes buttons */
$('.group-delete').click(function() {
var group_pk = $(this).data('group-pk');
var dir = window.location.pathname.indexOf('list') == -1;
addModalConfirmation(deleteObject,
{ 'url': '/dashboard/group/delete/' + group_pk + '/',
'data': [],
'type': "group",
'pk': group_pk,
'redirect': dir});
return false;
});
/* search for vms */ input = $(this).val().toLowerCase();
var my_vms = []; var search_result = [];
$("#dashboard-vm-search-input").keyup(function(e) { for(var i in my_vms) {
// if my_vms is empty get a list of our vms if(my_vms[i].name.toLowerCase().indexOf(input) != -1 ||
if(my_vms.length < 1) { (my_vms[i].host && my_vms[i].host.indexOf(input) != -1) ||
$.ajaxSetup( { "async": false } ); (my_vms[i].org_id && my_vms[i].org_id.toLowerCase().indexOf(input) != -1)
$.get("/dashboard/vm/list/", function(result) { ) {
for(var i in result) { search_result.push(my_vms[i]);
my_vms.push({
'pk': result[i].pk,
'name': result[i].name.toLowerCase(),
'state': result[i].state,
'fav': result[i].fav,
'host': result[i].host,
'icon': result[i].icon,
'status': result[i].status,
'owner': result[i].owner,
});
} }
});
$.ajaxSetup( { "async": true } );
}
input = $("#dashboard-vm-search-input").val().toLowerCase();
var search_result = [];
var html = '';
for(var i in my_vms) {
if(my_vms[i].name.indexOf(input) != -1 || my_vms[i].host.indexOf(input) != -1) {
search_result.push(my_vms[i]);
} }
} search_result.sort(compareVmByFav);
search_result.sort(compareVmByFav);
for(var i=0; i<5 && i<search_result.length; i++)
html += generateVmHTML(search_result[i].pk, search_result[i].name,
search_result[i].owner ? search_result[i].owner : search_result[i].host, search_result[i].icon,
search_result[i].status, search_result[i].fav,
(search_result.length < 5));
if(search_result.length === 0)
html += '<div class="list-group-item list-group-item-last">' + gettext("No result") + '</div>';
$("#dashboard-vm-list").html(html);
$('.title-favourite').tooltip({'placement': 'right'});
});
$("#dashboard-vm-search-form").submit(function() { var html = '';
var vm_list_items = $("#dashboard-vm-list .list-group-item"); var is_last = search_result.length < 5;
if(vm_list_items.length == 1 && vm_list_items.first().prop("href")) {
window.location.href = vm_list_items.first().prop("href");
return false;
}
return true;
});
/* search for nodes */ for(i=0; i<5 && i<search_result.length; i++)
var my_nodes = []; html += generateHTML(search_result[i], is_last);
$("#dashboard-node-search-input").keyup(function(e) {
// if my_nodes is empty get a list of our nodes
if(my_nodes.length < 1) {
$.ajaxSetup( { "async": false } );
$.get("/dashboard/node/list/", function(result) {
for(var i in result) {
my_nodes.push({
'name': result[i].name.toLowerCase(),
'icon': result[i].icon,
'status': result[i].status,
'label': result[i].label,
'url': result[i].url,
});
}
});
$.ajaxSetup( { "async": true } );
}
input = $("#dashboard-node-search-input").val().toLowerCase(); if(search_result.length === 0)
var search_result = []; html += '<div class="list-group-item list-group-item-last">' + gettext("No result") + '</div>';
var html = '';
for(var i in my_nodes) {
if(my_nodes[i].name.indexOf(input) != -1) {
search_result.push(my_nodes[i]);
}
}
for(i=0; i<5 && i<search_result.length; i++)
html += generateNodeHTML(search_result[i].name,
search_result[i].icon, search_result[i].status,
search_result[i].url,
(search_result.length < 5));
if(search_result.length === 0)
html += '<div class="list-group-item list-group-item-last">' + gettext("No result") + '</div>';
$("#dashboard-node-list").html(html);
html = '';
for(i=0; i<5 && i<search_result.length; i++)
html += generateNodeTagHTML(search_result[i].name,
search_result[i].icon, search_result[i].status,
search_result[i].label, search_result[i].url);
if(search_result.length === 0)
html += '<div class="list-group-item list-group-item-last">' + gettext("No result") + '</div>';
$("#dashboard-node-taglist").html(html);
// if there is only one result and ENTER is pressed redirect
if(e.keyCode == 13 && search_result.length == 1) {
window.location.href = search_result[0].url;
}
if(e.keyCode == 13 && search_result.length > 1 && input.length > 0) {
window.location.href = "/dashboard/node/list/?s=" + input;
}
});
/* search for groups */ list.html(html);
var my_groups = []; $('.title-favourite').tooltip({'placement': 'right'});
$("#dashboard-group-search-input").keyup(function(e) { });
// if my_groups is empty get a list of our groups
if(my_groups.length < 1) {
$.ajaxSetup( { "async": false } );
$.get("/dashboard/group/list/", function(result) {
for(var i in result) {
my_groups.push({
'url': result[i].url,
'name': result[i].name.toLowerCase(),
});
}
});
$.ajaxSetup( { "async": true } );
}
input = $("#dashboard-group-search-input").val().toLowerCase(); form.submit(function() {
var search_result = []; var vm_list_items = list.find(".list-group-item");
var html = ''; if(vm_list_items.length == 1 && vm_list_items.first().prop("href")) {
for(var i in my_groups) { window.location.href = vm_list_items.first().prop("href");
if(my_groups[i].name.indexOf(input) != -1) { return false;
search_result.push(my_groups[i]);
} }
} return true;
for(i=0; i<5 && i<search_result.length; i++) });
html += generateGroupHTML(search_result[i].url, search_result[i].name, search_result.length < 5); }
if(search_result.length === 0)
html += '<div class="list-group-item list-group-item-last">No result</div>'; register_search($("#dashboard-vm-search-form"), $("#dashboard-vm-list"), generateVmHTML);
$("#dashboard-group-list").html(html); register_search($("#dashboard-node-search-form"), $("#dashboard-node-list"), generateNodeHTML);
register_search($("#dashboard-group-search-form"), $("#dashboard-group-list"), generateGroupHTML);
// if there is only one result and ENTER is pressed redirect register_search($("#dashboard-user-search-form"), $("#dashboard-user-list"), generateUserHTML);
if(e.keyCode == 13 && search_result.length == 1) { register_search($("#dashboard-template-search-form"), $("#dashboard-template-list"), generateTemplateHTML);
window.location.href = search_result[0].url;
}
if(e.keyCode == 13 && search_result.length > 1 && input.length > 0) {
window.location.href = "/dashboard/group/list/?s=" + input;
}
});
/* notification message toggle */ /* notification message toggle */
$(document).on('click', ".notification-message-subject", function() { $(document).on('click', ".notification-message-subject", function() {
...@@ -398,8 +240,10 @@ $(function () { ...@@ -398,8 +240,10 @@ $(function () {
$("#notification-button a").click(function() { $("#notification-button a").click(function() {
$('#notification-messages').load("/dashboard/notifications/"); $('#notification-messages').load("/dashboard/notifications/");
$('#notification-button a span[class*="badge-pulse"]').remove(); $('#notification-button a span[class*="badge-pulse"]').remove();
favicon.reset();
}); });
/* on the client confirmation button fire the clientInstalledAction */ /* on the client confirmation button fire the clientInstalledAction */
$(document).on("click", "#client-check-button", function(event) { $(document).on("click", "#client-check-button", function(event) {
var connectUri = $('#connect-uri').val(); var connectUri = $('#connect-uri').val();
...@@ -436,43 +280,54 @@ $(function () { ...@@ -436,43 +280,54 @@ $(function () {
li.addClass('panel-primary').find('input').prop("checked", true); li.addClass('panel-primary').find('input').prop("checked", true);
return true; return true;
}); });
}); });
function generateVmHTML(pk, name, host, icon, _status, fav, is_last) { function generateVmHTML(data, is_last) {
return '<a href="/dashboard/vm/' + pk + '/" class="list-group-item' + return '<a href="' + data.url + '" class="list-group-item' +
(is_last ? ' list-group-item-last' : '') + '">' + (is_last ? ' list-group-item-last' : '') + '">' +
'<span class="index-vm-list-name">' + '<span class="index-vm-list-name">' +
'<i class="fa ' + icon + '" title="' + _status + '"></i> ' + safe_tags_replace(name) + '<i class="fa ' + data.icon + '" title="' + data.status + '"></i> ' + safe_tags_replace(data.name) +
'</span>' + '</span>' +
'<small class="text-muted"> ' + host + '</small>' + '<small class="text-muted index-vm-list-host"> ' + data.host + '</small>' +
'<div class="pull-right dashboard-vm-favourite" data-vm="' + pk + '">' + '<div class="pull-right dashboard-vm-favourite" data-vm="' + data.pk + '">' +
(fav ? '<i class="fa fa-star text-primary title-favourite" title="' + gettext("Unfavourite") + '"></i>' : (data.fav ? '<i class="fa fa-star text-primary title-favourite" title="' + gettext("Unfavourite") + '"></i>' :
'<i class="fa fa-star-o text-primary title-favourite" title="' + gettext("Mark as favorite") + '"></i>' ) + '<i class="fa fa-star-o text-primary title-favourite" title="' + gettext("Mark as favorite") + '"></i>' ) +
'</div>' + '</div>' +
'<div style="clear: both;"></div>' + '<div style="clear: both;"></div>' +
'</a>'; '</a>';
} }
function generateGroupHTML(url, name, is_last) { function generateGroupHTML(data, is_last) {
return '<a href="' + url + '" class="list-group-item real-link' + (is_last ? " list-group-item-last" : "") +'">'+ return '<a href="' + data.url + '" class="list-group-item real-link' + (is_last ? " list-group-item-last" : "") +'">'+
'<i class="fa fa-users"></i> '+ safe_tags_replace(name) + '<i class="fa fa-users"></i> '+ safe_tags_replace(data.name) +
'</a>'; '</a>';
} }
function generateNodeHTML(name, icon, _status, url, is_last) { function generateUserHTML(data, is_last) {
return '<a href="' + url + '" class="list-group-item real-link' + (is_last ? ' list-group-item-last' : '') + '">' + return '<a href="' + data.url + '" class="list-group-item real-link' + (is_last ? " list-group-item-last" : "") +'">'+
'<span class="index-node-list-name">' + '<span class="index-user-list-name"><i class="fa fa-user"></i> '+ safe_tags_replace(data.name) + '</span>' +
'<i class="fa ' + icon + '" title="' + _status + '"></i> ' + safe_tags_replace(name) + '<span class="index-user-list-org">' +
'</span>' + '<small class="text-muted"> ' + (data.org_id ? safe_tags_replace(data.org_id) : "") + '</small>' +
'<div style="clear: both;"></div>' + '</span></a>';
'</a>';
} }
function generateNodeTagHTML(name, icon, _status, label , url) { function generateTemplateHTML(data, is_last) {
return '<a href="' + url + '" class="label ' + label + '" >' + return '<a href="' + data.url + '" class="list-group-item real-link' + (is_last ? " list-group-item-last" : "") +'">'+
'<i class="fa ' + icon + '" title="' + _status + '"></i> ' + safe_tags_replace(name) + ' <span class="index-template-list-name">' +
'</a> '; ' <i class="fa fa-' + data.icon + '"></i> '+ safe_tags_replace(data.name) +
' </span>' +
' <small class="text-muted index-template-list-system">' + safe_tags_replace(data.system) + '</small>' +
' <div class="clearfix"></div>' +
'</a>';
}
function generateNodeHTML(data, is_last) {
return '<a href="' + data.url + '" class="list-group-item real-link' + (is_last ? ' list-group-item-last' : '') + '">' +
'<span class="index-node-list-name">' +
'<i class="fa ' + data.icon + '" title="' + data.status + '"></i> ' + safe_tags_replace(data.name) +
'</span>' +
'<div style="clear: both;"></div>' +
'</a>';
} }
/* copare vm-s by fav, pk order */ /* copare vm-s by fav, pk order */
...@@ -556,62 +411,6 @@ function setDefaultSliderValues() { ...@@ -556,62 +411,6 @@ function setDefaultSliderValues() {
} }
/* deletes the VM with the pk
* if dir is true, then redirect to the dashboard landing page
* else it adds a success message */
function deleteObject(data) {
$.ajax({
type: 'POST',
data: {'redirect': data.redirect},
url: data.url,
headers: {"X-CSRFToken": getCookie('csrftoken')},
success: function(re, textStatus, xhr) {
if(!data.redirect) {
selected = [];
addMessage(re.message, 'success');
if(data.type === "disk") {
// no need to remove them from DOM
$('a[data-disk-pk="' + data.pk + '"]').parent("li").fadeOut();
$('a[data-disk-pk="' + data.pk + '"]').parent("h4").fadeOut();
}
else {
$('a[data-'+data.type+'-pk="' + data.pk + '"]').closest('tr').fadeOut(function() {
$(this).remove();
});
}
} else {
window.location.replace('/dashboard');
}
},
error: function(xhr, textStatus, error) {
addMessage('Uh oh :(', 'danger');
}
});
}
function massDeleteVm(data) {
f = function() {
selected = [];
// reset group buttons
$('.vm-list-group-control a').attr('disabled', true);
$(this).remove();
};
$.ajax({
traditional: true,
url: data.url,
headers: {"X-CSRFToken": getCookie('csrftoken')},
type: 'POST',
data: {'vms': data.data.v},
success: function(re, textStatus, xhr) {
for(var i=0; i< data.data.v.length; i++)
$('.vm-list-table tbody tr[data-vm-pk="' + data.data.v[i] + '"]').fadeOut(500, f);
addMessage(re.message, 'success');
},
error: function(xhr, textStatus, error) {
// TODO this
}
});
}
function addMessage(text, type) { function addMessage(text, type) {
...@@ -644,19 +443,19 @@ function addModalConfirmation(func, data) { ...@@ -644,19 +443,19 @@ function addModalConfirmation(func, data) {
}); });
} }
function clientInstalledAction(location) { function clientInstalledAction(location) {
setCookie('downloaded_client', true, 365 * 24 * 60 * 60 * 1000, "/"); setCookie('downloaded_client', true, 365 * 24 * 60 * 60 * 1000, "/");
window.location.href = location; window.location.href = location;
$('#confirmation-modal').modal("hide"); $('#confirmation-modal').modal("hide");
} }
function setCookie(name, value, seconds, path) { function setCookie(name, value, seconds, path) {
if (seconds!=null) { if (seconds !== null) {
var today = new Date(); var today = new Date();
var expire = new Date(); var expire = new Date();
expire.setTime(today.getTime() + seconds); expire.setTime(today.getTime() + seconds);
document.cookie = name+"="+escape(value)+"; expires="+expire.toUTCString()+"; path="+path;
} }
document.cookie = name+"="+escape(value)+"; expires="+expire.toUTCString()+"; path="+path;
} }
/* no js compatibility */ /* no js compatibility */
...@@ -670,7 +469,7 @@ function getParameterByName(name) { ...@@ -670,7 +469,7 @@ function getParameterByName(name) {
name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]"); name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"), var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
results = regex.exec(location.search); results = regex.exec(location.search);
return results == null ? "" : decodeURIComponent(results[1].replace(/\+/g, " ")); return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
} }
// for AJAX calls // for AJAX calls
...@@ -699,6 +498,7 @@ function csrfSafeMethod(method) { ...@@ -699,6 +498,7 @@ function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection // these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method)); return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
} }
$.ajaxSetup({ $.ajaxSetup({
beforeSend: function(xhr, settings) { beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) { if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
...@@ -711,7 +511,7 @@ $.ajaxSetup({ ...@@ -711,7 +511,7 @@ $.ajaxSetup({
$(function() { $(function() {
yourlabs.TextWidget.prototype.getValue = function(choice) { yourlabs.TextWidget.prototype.getValue = function(choice) {
return choice.children().html(); return choice.children().html();
} };
}); });
var tagsToReplace = { var tagsToReplace = {
......
...@@ -23,46 +23,23 @@ html { ...@@ -23,46 +23,23 @@ html {
padding-right: 15px; padding-right: 15px;
} }
/* values for 45px tall navbar */ /* --- */
.navbar {
min-height: 45px;
}
.navbar-brand {
height: 45px;
padding: 12.5px 12.5px;
}
.navbar-toggle { #dashboard-menu > li > a {
margin-top: 5.5px; color: white;
margin-bottom: 5.5px; font-size: 10px;
} }
.navbar-form {
margin-top: 5.5px;
margin-bottom: 5.5px;
}
.navbar-btn { #dashboard-menu {
margin-top: 5.5px; margin-right: 15px;
margin-bottom: 5.5px;
} }
.navbar-btn.btn-sm { /* we need this for mobile view */
margin-top: 7.5px; .container > :first-child {
margin-bottom: 7.5px; margin-top: 15px;
}
.navbar-btn.btn-xs {
margin-top: 11.5px;
margin-bottom: 11.5px;
}
.navbar-text {
margin-top: 12.5px;
margin-bottom: 12.5px;
} }
/* --- */
/* Responsive: Portrait tablets and up */ /* Responsive: Portrait tablets and up */
@media screen and (min-width: 768px) { @media screen and (min-width: 768px) {
/* Let the jumbotron breathe */ /* Let the jumbotron breathe */
...@@ -80,13 +57,17 @@ html { ...@@ -80,13 +57,17 @@ html {
} }
} }
.no-margin { .no-margin {
margin: 0!important; margin: 0!important;
} }
.list-group .list-group-footer { .list-group .list-group-footer {
padding-top: 5px; height: 41px;
padding-bottom: 5px; }
.list-group-footer .text-right {
padding-top: 4px;
} }
.big { .big {
...@@ -194,7 +175,7 @@ html { ...@@ -194,7 +175,7 @@ html {
} }
.dashboard-index .panel { .dashboard-index .panel {
height: 300px; height: 294px;
} }
#vm-details-rename, #vm-details-h1-name, #vm-details-rename , #vm-details-rename, #vm-details-h1-name, #vm-details-rename ,
...@@ -207,11 +188,15 @@ html { ...@@ -207,11 +188,15 @@ html {
display: none; display: none;
} }
.vm-details-home-name { #group-details-rename-form {
display: inline-block;
}
.vm-details-home-name, #group-details-rename-form .input-group {
max-width: 401px; max-width: 401px;
} }
#node-details-rename-name, #group-details-rename-name { #node-details-rename-name {
max-width: 160px; max-width: 160px;
} }
...@@ -397,10 +382,6 @@ a.hover-black { ...@@ -397,10 +382,6 @@ a.hover-black {
font-size: 12px; font-size: 12px;
} }
#notification-button {
margin-right: 15px;
}
#vm-migrate-node-list { #vm-migrate-node-list {
list-style: none; list-style: none;
} }
...@@ -516,15 +497,6 @@ footer a, footer a:hover, footer a:visited { ...@@ -516,15 +497,6 @@ footer a, footer a:hover, footer a:visited {
padding: 5px; /* it's nice this way in the tour */ padding: 5px; /* it's nice this way in the tour */
} }
.index-vm-list-name {
display: inline-block;
max-width: 70%;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
float: left;
}
#dashboard-vm-list a small { #dashboard-vm-list a small {
padding-left: 10px; padding-left: 10px;
} }
...@@ -590,8 +562,8 @@ footer a, footer a:hover, footer a:visited { ...@@ -590,8 +562,8 @@ footer a, footer a:hover, footer a:visited {
} }
#dashboard-vm-list, #dashboard-node-list, #dashboard-group-list, #dashboard-vm-list, #dashboard-node-list, #dashboard-group-list,
#dashboard-template-list { #dashboard-template-list, #dashboard-files-toplist, #dashboard-user-list {
min-height: 204px; min-height: 200px;
} }
#group-detail-user-table td:first-child, #group-detail-user-table th:last-child, #group-detail-user-table td:first-child, #group-detail-user-table th:last-child,
...@@ -754,15 +726,14 @@ textarea[name="new_members"] { ...@@ -754,15 +726,14 @@ textarea[name="new_members"] {
} }
#dashboard-files-toplist { #dashboard-files-toplist {
min-height: 204px; div.list-group-item {
} color: #555;
height: 41px;
#dashboard-files-toplist div.list-group-item { &:hover {
color: #555; background: #eee;
} }
}
#dashboard-files-toplist div.list-group-item:hover {
background: #eee;
} }
.store-list-item-name { .store-list-item-name {
...@@ -961,6 +932,11 @@ textarea[name="new_members"] { ...@@ -961,6 +932,11 @@ textarea[name="new_members"] {
#vm-list-search, #vm-mass-ops { #vm-list-search, #vm-mass-ops {
margin-top: 8px; margin-top: 8px;
} }
.list-group-item {
border-bottom: 0px !important;
}
.list-group-item-last { .list-group-item-last {
border-bottom: 1px solid #ddd !important; border-bottom: 1px solid #ddd !important;
} }
...@@ -1105,6 +1081,25 @@ textarea[name="new_members"] { ...@@ -1105,6 +1081,25 @@ textarea[name="new_members"] {
text-align: center; text-align: center;
} }
.vm-create-list-name {
display: inline-block;
max-width: 60%;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
float: left;
}
.vm-create-list-system {
display: inline-block;
max-width: 40%;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
float: right;
}
/* for introjs /* for introjs
* newer version has this fixed * newer version has this fixed
* but it doesn't work w bootstrap 3.2.0 * but it doesn't work w bootstrap 3.2.0
...@@ -1151,3 +1146,104 @@ textarea[name="new_members"] { ...@@ -1151,3 +1146,104 @@ textarea[name="new_members"] {
background-position: 0 0px; background-position: 0 0px;
} }
} }
#dashboard-vm-list {
.list-group-item {
display: flex;
}
.index-vm-list-name, .index-vm-list-host {
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
.index-vm-list-name {
max-width: 70%;
}
.index-vm-list-host {
padding-top: 3px;
flex: 1;
}
}
#dashboard-user-list {
.list-group-item {
display: flex;
}
.index-user-list-name, .index-user-list-org {
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
.index-user-list-name {
max-width: 80%;
}
.index-user-list-org {
padding-left: 5px;
flex: 1;
}
}
.fa-fw-12 {
/* fa-fw is too wide */
width: 12px;
}
.btn-op-form-send {
padding: 6px 12px 6px 8px;
}
@media (max-width: 767px) {
#vm-detail-panel .graph-buttons {
padding-top: 15px;
}
.graph-buttons a {
margin-bottom: 8px;
}
#ops .operation {
margin-bottom: 5px;
}
.vm-details-connection dd {
margin-left: 25px;
}
.vm-details-connection dt {
padding-left: 0px;
}
}
#notifications-upper-pagination {
margin-top: 4px;
}
#notifications-bottom-pagination {
* {
display: inline-block;
}
a {
font-size: 20px;
&:hover {
text-decoration: none;
}
}
.page-numbers {
padding: 25px;
}
}
.pagination {
width: 100%;
}
$(function() {
/* rename */ /* rename */
$("#group-details-h1-name, .group-details-rename-button").click(function() { $("#group-details-h1-name, .group-details-rename-button").click(function() {
$("#group-details-h1-name").hide(); $("#group-details-h1-name span").hide();
$("#group-details-rename").css('display', 'inline'); $("#group-details-rename-form").show().css('display', 'inline-block');
$("#group-details-rename-name").focus(); $("#group-details-rename-name").select();
}); });
/* rename ajax */ /* rename ajax */
$('#group-details-rename-submit').click(function() { $('#group-details-rename-submit').click(function() {
if(!$("#group-details-rename-name")[0].checkValidity()) {
return true;
}
var name = $('#group-details-rename-name').val(); var name = $('#group-details-rename-name').val();
$.ajax({ $.ajax({
method: 'POST', method: 'POST',
url: location.href, url: location.href,
data: {'new_name': name}, data: {'new_name': name},
headers: {"X-CSRFToken": getCookie('csrftoken')}, headers: {"X-CSRFToken": getCookie('csrftoken')},
success: function(data, textStatus, xhr) { success: function(data, textStatus, xhr) {
$("#group-details-h1-name").text(data['new_name']).show(); $("#group-details-h1-name span").text(data.new_name).show();
$('#group-details-rename').hide(); $('#group-details-rename-form').hide();
// addMessage(data['message'], "success");
}, },
error: function(xhr, textStatus, error) { error: function(xhr, textStatus, error) {
addMessage("Error during renaming!", "danger"); addMessage("Error during renaming.", "danger");
} }
}); });
return false; return false;
}); });
});
$(".group-details-help-button").click(function() {
$(".group-details-help").stop().slideToggle();
});
/* for Node removes buttons */
$('.delete-from-group').click(function() {
var href = $(this).attr('href');
var tr = $(this).closest('tr');
var group = $(this).data('group_pk');
var member = $(this).data('member_pk');
var dir = window.location.pathname.indexOf('list') == -1;
addModalConfirmation(removeMember,
{ 'url': href,
'data': [],
'tr': tr,
'group_pk': group,
'member_pk': member,
'type': "user",
'redirect': dir});
return false;
});
function removeMember(data) {
$.ajax({
type: 'POST',
url: data.url,
headers: {"X-CSRFToken": getCookie('csrftoken')},
success: function(re, textStatus, xhr) {
data.tr.fadeOut(function() {
$(this).remove();});
},
error: function(xhr, textStatus, error) {
addMessage('Uh oh :(', 'danger');
}
});
}
$(function() { $(function() {
/* rename */ /* rename */
$("#group-list-rename-button, .group-details-rename-button").click(function() { $("#group-list-rename-button, .group-details-rename-button").click(function() {
$("#group-list-column-name", $(this).closest("tr")).hide(); $(".group-list-column-name", $(this).closest("tr")).hide();
$("#group-list-rename", $(this).closest("tr")).css('display', 'inline'); $("#group-list-rename", $(this).closest("tr")).css('display', 'inline');
$("#group-list-rename").find("input").select(); $("#group-list-rename").find("input").select();
}); });
...@@ -10,7 +10,7 @@ $(function() { ...@@ -10,7 +10,7 @@ $(function() {
$('.group-list-rename-submit').click(function() { $('.group-list-rename-submit').click(function() {
var row = $(this).closest("tr"); var row = $(this).closest("tr");
var name = $('#group-list-rename-name', row).val(); var name = $('#group-list-rename-name', row).val();
var url = '/dashboard/group/' + row.children("td:first-child").text().replace(" ", "") + '/'; var url = row.find(".group-list-column-name a").prop("href");
$.ajax({ $.ajax({
method: 'POST', method: 'POST',
url: url, url: url,
...@@ -18,7 +18,7 @@ $(function() { ...@@ -18,7 +18,7 @@ $(function() {
headers: {"X-CSRFToken": getCookie('csrftoken')}, headers: {"X-CSRFToken": getCookie('csrftoken')},
success: function(data, textStatus, xhr) { success: function(data, textStatus, xhr) {
$("#group-list-column-name", row).html( $(".group-list-column-name", row).html(
$("<a/>", { $("<a/>", {
'class': "real-link", 'class': "real-link",
href: "/dashboard/group/" + data.group_pk + "/", href: "/dashboard/group/" + data.group_pk + "/",
......
$(function() {
nodeCreateLoaded();
});
function nodeCreateLoaded() {
/* no js compatibility */
$('.no-js-hidden').show();
$('.js-hidden').hide();
}
...@@ -15,7 +15,7 @@ $(function() { ...@@ -15,7 +15,7 @@ $(function() {
data: {'new_name': name}, data: {'new_name': name},
headers: {"X-CSRFToken": getCookie('csrftoken')}, headers: {"X-CSRFToken": getCookie('csrftoken')},
success: function(data, textStatus, xhr) { success: function(data, textStatus, xhr) {
$("#node-details-h1-name").text(data['new_name']).show(); $("#node-details-h1-name").text(data.new_name).show();
$('#node-details-rename').hide(); $('#node-details-rename').hide();
// addMessage(data.message, "success"); // addMessage(data.message, "success");
}, },
...@@ -30,20 +30,6 @@ $(function() { ...@@ -30,20 +30,6 @@ $(function() {
$(".node-details-help").stop().slideToggle(); $(".node-details-help").stop().slideToggle();
}); });
/* for Node removes buttons */
$('.node-enable').click(function() {
var node_pk = $(this).data('node-pk');
var dir = window.location.pathname.indexOf('list') == -1;
addModalConfirmation(changeNodeStatus,
{ 'url': '/dashboard/node/status/' + node_pk + '/',
'data': [],
'pk': node_pk,
'type': "node",
'redirect': dir});
return false;
});
// remove trait // remove trait
$('.node-details-remove-trait').click(function() { $('.node-details-remove-trait').click(function() {
var to_remove = $(this).data("trait-pk"); var to_remove = $(this).data("trait-pk");
...@@ -69,22 +55,3 @@ $(function() { ...@@ -69,22 +55,3 @@ $(function() {
}); });
}); });
function changeNodeStatus(data) {
$.ajax({
type: 'POST',
url: data.url,
headers: {"X-CSRFToken": getCookie('csrftoken')},
success: function(re, textStatus, xhr) {
if(!data.redirect) {
selected = [];
addMessage(re.message, 'success');
} else {
window.location.replace('/dashboard');
}
},
error: function(xhr, textStatus, error) {
addMessage('Uh oh :(', 'danger');
}
});
}
$(function() { $(function() {
$(document).ready( function() { $(document).ready( function() {
colortable(); // find disabled nodes, set danger (red) on the rows
}); $('.node-disabled').closest("tr").addClass('danger');
// find disabled nodes, set danger (red) on the rows
function colortable()
{
$('.false').closest("tr").addClass('danger');
$('.true').closest("tr").removeClass('danger');
}
function statuschangeSuccess(tr){
var tspan=tr.children('.enabled').children();
var buttons=tr.children('.actions').children('.btn-group').children('.dropdown-menu').children('li').children('.node-enable');
buttons.each(function(index){
if ($(this).css("display")=="block"){
$(this).css("display","none");
}
else{
$(this).css("display","block");
}
});
if(tspan.hasClass("false")){
tspan.removeClass("false");
tspan.addClass("true");
tspan.text("✔");
}
else{
tspan.removeClass("true");
tspan.addClass("false");
tspan.text("✘");
}
colortable();
}
$('#table_container').on('click','.node-enable',function() {
var tr= $(this).closest("tr");
var pk =$(this).attr('data-node-pk');
var url = $(this).attr('href');
$.ajax({
method: 'POST',
url: url,
data: {'change_status':''},
headers: {"X-CSRFToken": getCookie('csrftoken')},
success: function(data, textStatus, xhr) {
statuschangeSuccess(tr);
},
error: function(xhr, textStatus, error) {
addMessage("Error!", "danger");
}
});
return false;
}); });
}); });
$(function() { $(function() {
/* for template removes buttons */
$('.template-delete').click(function() {
var template_pk = $(this).data('template-pk');
addModalConfirmationOrDisplayMessage(deleteTemplate,
{ 'url': '/dashboard/template/delete/' + template_pk + '/',
'data': [],
'template_pk': template_pk,
});
return false;
});
/* for lease removes buttons */
$('.lease-delete').click(function() {
var lease_pk = $(this).data('lease-pk');
addModalConfirmationOrDisplayMessage(deleteLease,
{ 'url': '/dashboard/lease/delete/' + lease_pk + '/',
'data': [],
'lease_pk': lease_pk,
});
return false;
});
/* template table sort */ /* template table sort */
var ttable = $(".template-list-table").stupidtable(); var ttable = $(".template-list-table").stupidtable();
...@@ -43,67 +21,3 @@ $(function() { ...@@ -43,67 +21,3 @@ $(function() {
event.preventDefault(); event.preventDefault();
}); });
}); });
// send POST request then delete the row in table
function deleteTemplate(data) {
$.ajax({
type: 'POST',
url: data.url,
headers: {"X-CSRFToken": getCookie('csrftoken')},
success: function(re, textStatus, xhr) {
addMessage(re.message, 'success');
$('a[data-template-pk="' + data.template_pk + '"]').closest('tr').fadeOut(function() {
$(this).remove();
});
},
error: function(xhr, textStatus, error) {
addMessage('Uh oh :(', 'danger');
}
});
}
// send POST request then delete the row in table
function deleteLease(data) {
$.ajax({
type: 'POST',
url: data.url,
headers: {"X-CSRFToken": getCookie('csrftoken')},
success: function(re, textStatus, xhr) {
addMessage(re.message, 'success');
$('a[data-lease-pk="' + data.lease_pk + '"]').closest('tr').fadeOut(function() {
$(this).remove();
});
},
error: function(xhr, textStatus, error) {
addMessage('Uh oh :(', 'danger');
}
});
}
function addModalConfirmationOrDisplayMessage(func, data) {
$.ajax({
type: 'GET',
url: data['url'],
data: jQuery.param(data['data']),
success: function(result) {
$('body').append(result);
$('#confirmation-modal').modal('show');
$('#confirmation-modal').on('hidden.bs.modal', function() {
$('#confirmation-modal').remove();
});
$('#confirmation-modal-button').click(function() {
func(data);
$('#confirmation-modal').modal('hide');
});
},
error: function(xhr, textStatus, error) {
if(xhr.status === 403) {
addMessage(gettext("Only the owners can delete the selected object."), "warning");
} else {
addMessage(gettext("An error occurred. (") + xhr.status + ")", 'danger')
}
}
});
}
...@@ -20,15 +20,15 @@ function vmCreateLoaded() { ...@@ -20,15 +20,15 @@ function vmCreateLoaded() {
var template = $(this).data("template-pk"); var template = $(this).data("template-pk");
$.get("/dashboard/vm/create/?template=" + template, function(data) { $.get("/dashboard/vm/create/?template=" + template, function(data) {
var r = $('#create-modal'); r.next('div').remove(); r.remove(); var r = $('#confirmation-modal'); r.next('div').remove(); r.remove();
$('body').append(data); $('body').append(data);
vmCreateLoaded(); vmCreateLoaded();
addSliderMiscs(); addSliderMiscs();
$('#create-modal').modal('show'); $('#confirmation-modal').modal('show');
$('#create-modal').on('hidden.bs.modal', function() { $('#confirmation-modal').on('hidden.bs.modal', function() {
$('#create-modal').remove(); $('#confirmation-modal').remove();
}); });
$("#create-modal").on("shown.bs.modal", function() { $("#confirmation-modal").on("shown.bs.modal", function() {
setDefaultSliderValues(); setDefaultSliderValues();
}); });
}); });
...@@ -48,18 +48,18 @@ function vmCreateLoaded() { ...@@ -48,18 +48,18 @@ function vmCreateLoaded() {
window.location.replace(data.redirect + '#activity'); window.location.replace(data.redirect + '#activity');
} }
else { else {
var r = $('#create-modal'); r.next('div').remove(); r.remove(); var r = $('#confirmation-modal'); r.next('div').remove(); r.remove();
$('body').append(data); $('body').append(data);
vmCreateLoaded(); vmCreateLoaded();
addSliderMiscs(); addSliderMiscs();
$('#create-modal').modal('show'); $('#confirmation-modal').modal('show');
$('#create-modal').on('hidden.bs.modal', function() { $('#confirmation-modal').on('hidden.bs.modal', function() {
$('#create-modal').remove(); $('#confirmation-modal').remove();
}); });
} }
}, },
error: function(xhr, textStatus, error) { error: function(xhr, textStatus, error) {
var r = $('#create-modal'); r.next('div').remove(); r.remove(); var r = $('#confirmation-modal'); r.next('div').remove(); r.remove();
if (xhr.status == 500) { if (xhr.status == 500) {
addMessage("500 Internal Server Error", "danger"); addMessage("500 Internal Server Error", "danger");
...@@ -211,7 +211,7 @@ function vmCustomizeLoaded() { ...@@ -211,7 +211,7 @@ function vmCustomizeLoaded() {
}); });
/* start vm button clicks */ /* start vm button clicks */
$('#vm-create-customized-start').click(function() { $('#confirmation-modal #vm-create-customized-start').click(function() {
var error = false; var error = false;
$(".cpu-count-input, .ram-input, #id_name, #id_amount ").each(function() { $(".cpu-count-input, .ram-input, #id_name, #id_amount ").each(function() {
if(!$(this)[0].checkValidity()) { if(!$(this)[0].checkValidity()) {
...@@ -222,8 +222,6 @@ function vmCustomizeLoaded() { ...@@ -222,8 +222,6 @@ function vmCustomizeLoaded() {
$(this).find("i").prop("class", "fa fa-spinner fa-spin"); $(this).find("i").prop("class", "fa fa-spinner fa-spin");
if($("#create-modal")) return true;
$.ajax({ $.ajax({
url: '/dashboard/vm/create/', url: '/dashboard/vm/create/',
headers: {"X-CSRFToken": getCookie('csrftoken')}, headers: {"X-CSRFToken": getCookie('csrftoken')},
...@@ -238,18 +236,18 @@ function vmCustomizeLoaded() { ...@@ -238,18 +236,18 @@ function vmCustomizeLoaded() {
window.location.href = data.redirect + '#activity'; window.location.href = data.redirect + '#activity';
} }
else { else {
var r = $('#create-modal'); r.next('div').remove(); r.remove(); var r = $('#confirmation-modal'); r.next('div').remove(); r.remove();
$('body').append(data); $('body').append(data);
vmCreateLoaded(); vmCreateLoaded();
addSliderMiscs(); addSliderMiscs();
$('#create-modal').modal('show'); $('#confirmation-modal').modal('show');
$('#create-modal').on('hidden.bs.modal', function() { $('#confirmation-modal').on('hidden.bs.modal', function() {
$('#create-modal').remove(); $('#confirmation-modal').remove();
}); });
} }
}, },
error: function(xhr, textStatus, error) { error: function(xhr, textStatus, error) {
var r = $('#create-modal'); r.next('div').remove(); r.remove(); var r = $('#confirmation-modal'); r.next('div').remove(); r.remove();
if (xhr.status == 500) { if (xhr.status == 500) {
addMessage("500 Internal Server Error", "danger"); addMessage("500 Internal Server Error", "danger");
......
var show_all = false;
var in_progress = false;
var activity_hash = 5;
var Websock_native; // not sure var Websock_native; // not sure
var reload_vm_detail = false;
$(function() { $(function() {
/* do we need to check for new activities */
if(decideActivityRefresh()) {
if(!in_progress) {
checkNewActivity(1);
in_progress = true;
}
}
$('a[href="#activity"]').click(function(){
$('a[href="#activity"] i').addClass('fa-spin');
if(!in_progress) {
checkNewActivity(1);
in_progress = true;
}
});
$("#activity-refresh").on("click", "#show-all-activities", function() {
$(this).find("i").addClass("fa-spinner fa-spin");
show_all = !show_all;
$('a[href="#activity"]').trigger("click");
return false;
});
/* save resources */ /* save resources */
$('#vm-details-resources-save').click(function(e) { $('#vm-details-resources-save').click(function(e) {
var error = false; var error = false;
...@@ -43,7 +16,7 @@ $(function() { ...@@ -43,7 +16,7 @@ $(function() {
var vm = $(this).data("vm"); var vm = $(this).data("vm");
$.ajax({ $.ajax({
type: 'POST', type: 'POST',
url: "/dashboard/vm/" + vm + "/op/resources_change/", url: $(this).parent("form").prop('action'),
data: $('#vm-details-resources-form').serialize(), data: $('#vm-details-resources-form').serialize(),
success: function(data, textStatus, xhr) { success: function(data, textStatus, xhr) {
if(data.success) { if(data.success) {
...@@ -89,17 +62,6 @@ $(function() { ...@@ -89,17 +62,6 @@ $(function() {
return false; return false;
}); });
/* remove port */
$('.vm-details-remove-port').click(function() {
addModalConfirmation(removePort,
{
'url': $(this).prop("href"),
'data': [],
'rule': $(this).data("rule")
});
return false;
});
/* for js fallback */ /* for js fallback */
$("#vm-details-pw-show").parent("div").children("input").prop("type", "password"); $("#vm-details-pw-show").parent("div").children("input").prop("type", "password");
...@@ -108,8 +70,8 @@ $(function() { ...@@ -108,8 +70,8 @@ $(function() {
var input = $(this).parent("div").children("input"); var input = $(this).parent("div").children("input");
var eye = $(this).children("#vm-details-pw-eye"); var eye = $(this).children("#vm-details-pw-eye");
var span = $(this); var span = $(this);
span.tooltip("destroy") span.tooltip("destroy");
if(eye.hasClass("fa-eye")) { if(eye.hasClass("fa-eye")) {
eye.removeClass("fa-eye").addClass("fa-eye-slash"); eye.removeClass("fa-eye").addClass("fa-eye-slash");
input.prop("type", "text"); input.prop("type", "text");
...@@ -123,80 +85,6 @@ $(function() { ...@@ -123,80 +85,6 @@ $(function() {
span.tooltip(); span.tooltip();
}); });
/* change password confirmation */
$("#vm-details-pw-change").click(function() {
$("#vm-details-pw-confirm").fadeIn();
return false;
});
/* change password */
$(".vm-details-pw-confirm-choice").click(function() {
choice = $(this).data("choice");
if(choice) {
pk = $(this).data("vm");
$.ajax({
type: 'POST',
url: "/dashboard/vm/" + pk + "/",
data: {'change_password': 'true'},
headers: {"X-CSRFToken": getCookie('csrftoken')},
success: function(re, textStatus, xhr) {
location.reload();
},
error: function(xhr, textStatus, error) {
if (xhr.status == 500) {
addMessage("Internal Server Error", "danger");
} else {
addMessage(xhr.status + " Unknown Error", "danger");
}
}
});
} else {
$("#vm-details-pw-confirm").fadeOut();
}
return false;
});
/* add network button */
$("#vm-details-network-add").click(function() {
$("#vm-details-network-add-form").toggle();
return false;
});
/* add disk button */
$("#vm-details-disk-add").click(function() {
$("#vm-details-disk-add-for-form").html($("#vm-details-disk-add-form").html());
return false;
});
/* for interface remove buttons */
$('.interface-remove').click(function() {
var interface_pk = $(this).data('interface-pk');
addModalConfirmation(removeInterface,
{ 'url': '/dashboard/interface/' + interface_pk + '/delete/',
'data': [],
'pk': interface_pk,
'type': "interface",
});
return false;
});
/* removing interface post */
function removeInterface(data) {
$.ajax({
type: 'POST',
url: data.url,
headers: {"X-CSRFToken": getCookie('csrftoken')},
success: function(re, textStatus, xhr) {
/* remove the html element */
$('a[data-interface-pk="' + data.pk + '"]').closest("div").fadeOut();
location.reload();
},
error: function(xhr, textStatus, error) {
addMessage('Uh oh :(', 'danger');
}
});
}
/* rename */ /* rename */
$("#vm-details-h1-name, .vm-details-rename-button").click(function() { $("#vm-details-h1-name, .vm-details-rename-button").click(function() {
$("#vm-details-h1-name").hide(); $("#vm-details-h1-name").hide();
...@@ -244,7 +132,7 @@ $(function() { ...@@ -244,7 +132,7 @@ $(function() {
var tmp = ta.val(); var tmp = ta.val();
ta.val(""); ta.val("");
ta.focus(); ta.focus();
ta.val(tmp) ta.val(tmp);
e.preventDefault(); e.preventDefault();
}); });
...@@ -319,7 +207,7 @@ $(function() { ...@@ -319,7 +207,7 @@ $(function() {
$("#dashboard-tutorial-toggle").click(function() { $("#dashboard-tutorial-toggle").click(function() {
var box = $("#alert-new-template"); var box = $("#alert-new-template");
var list = box.find("ol") var list = box.find("ol");
list.stop().slideToggle(function() { list.stop().slideToggle(function() {
var url = box.find("form").prop("action"); var url = box.find("form").prop("action");
var hidden = list.css("display") === "none"; var hidden = list.css("display") === "none";
...@@ -331,114 +219,8 @@ $(function() { ...@@ -331,114 +219,8 @@ $(function() {
headers: {"X-CSRFToken": getCookie('csrftoken')}, headers: {"X-CSRFToken": getCookie('csrftoken')},
success: function(re, textStatus, xhr) {} success: function(re, textStatus, xhr) {}
}); });
}); });
return false; return false;
}); });
}); });
function removePort(data) {
$.ajax({
type: 'POST',
url: data.url,
headers: {"X-CSRFToken": getCookie('csrftoken')},
success: function(re, textStatus, xhr) {
$("a[data-rule=" + data.rule + "]").each(function() {
$(this).closest("tr").fadeOut(500, function() {
$(this).remove();
});
});
addMessage(re.message, "success");
},
error: function(xhr, textStatus, error) {
}
});
}
function decideActivityRefresh() {
var check = false;
/* if something is still spinning */
if($('.timeline .activity i').hasClass('fa-spin'))
check = true;
return check;
}
function checkNewActivity(runs) {
var instance = location.href.split('/'); instance = instance[instance.length - 2];
$.ajax({
type: 'GET',
url: '/dashboard/vm/' + instance + '/activity/',
data: {'show_all': show_all},
success: function(data) {
var new_activity_hash = (data.activities + "").hashCode();
if(new_activity_hash != activity_hash) {
$("#activity-refresh").html(data.activities);
}
activity_hash = new_activity_hash;
$("#ops").html(data.ops);
$("#disk-ops").html(data.disk_ops);
$("[title]").tooltip();
/* changing the status text */
var icon = $("#vm-details-state i");
if(data.is_new_state) {
if(!icon.hasClass("fa-spin"))
icon.prop("class", "fa fa-spinner fa-spin");
} else {
icon.prop("class", "fa " + data.icon);
}
$("#vm-details-state").data("status", data['status']);
$("#vm-details-state span").html(data['human_readable_status'].toUpperCase());
if(data['status'] == "RUNNING") {
if(data['connect_uri']) {
$("#dashboard-vm-details-connect-button").removeClass('disabled');
}
$("[data-target=#_console]").attr("data-toggle", "pill").attr("href", "#console").parent("li").removeClass("disabled");
} else {
if(data['connect_uri']) {
$("#dashboard-vm-details-connect-button").addClass('disabled');
}
$("[data-target=#_console]").attr("data-toggle", "_pill").attr("href", "#").parent("li").addClass("disabled");
}
if(data.status == "STOPPED" || data.status == "PENDING") {
$(".change-resources-button").prop("disabled", false);
$(".change-resources-help").hide();
} else {
$(".change-resources-button").prop("disabled", true);
$(".change-resources-help").show();
}
if(runs > 0 && decideActivityRefresh()) {
setTimeout(
function() {checkNewActivity(runs + 1);},
1000 + Math.exp(runs * 0.05)