Commit c4b25bb6 authored by Vangelis Koukis's avatar Vangelis Koukis
Browse files

Merge branch 'reconcilation'

parents 6ca730ea 6c00ebec
......@@ -142,6 +142,35 @@ to Synnefo v0.3.
VNCAUTHPROXY_CTRL_SOCKET.
-Administration
* Reconciliation process: On certain occasions, such as a Ganeti or
RabbitMQ failure, the VM state in the system's database may differ from
that in the Ganeti installation. The reconciliation process is designed
to bring the system's database in sync with what Ganeti knows about
each VM.
The reconciliation process can be triggered for all VMs using the command
./manage.py reconcile --all
It is advised, though not strictly necessary, to run the reconciliation
process periodically, through cron. To avoid overloading the Ganeti
master, the periodic reconciliation process takes a staggered approach
to updating the VMs, which is configured through the following
parameters:
* The settings.py parameter: RECONCILIATION_MIN, which specifies the
maximum time a VM can remain ``non-reconciled''. (default: 30 mins)
* The --interval option to the reconcile command, which declares the
interval time between reconciliation attempts (default: 1 min)
On each invocation of the reconcile command, the system will trigger a
reconciliation for ((num_all_vms/RECONCILIATION_MIN) * interval)
machines. Obviously the less the interval value and the more the
RECONCILIATION_MIN setting, the less load is going to be put on Ganeti.
- OS Specific instructions
* Debian Squeeze
......
......@@ -19,6 +19,13 @@ also, depending on the database engine of choice, on one of the following:
- MySQL-python [MySQL-python==1.2.3]
- psycopg2 [psycopg2==2.4]
if the invitations application is deployed, the following
dependencies should be installed
-pycrypto==2.1.0
if you want to test the ganeti
to run the user interface tests, selenium must be installed
- selenium [?]
......
......@@ -8,7 +8,8 @@
"uniq" :"test@synnefo.gr",
"credit": 10,
"auth_token": "46e427d657b20defe352804f0eb6f8a2",
"auth_token_created": "2009-04-07 09:17:14",
"auth_token_created": "2011-04-07 09:17:14",
"auth_token_expires": "2015-04-07 09:17:14",
"type": "STUDENT",
"created": "2011-02-06"
}
......
......@@ -3,7 +3,6 @@ from django.http import HttpResponse, HttpResponseRedirect
from synnefo.db.models import SynnefoUser
from synnefo.aai.shibboleth import Tokens, register_shibboleth_user
import time
import datetime
class SynnefoAuthMiddleware(object):
......@@ -15,11 +14,15 @@ class SynnefoAuthMiddleware(object):
if request.path.startswith('/api/') :
return
if request.path.startswith('/invitations/login') :
return
# Special case for testing purposes, delivers the cookie for the
# test user on first access
# TODO: REMOVE THE FOLLOWING BEFORE DEPLOYMENT
if request.GET.get('test') is not None:
u = SynnefoUser.objects.get(auth_token='46e427d657b20defe352804f0eb6f8a2')
if settings.BYPASS_AUTHENTICATION and \
request.GET.get('test') is not None:
u = SynnefoUser.objects.get(
auth_token='46e427d657b20defe352804f0eb6f8a2')
return self._redirect_shib_auth_user(user = u)
token = None
......@@ -43,8 +46,7 @@ class SynnefoAuthMiddleware(object):
#Check user's auth token
if (time.time() -
time.mktime(user.auth_token_created.timetuple()) -
settings.AUTH_TOKEN_DURATION * 3600) > 0:
time.mktime(user.auth_token_expires.timetuple())) > 0:
#The user's token has expired, re-login
return HttpResponseRedirect(settings.APP_INSTALL_URL + settings.LOGIN_PATH)
......@@ -92,8 +94,7 @@ class SynnefoAuthMiddleware(object):
return response
def _redirect_shib_auth_user(self, user):
expire = user.auth_token_created + datetime.timedelta(hours=settings.AUTH_TOKEN_DURATION)
expire_fmt = expire.strftime('%a, %d-%b-%Y %H:%M:%S %Z')
expire_fmt = user.auth_token_expires.strftime('%a, %d-%b-%Y %H:%M:%S %Z')
response = HttpResponse()
......
......@@ -6,6 +6,7 @@
from synnefo.logic import users
class Tokens:
SIB_NAME = "Shib-InetOrgPerson-givenName"
SIB_SURNAME = "Shib-Person-surname"
......@@ -17,20 +18,16 @@ class Tokens:
SIB_GR_EDU_PERSON_UNDERGRADUATE_BRANCH = "grEduPersonUndergraduateBranch"
SIB_SESSION_ID = "Shib-Session-ID"
class NoUniqueToken(object):
class NoUniqueToken(BaseException):
def __init__(self, msg):
self.msg = msg
pass
class NoRealName(object):
class NoRealName(BaseException):
def __init__(self, msg):
self.msg = msg
pass
def register_shibboleth_user(tokens):
"""Registers a sibbolleth user using the input hash as a source for data.
The token requirements are described in:
......@@ -61,8 +58,8 @@ def register_shibboleth_user(tokens):
raise NoRealName("Authentication does not return the user's name")
if is_student:
users.register_student(realname, '' ,unq)
users.register_student(realname, '' , unq)
else:
users.register_professor(realname, '' ,unq)
users.register_professor(realname, '' , unq)
return True
......@@ -5,7 +5,6 @@
#
# Copyright 2011 Greek Research and Technology Network
#
from Cookie import Cookie
from django.test import TestCase
from django.test.client import Client
......@@ -15,7 +14,8 @@ from synnefo.db.models import SynnefoUser
from datetime import datetime, timedelta
from synnefo.aai.shibboleth import Tokens, NoUniqueToken
from synnefo.aai.shibboleth import Tokens
class AaiTestCase(TestCase):
fixtures = ['api_test_data', 'auth_test_data']
......@@ -45,7 +45,6 @@ class AaiTestCase(TestCase):
self.assertEquals(response['X-Auth-Token'], user.auth_token)
#self.assertNotEquals(response.cookies['X-Auth-Token'].find(user.auth_token), -1)
def test_shibboleth_no_uniq_request(self):
"""test a request with no unique field
"""
......@@ -55,13 +54,13 @@ class AaiTestCase(TestCase):
'TEST-AAI': 'true'})
self._test_redirect(response)
def test_shibboleth_expired_token(self):
""" test request from expired token
"""
user = SynnefoUser.objects.get(uniq="test@synnefo.gr")
self.assertNotEqual(user.auth_token_created, None)
self._update_user_ts(user)
self.assertNotEqual(user.auth_token_expires, None)
user.auth_token_expires = datetime.now()
user.save()
response = self.client.get('/index.html', {},
**{'X-Auth-Token': user.auth_token,
'TEST-AAI': 'true'})
......@@ -84,12 +83,18 @@ class AaiTestCase(TestCase):
self.assertTrue('Vary' in response)
self.assertTrue('X-Auth-Token' in response['Vary'])
def test_auth_cookie(self):
user = SynnefoUser.objects.get(uniq = "test@synnefo.gr")
self.client.cookies['X-Auth-Token'] = user.auth_token
response = self.client.get('/', {},
**{'X-Auth-Token': user.auth_token,
'TEST-AAI' : 'true'})
self.assertTrue(response.status_code, 200)
self.assertTrue('Vary' in response)
self.assertTrue('X-Auth-Token' in response['Vary'])
def _test_redirect(self, response):
self.assertEquals(response.status_code, 302)
self.assertTrue('Location' in response)
self.assertTrue(response['Location'].endswith(settings.LOGIN_PATH))
def _update_user_ts(self, user):
user.auth_token_created = (datetime.now() -
timedelta(hours = settings.AUTH_TOKEN_DURATION))
user.save()
\ No newline at end of file
......@@ -37,8 +37,7 @@ class ApiAuthMiddleware(object):
#Check user's auth token
if (time.time() -
time.mktime(user.auth_token_created.timetuple()) -
settings.AUTH_TOKEN_DURATION * 3600) > 0:
time.mktime(user.auth_token_expires.timetuple())) > 0:
#The user's token has expired, re-login
user = None
......
......@@ -812,16 +812,6 @@ class AaiTestCase(TestCase):
def setUp(self):
self.client = Client()
def test_auth_cookie(self):
user = SynnefoUser.objects.get(uniq = "test@synnefo.gr")
self.client.cookies['X-Auth-Token'] = user.auth_token
response = self.client.get('/index.html', {},
**{'X-Auth-Token': user.auth_token,
'TEST-AAI' : 'true'})
self.assertTrue(response.status_code, 200)
self.assertTrue('Vary' in response)
self.assertTrue('X-Auth-Token' in response['Vary'])
def test_fail_oapi_auth(self):
""" test authentication from not registered user using OpenAPI
"""
......
......@@ -8,3 +8,4 @@ psycopg2==2.4
south==0.7.1
amqplib==0.6.1
daemon==1.0
pycrypto==2.1.0
......@@ -9,6 +9,7 @@
"credit": 10,
"auth_token": "46e427d657b20defe352804f0eb6f8a2",
"auth_token_created": "2009-04-07 09:17:14",
"auth_token_expires": "2015-04-07 09:17:14",
"type": "STUDENT",
"created": "2011-02-06"
}
......
......@@ -9,6 +9,7 @@
"credit": 10,
"auth_token": "46e427d657b20defe352804f0eb6f8a2",
"auth_token_created": "2011-05-10",
"auth_token_expires": "2015-05-10",
"type": "STUDENT",
"created": "2011-05-10"
}
......
# encoding: 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 'Invitations'
db.create_table('db_invitations', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('source', self.gf('django.db.models.fields.related.ForeignKey')(related_name='source', to=orm['db.SynnefoUser'])),
('target', self.gf('django.db.models.fields.related.ForeignKey')(related_name='target', to=orm['db.SynnefoUser'])),
('accepted', self.gf('django.db.models.fields.BooleanField')(default=False, blank=True)),
('created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)),
('updated', self.gf('django.db.models.fields.DateTimeField')(auto_now=True, blank=True)),
))
db.send_create_signal('db', ['Invitations'])
def backwards(self, orm):
# Deleting model 'Invitations'
db.delete_table('db_invitations')
models = {
'db.debit': {
'Meta': {'object_name': 'Debit'},
'description': ('django.db.models.fields.TextField', [], {}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['db.SynnefoUser']"}),
'vm': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['db.VirtualMachine']"}),
'when': ('django.db.models.fields.DateTimeField', [], {})
},
'db.disk': {
'Meta': {'object_name': 'Disk'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['db.SynnefoUser']", 'null': 'True', 'blank': 'True'}),
'size': ('django.db.models.fields.PositiveIntegerField', [], {}),
'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'vm': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['db.VirtualMachine']", 'null': 'True', 'blank': 'True'})
},
'db.flavor': {
'Meta': {'unique_together': "(('cpu', 'ram', 'disk'),)", 'object_name': 'Flavor'},
'cpu': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'disk': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'ram': ('django.db.models.fields.IntegerField', [], {'default': '0'})
},
'db.flavorcost': {
'Meta': {'object_name': 'FlavorCost'},
'cost_active': ('django.db.models.fields.PositiveIntegerField', [], {}),
'cost_inactive': ('django.db.models.fields.PositiveIntegerField', [], {}),
'effective_from': ('django.db.models.fields.DateTimeField', [], {}),
'flavor': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['db.Flavor']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
'db.image': {
'Meta': {'object_name': 'Image'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['db.SynnefoUser']", 'null': 'True', 'blank': 'True'}),
'sourcevm': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['db.VirtualMachine']", 'null': 'True'}),
'state': ('django.db.models.fields.CharField', [], {'max_length': '30'}),
'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'})
},
'db.imagemetadata': {
'Meta': {'object_name': 'ImageMetadata'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'image': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['db.Image']"}),
'meta_key': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
'meta_value': ('django.db.models.fields.CharField', [], {'max_length': '500'})
},
'db.invitations': {
'Meta': {'object_name': 'Invitations'},
'accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'source': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'source'", 'to': "orm['db.SynnefoUser']"}),
'target': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'target'", 'to': "orm['db.SynnefoUser']"}),
'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'})
},
'db.limit': {
'Meta': {'object_name': 'Limit'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '30'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['db.SynnefoUser']"}),
'value': ('django.db.models.fields.IntegerField', [], {})
},
'db.network': {
'Meta': {'object_name': 'Network'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'machines': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['db.VirtualMachine']", 'symmetrical': 'False'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['db.SynnefoUser']"}),
'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'})
},
'db.synnefouser': {
'Meta': {'object_name': 'SynnefoUser'},
'auth_token': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}),
'auth_token_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'credit': ('django.db.models.fields.IntegerField', [], {}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '255'}),
'realname': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '255'}),
'type': ('django.db.models.fields.CharField', [], {'max_length': '30'}),
'uniq': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'})
},
'db.virtualmachine': {
'Meta': {'object_name': 'VirtualMachine'},
'action': ('django.db.models.fields.CharField', [], {'max_length': '30', 'null': 'True'}),
'backendjobid': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True'}),
'backendjobstatus': ('django.db.models.fields.CharField', [], {'max_length': '30', 'null': 'True'}),
'backendlogmsg': ('django.db.models.fields.TextField', [], {'null': 'True'}),
'backendopcode': ('django.db.models.fields.CharField', [], {'max_length': '30', 'null': 'True'}),
'charged': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2011, 5, 11, 11, 23, 53, 498564)'}),
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
'flavor': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['db.Flavor']"}),
'hostid': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'ipfour': ('django.db.models.fields.IPAddressField', [], {'max_length': '15'}),
'ipsix': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'operstate': ('django.db.models.fields.CharField', [], {'max_length': '30', 'null': 'True'}),
'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['db.SynnefoUser']"}),
'sourceimage': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['db.Image']"}),
'suspended': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'})
},
'db.virtualmachinegroup': {
'Meta': {'object_name': 'VirtualMachineGroup'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'machines': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['db.VirtualMachine']", 'symmetrical': 'False'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['db.SynnefoUser']"}),
'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'})
},
'db.virtualmachinemetadata': {
'Meta': {'object_name': 'VirtualMachineMetadata'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'meta_key': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
'meta_value': ('django.db.models.fields.CharField', [], {'max_length': '500'}),
'vm': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['db.VirtualMachine']"})
}
}
complete_apps = ['db']
# encoding: 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 field 'SynnefoUser.auth_token_expires'
db.add_column('db_synnefouser', 'auth_token_expires', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, null=True, blank=True), keep_default=False)
# Changing field 'SynnefoUser.auth_token_created'
db.alter_column('db_synnefouser', 'auth_token_created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, null=True, blank=True))
def backwards(self, orm):
# Deleting field 'SynnefoUser.auth_token_expires'
db.delete_column('db_synnefouser', 'auth_token_expires')
# Changing field 'SynnefoUser.auth_token_created'
db.alter_column('db_synnefouser', 'auth_token_created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True))
models = {
'db.debit': {
'Meta': {'object_name': 'Debit'},
'description': ('django.db.models.fields.TextField', [], {}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['db.SynnefoUser']"}),
'vm': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['db.VirtualMachine']"}),
'when': ('django.db.models.fields.DateTimeField', [], {})
},
'db.disk': {
'Meta': {'object_name': 'Disk'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['db.SynnefoUser']", 'null': 'True', 'blank': 'True'}),
'size': ('django.db.models.fields.PositiveIntegerField', [], {}),
'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'vm': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['db.VirtualMachine']", 'null': 'True', 'blank': 'True'})
},
'db.flavor': {
'Meta': {'unique_together': "(('cpu', 'ram', 'disk'),)", 'object_name': 'Flavor'},
'cpu': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'disk': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'ram': ('django.db.models.fields.IntegerField', [], {'default': '0'})
},
'db.flavorcost': {
'Meta': {'object_name': 'FlavorCost'},
'cost_active': ('django.db.models.fields.PositiveIntegerField', [], {}),
'cost_inactive': ('django.db.models.fields.PositiveIntegerField', [], {}),
'effective_from': ('django.db.models.fields.DateTimeField', [], {}),
'flavor': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['db.Flavor']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
'db.image': {
'Meta': {'object_name': 'Image'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['db.SynnefoUser']", 'null': 'True', 'blank': 'True'}),
'sourcevm': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['db.VirtualMachine']", 'null': 'True'}),
'state': ('django.db.models.fields.CharField', [], {'max_length': '30'}),
'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'})
},
'db.imagemetadata': {
'Meta': {'object_name': 'ImageMetadata'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'image': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['db.Image']"}),
'meta_key': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
'meta_value': ('django.db.models.fields.CharField', [], {'max_length': '500'})
},
'db.invitations': {
'Meta': {'object_name': 'Invitations'},
'accepted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'source': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'source'", 'to': "orm['db.SynnefoUser']"}),
'target': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'target'", 'to': "orm['db.SynnefoUser']"}),
'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'})
},
'db.limit': {
'Meta': {'object_name': 'Limit'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '30'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['db.SynnefoUser']"}),
'value': ('django.db.models.fields.IntegerField', [], {})
},
'db.network': {
'Meta': {'object_name': 'Network'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'machines': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['db.VirtualMachine']", 'symmetrical': 'False'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['db.SynnefoUser']"}),
'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'})
},
'db.synnefouser': {
'Meta': {'object_name': 'SynnefoUser'},
'auth_token': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}),
'auth_token_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'null': 'True', 'blank': 'True'}),
'auth_token_expires': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'null': 'True', 'blank': 'True'}),
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'credit': ('django.db.models.fields.IntegerField', [], {}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '255'}),
'realname': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '255'}),
'type': ('django.db.models.fields.CharField', [], {'max_length': '30'}),
'uniq': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'})
},
'db.virtualmachine': {
'Meta': {'object_name': 'VirtualMachine'},
'action': ('django.db.models.fields.CharField', [], {'max_length': '30', 'null': 'True'}),
'backendjobid': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True'}),
'backendjobstatus': ('django.db.models.fields.CharField', [], {'max_length': '30', 'null': 'True'}),
'backendlogmsg': ('django.db.models.fields.TextField', [], {'null': 'True'}),
'backendopcode': ('django.db.models.fields.CharField', [], {'max_length': '30', 'null': 'True'}),
'charged': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2011, 5, 20, 8, 2, 25, 55390)'}),
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'deleted': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
'flavor': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['db.Flavor']"}),
'hostid': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'ipfour': ('django.db.models.fields.IPAddressField', [], {'max_length': '15'}),
'ipsix': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'operstate': ('django.db.models.fields.CharField', [], {'max_length': '30', 'null': 'True'}),
'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['db.SynnefoUser']"}),
'sourceimage': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['db.Image']"}),
'suspended': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'})
},
'db.virtualmachinegroup': {
'Meta': {'object_name': 'VirtualMachineGroup'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'machines': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['db.VirtualMachine']", 'symmetrical': 'False'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'owner': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['db.SynnefoUser']"}),
'updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'})
},
'db.virtualmachinemetadata': {
'Meta': {'object_name': 'VirtualMachineMetadata'},