Merge branch 'onelab' of ssh://git.onelab.eu/git/myslice into onelab
authorYasin Rahman <loic.baron@lip6.fr>
Fri, 13 Mar 2015 13:29:29 +0000 (14:29 +0100)
committerYasin Rahman <loic.baron@lip6.fr>
Fri, 13 Mar 2015 13:29:29 +0000 (14:29 +0100)
12 files changed:
.gitignore
forge/urls.py [new file with mode: 0644]
influxdb/__init__.py [new file with mode: 0644]
influxdb/client.py [new file with mode: 0644]
influxdb/urls.py [new file with mode: 0644]
manifoldapi/manifoldapi.py
myslice/components.py [new file with mode: 0644]
myslice/myslice.ini.dist [new file with mode: 0644]
myslice/settings.py
myslice/urls.py
plugins/scheduler2/static/js/scheduler2.js
portal/migrations/0012_initial.py [deleted file]

index bf4b0b5..21f5aa6 100644 (file)
@@ -16,9 +16,10 @@ plugins/*/*.css
 plugins/*/*.js
 plugins/*/*.html
 # myslice.ini* is not intended to be under git as it may contain keys and other specifics
-myslice.ini*
-# other junk
+myslice.ini
+#other junk
 foo.*
 .project
+.settings
 .pydevproject
-/sla/trashcan
\ No newline at end of file
+/sla/trashcan
diff --git a/forge/urls.py b/forge/urls.py
new file mode 100644 (file)
index 0000000..9ede7e3
--- /dev/null
@@ -0,0 +1,7 @@
+from django.conf.urls import patterns, url, include
+
+import forge.views
+
+urlpatterns = patterns('',
+                (r'^studentslabs/(?P<slicename>[^/]+)/?$', forge.views.CreateCourseViev.as_view())
+)
\ No newline at end of file
diff --git a/influxdb/__init__.py b/influxdb/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/influxdb/client.py b/influxdb/client.py
new file mode 100644 (file)
index 0000000..50daa30
--- /dev/null
@@ -0,0 +1,119 @@
+from django.http import HttpResponse
+from rest import error
+import os,json
+import ConfigParser
+import string, random
+
+from portal.models import MeasurementsDB
+
+from manifold.core.query             import Query, AnalyzedQuery
+from manifoldapi.manifoldapi         import execute_query
+
+from influxdb import InfluxDBClient
+
+def createDatabase(request, slicename):
+    result = {}
+    
+    Config = config(request)
+    
+    server = Config.get('influxdb', 'server')
+    #port = Config.get('influxdb', 'port', 8086)
+    port = 8086
+    user = Config.get('influxdb', 'user')
+    password = Config.get('influxdb', 'password')
+    
+    dbname = slicename
+    dbuser = request.user.username
+    dbpassword = generatePassword()
+    
+    query = Query().get('user').filter_by('user_email', '==', dbuser).select('slices')
+    slices = execute_query(request, query)
+    
+    if not slicename in slices:
+        result['status'] = 'fail'
+        result['message'] = 'no permissions'
+        return HttpResponse(json.dumps(result), content_type="application/json")
+
+    client = InfluxDBClient(server, port, user, password, dbname)
+    
+    try :
+        client.create_database(dbname)
+    except Exception as e:
+        print e
+    
+    # Add database user
+    try :
+        client.add_database_user(dbuser, dbpassword)
+    except Exception as e:
+        print e
+    
+    # Make user a database admin
+    client.set_database_admin(dbuser)
+    
+    
+    # Insert an entry in the Influxdb table
+    i = MeasurementsDB(
+        backend         = 'influxdb',
+        server          = server,
+        port            = port,
+        dbname          = dbname,
+        dbuser          = dbuser,
+        dbpassword      = dbpassword
+    )
+    i.save()
+    
+    
+    result['status'] = 'ok'
+
+    return HttpResponse(json.dumps(result), content_type="application/json")
+
+def infoDatabase(request, slicename):
+    Config = config(request)
+    
+    res = MeasurementsDB.objects.get(dbname=slicename, dbuser=request.user.username)
+    result = {
+              'server' : res.server,
+              'port' : res.port,
+              'dbname' : res.dbname,
+              'dbuser' : res.dbuser,
+              'dbpassword' : res.dbpassword
+              }
+    return HttpResponse(json.dumps(result), content_type="application/json")
+
+def config(request):
+    Config = ConfigParser.ConfigParser()
+    Config.read(os.getcwd() + "/myslice/measurements.ini")
+
+    if not request.user.is_authenticated :
+        return HttpResponse(json.dumps({'error' : 'not authenticated'}), content_type="application/json")
+    
+    #if Config.has_section('influxdb') :
+    if not Config.has_option('influxdb', 'server') :
+        return HttpResponse(json.dumps({'error' : 'server not specified'}), content_type="application/json")
+    
+    if not Config.has_option('influxdb', 'user') :
+        return HttpResponse(json.dumps({'error' : 'user not specified'}), content_type="application/json")
+    
+    if not Config.has_option('influxdb', 'password') :
+        return HttpResponse(json.dumps({'error' : 'server not specified'}), content_type="application/json")
+    
+    return Config
+
+def generatePassword():
+    password_len = 16
+    password = []
+    
+    for group in (string.ascii_letters, string.punctuation, string.digits):
+        password += random.sample(group, 3)
+    
+    password += random.sample(
+                     string.ascii_letters + string.punctuation + string.digits,
+                     password_len - len(password))
+    
+    random.shuffle(password)
+    password = ''.join(password)
+    
+    
+    return password
+    
+
diff --git a/influxdb/urls.py b/influxdb/urls.py
new file mode 100644 (file)
index 0000000..bf47489
--- /dev/null
@@ -0,0 +1,6 @@
+from django.conf.urls import patterns, url, include
+
+urlpatterns = patterns('',
+                (r'^influxdb/create/(?P<slicename>[^/]+)/?$', 'influxdb.client.createDatabase'),
+                (r'^influxdb/info/(?P<slicename>[^/]+)/?$', 'influxdb.client.infoDatabase'),
+)
\ No newline at end of file
index 8ba7e15..796d0a5 100644 (file)
@@ -1,5 +1,5 @@
 # Manifold API Python interface
-import copy, xmlrpclib
+import copy, xmlrpclib, ssl
 
 from myslice.configengine import ConfigEngine
 
@@ -41,8 +41,13 @@ class ManifoldAPI:
         self.calls = {}
         self.multicall = False
         self.url = ConfigEngine().manifold_url()
-        # for more debug on this link, set verbose=True
-        self.server = xmlrpclib.Server(self.url, verbose=False, allow_none=True)
+        
+        # Manifold uses a self signed certificate
+        # https://www.python.org/dev/peps/pep-0476/
+        if hasattr(ssl, '_create_unverified_context'): 
+            self.server = xmlrpclib.Server(self.url, verbose=False, allow_none=True, context=ssl._create_unverified_context())
+        else :
+            self.server = xmlrpclib.Server(self.url, verbose=False, allow_none=True)
 
     def __repr__ (self): return "ManifoldAPI[%s]"%self.url
 
diff --git a/myslice/components.py b/myslice/components.py
new file mode 100644 (file)
index 0000000..cfabb63
--- /dev/null
@@ -0,0 +1,20 @@
+from django.conf.urls import include, url
+from myslice.configengine import ConfigEngine
+
+def list():
+    config = ConfigEngine()
+    return config.myslice.components.split(',')
+
+def urls():
+    u = []
+    for component in list():
+        try:
+            __import__(component)
+            u.append( url(r'^%s/' % component, include('%s.urls' % component)) )
+        except Exception, e:
+            print "-> Cannot load component (%s): %s" % (component, e)
+        else:
+            print "-> Loaded component %s" % component
+            
+    return u
+
diff --git a/myslice/myslice.ini.dist b/myslice/myslice.ini.dist
new file mode 100644 (file)
index 0000000..dadcb71
--- /dev/null
@@ -0,0 +1,27 @@
+[manifold]
+url = https://portal.onelab.eu:7080
+admin_user = 
+admin_password = 
+
+[myslice]
+theme = onelab
+debug = true
+httproot =
+dataroot =
+components = sla,influxdb,forge
+
+[database]
+# postgresql_psycopg2, mysql, sqlite3 or oracle
+engine = sqlite3
+name = myslice
+server = 
+port = 
+user =
+password =
+
+
+
+[activity]
+#server = http://athos.ipv6.lip6.fr/activity/push/log
+#apikey = 
+#secret = 
index 10b3953..6a4518c 100644 (file)
@@ -1,11 +1,17 @@
-# Django settings for unfold project.
+#from __future__ import print_function
+import os.path
 
-from __future__ import print_function
+try:
+    ROOT = os.path.realpath(os.path.dirname(__file__) + '/..')
+except:
+    import traceback
+    traceback.print_exc()
 
-import os.path
+import myslice.components as components
+from myslice.configengine import ConfigEngine
 
-import djcelery
-djcelery.setup_loader()
+import djcelery
+djcelery.setup_loader()
 
 ### detect if we're in a build environment
 try:
@@ -14,59 +20,31 @@ try:
 except:
     building=True
 
-DEBUG = True
+config = ConfigEngine()
 
-# show the various settings as we go
-DEBUG_SETTINGS = False
+if config.myslice.debug :
+    DEBUG = True
+else :
+    DEBUG = False
 
-# compute ROOT from where this file is installed
-# should fit every need including developers
-# but you can redefine ROOT if that's not working for you
-try:
-    # get the directory where this file is
-    ROOT=os.path.dirname(__file__) or '.'
-    # move one step up
-    ROOT=os.path.realpath(ROOT+'/..')
-except:
-    # something is badly wrong here
-    ROOT=None
-    import traceback
-    traceback.print_exc()
-
-#### this is where the problem lies I believe
-# first try to run manage.py collectstatic without this
 # themes
-theme=None
-try:
-    from myslice.configengine import ConfigEngine
-    configEngine = ConfigEngine()
-    if configEngine.myslice.theme :
-        theme = configEngine.myslice.theme
-except:
-    pass
-    
-# find out HTTPROOT, which is different from ROOT 
-# when deployed from a package
-# this code is run by collectstatic too, so we cannot
-# assume we have ./static present already
-HTTPROOT="/var/myslice-f4f"
-# the place to store local data, like e.g. the sqlite db
-DATAROOT="/var/unfold"
-if not os.path.isdir(DATAROOT):
-    print("WARNING: {} is a non-existing directory".format(DATAROOT))
-    print("consequently we assume development mode and re-route DATAROOT to {}".format(ROOT))
-    DATAROOT=ROOT
-# if not there, then we assume it's from a devel tree
-if not os.path.isdir (os.path.join(HTTPROOT,"static")):
-    HTTPROOT=ROOT
-
-if not os.path.isdir(ROOT): raise Exception,"Cannot find ROOT %s for unfold"%ROOT
-if not os.path.isdir(HTTPROOT): raise Exception,"Cannot find HTTPROOT %s for unfold"%HTTPROOT
-
-if DEBUG_SETTINGS:
-    print('ROOT', ROOT)
-    print('DATAROOT', DATAROOT)
-    print('HTTPROOT', HTTPROOT)
+if config.myslice.theme :
+    theme = config.myslice.theme
+else :
+    theme = None
+
+# HTTPROOT
+if config.myslice.httproot :
+    HTTPROOT = config.myslice.httproot
+else :
+    HTTPROOT = ROOT
+
+# DATAROOT
+if config.myslice.httproot :
+    DATAROOT = config.myslice.dataroot
+else :
+    DATAROOT = ROOT
+
 
 # dec 2013 - we currently have 2 auxiliary subdirs with various utilities
 # that we do not wish to package 
@@ -103,20 +81,33 @@ EMAIL_USE_TLS = False
 #    EMAIL_USE_TLS = False
 #    DEFAULT_FROM_EMAIL = 'testing@example.com'
 
-DATABASES = {
-    'default': {
-        'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'.
-        'NAME': os.path.join(DATAROOT,'unfold.sqlite3'), # Or path to database file if using sqlite3.
-        'USER': '',                      # Not used with sqlite3.
-        'PASSWORD': '',                  # Not used with sqlite3.
-        'HOST': '',                      # Set to empty string for localhost. Not used with sqlite3.
-        'PORT': '',                      # Set to empty string for default. Not used with sqlite3.
+if config.database : 
+    DATABASES = {
+        'default': {
+            'ENGINE'    : 'django.db.backends.%s' % config.database.engine,
+            'USER'      : config.database.user or '',
+            'PASSWORD'  : config.database.password or '',
+            'HOST'      : config.database.host or '',
+            'PORT'      : config.database.port or '',
+        }
     }
-}
-
-if DEBUG_SETTINGS:
-    print('DATABASE NAME',DATABASES['default']['NAME'])
-
+    if config.database.engine == 'sqlite3' :
+        DATABASES['default']['NAME'] = os.path.join(DATAROOT,'%s.sqlite3' % config.database.name)
+    else :
+        DATABASES['default']['NAME'] = config.database.name
+else :
+    # default database is sqlite
+    DATABASES = {
+        'default': {
+            'ENGINE'    : 'django.db.backends.sqlite3',
+            'NAME'      : os.path.join(DATAROOT,'myslice.sqlite3'),
+            'USER'      : '',
+            'PASSWORD'  : '',
+            'HOST'      : '',
+            'PORT'      : '',
+        }
+    }
+print DATABASES
 # Local time zone for this installation. Choices can be found here:
 # http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
 # although not all choices may be available on all operating systems.
@@ -219,14 +210,14 @@ ROOT_URLCONF = 'myslice.urls'
 # Python dotted path to the WSGI application used by Django's runserver.
 WSGI_APPLICATION = 'unfold.wsgi.application'
 
-TEMPLATE_DIRS = [ ]
+TEMPLATE_DIRS = []
 # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
 # Always use forward slashes, even on Windows.
 # Don't forget to use absolute paths, not relative paths.
 if theme is not None:
-    TEMPLATE_DIRS.append ( os.path.join(HTTPROOT,"portal/templates", theme))
-TEMPLATE_DIRS.append     ( os.path.join(HTTPROOT,"portal/templates"))
-TEMPLATE_DIRS.append     (  os.path.join(HTTPROOT,"templates"))
+    TEMPLATE_DIRS.append( os.path.join(HTTPROOT,"portal/templates", theme) )
+TEMPLATE_DIRS.append( os.path.join(HTTPROOT,"portal/templates") )
+TEMPLATE_DIRS.append( os.path.join(HTTPROOT,"templates") )
 
 INSTALLED_APPS = [ 
     'django.contrib.auth',
@@ -253,17 +244,17 @@ INSTALLED_APPS = [
     # Uncomment the next line to enable the admin:
      'django.contrib.admin',
        # FORGE Plugin app
-       'djcelery',
-       'forge',
+#      'djcelery',
     # Uncomment the next line to enable admin documentation:
     # 'django.contrib.admindocs',
     'portal',
-    # SLA
-    'sla',
 ]
 # this app won't load in a build environment
 if not building: INSTALLED_APPS.append ('rest')
 
+for component in components.list() :
+    INSTALLED_APPS.append(component)
+
 BROKER_URL = "amqp://myslice:myslice@localhost:5672/myslice"
 
 for aux in auxiliaries:
index ca150a4..ad15178 100644 (file)
@@ -2,6 +2,11 @@ from django.conf.urls import patterns, include, url
 from django.conf      import settings
 from django.contrib import admin
 
+##
+# components module
+##
+import components
+
 # Uncomment the next two lines to enable the admin:
 # from django.contrib import admin
 # admin.autodiscover()
@@ -12,24 +17,20 @@ add_to_builtins('insert_above.templatetags.insert_tags')
 
 from settings import auxiliaries, INSTALLED_APPS
 
+import portal.about
+import portal.institution
+import portal.registrationview
+import portal.accountview
+import portal.contactview
+import portal.termsview
+import portal.supportview
+
 import portal.platformsview
 import portal.dashboardview
 import portal.homeview
 import portal.newsview
 import portal.loginwidget
 
-from portal.about                   import AboutView
-from portal.registrationview        import RegistrationView
-from portal.accountview             import AccountView, account_process
-from portal.institution             import InstitutionView
-
-from portal.supportview             import SupportView
-from portal.contactview             import ContactView
-
-from portal.termsview               import TermsView
-
-home_view=portal.homeview.HomeView.as_view()
-dashboard_view=portal.dashboardview.DashboardView.as_view()
 platforms_view=portal.platformsview.PlatformsView.as_view()
 
 #import portal.testbedlist
@@ -45,19 +46,6 @@ import portal.slicetabmeasurements
 import portal.managementtababout
 import portal.managementtabrequests
 
-import forge.views
-
-#### high level choices
-# main entry point (set to the / URL)
-# beware that if this view is broken you end up in an endless cycle...
-# maybe platforms_view would be best on the longer run
-the_default_view=home_view
-# where to be redirected after login
-the_after_login_view=dashboard_view
-# where to redirect when login is required
-# might need another one ?
-the_login_view=home_view
-admin.autodiscover()
 urls = [
     '',
     # Examples:
@@ -66,17 +54,17 @@ urls = [
     # Uncomment the admin/doc line below to enable admin documentation:
     # url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
     # Uncomment the next line to enable the admin:
-     url(r'^admin/', include(admin.site.urls)),
+    url(r'^admin/', include(admin.site.urls)),
     #
     # default / view
-    (r'^/?$', the_default_view),
+    (r'^/?$', portal.homeview.HomeView.as_view()),
     #
     # login / logout
-    (r'^login-ok/?$', the_after_login_view, {'state': 'Welcome to MySlice'} ),
+    (r'^login-ok/?$', portal.dashboardview.DashboardView.as_view(), {'state': 'Welcome to MySlice'} ),
     #
     # seems to be what login_required uses to redirect ...
-    (r'^accounts/login/$', the_login_view),
-    (r'^login/?$', the_login_view),
+    (r'^accounts/login/$', portal.homeview.HomeView.as_view()),
+    (r'^login/?$', portal.homeview.HomeView.as_view()),
     (r'^logout/?$', 'auth.views.logout_user'),
     #
     # the manifold proxy
@@ -114,20 +102,20 @@ urls = [
     (r'^testbeds/(?P<slicename>[^/]+)/?$', portal.slicetabtestbeds.SliceTabTestbeds.as_view()),
     (r'^measurements/(?P<slicename>[^/]+)/?$', portal.slicetabmeasurements.SliceTabMeasurements.as_view()),
     (r'^experiment/(?P<slicename>[^/]+)/?$', portal.slicetabexperiment.ExperimentView.as_view()),
-    (r'^studentslabs/(?P<slicename>[^/]+)/?$', forge.views.CreateCourseViev.as_view()),
     
-    url(r'^about/?$', AboutView.as_view(), name='about'),
     
-    url(r'^institution/?$', InstitutionView.as_view(), name='institution'),
+    url(r'^about/?$', portal.about.AboutView.as_view(), name='about'),
+    
+    url(r'^institution/?$', portal.institution.InstitutionView.as_view(), name='institution'),
     (r'^management/requests/?$', portal.managementtabrequests.ManagementRequestsView.as_view()),
     (r'^management/about/?$', portal.managementtababout.ManagementAboutView.as_view()),
     #
-    url(r'^register/?$', RegistrationView.as_view(), name='registration'),
-    url(r'^account/?$', AccountView.as_view(), name='account'),
-    url(r'^account/account_process/?$', account_process),
-    url(r'^contact/?$', ContactView.as_view(), name='contact'),
-    url(r'^terms/?$', TermsView.as_view(), name='terms'),
-    url(r'^support/?$', SupportView.as_view(), name='support'),
+    url(r'^register/?$', portal.registrationview.RegistrationView.as_view(), name='registration'),
+    url(r'^account/?$', portal.accountview.AccountView.as_view(), name='account'),
+    url(r'^account/account_process/?$', portal.accountview.account_process),
+    url(r'^contact/?$', portal.contactview.ContactView.as_view(), name='contact'),
+    url(r'^terms/?$', portal.termsview.TermsView.as_view(), name='terms'),
+    url(r'^support/?$', portal.supportview.SupportView.as_view(), name='support'),
     #
     url(r'^portal/', include('portal.urls')),
 
@@ -135,11 +123,13 @@ urls = [
 #    url(r'^sla/', include('sla.urls')),
 ]
 
+urls.extend( components.urls() )
+
 #this one would not match the convention
 # url(r'^debug/', include('debug_platform.urls')),
 # but it was commented out anyways
 for aux in auxiliaries:
     if aux in INSTALLED_APPS:
-        urls.append ( url ( r'^%s/'%aux, include ('%s.urls'%aux )))
+        urls.append ( url ( r'^%s/'%aux, include ('%s.urls' % aux )))
 
 urlpatterns = patterns(*urls)
index a72341e..a13856a 100755 (executable)
@@ -364,7 +364,7 @@ var SCHEDULER_COLWIDTH = 50;
             }
             
 
-            $scope._dump_leases();
+            //$scope._dump_leases();
         };
   
         $scope._dump_leases = function()
diff --git a/portal/migrations/0012_initial.py b/portal/migrations/0012_initial.py
deleted file mode 100644 (file)
index 9b58fae..0000000
+++ /dev/null
@@ -1,189 +0,0 @@
-# -*- 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 'Institution'
-        db.create_table(u'portal_institution', (
-            (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
-            ('name', self.gf('django.db.models.fields.TextField')()),
-        ))
-        db.send_create_signal(u'portal', ['Institution'])
-
-        # Adding model 'PendingUser'
-        db.create_table(u'portal_pendinguser', (
-            (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
-            ('first_name', self.gf('django.db.models.fields.TextField')()),
-            ('last_name', self.gf('django.db.models.fields.TextField')()),
-            ('email', self.gf('django.db.models.fields.EmailField')(max_length=75)),
-            ('password', self.gf('django.db.models.fields.TextField')()),
-            ('user_hrn', self.gf('django.db.models.fields.TextField')()),
-            ('public_key', self.gf('django.db.models.fields.TextField')()),
-            ('private_key', self.gf('django.db.models.fields.TextField')()),
-            ('authority_hrn', self.gf('django.db.models.fields.TextField')()),
-            ('login', self.gf('django.db.models.fields.TextField')()),
-            ('pi', self.gf('django.db.models.fields.TextField')()),
-            ('email_hash', self.gf('django.db.models.fields.TextField')()),
-            ('status', self.gf('django.db.models.fields.TextField')()),
-            ('created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)),
-        ))
-        db.send_create_signal(u'portal', ['PendingUser'])
-
-        # Adding model 'PendingAuthority'
-        db.create_table(u'portal_pendingauthority', (
-            (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
-            ('site_name', self.gf('django.db.models.fields.TextField')()),
-            ('site_authority', self.gf('django.db.models.fields.TextField')()),
-            ('site_abbreviated_name', self.gf('django.db.models.fields.TextField')()),
-            ('site_url', self.gf('django.db.models.fields.TextField')()),
-            ('site_latitude', self.gf('django.db.models.fields.TextField')()),
-            ('site_longitude', self.gf('django.db.models.fields.TextField')()),
-            ('address_line1', self.gf('django.db.models.fields.TextField')()),
-            ('address_line2', self.gf('django.db.models.fields.TextField')()),
-            ('address_line3', self.gf('django.db.models.fields.TextField')()),
-            ('address_city', self.gf('django.db.models.fields.TextField')()),
-            ('address_postalcode', self.gf('django.db.models.fields.TextField')()),
-            ('address_state', self.gf('django.db.models.fields.TextField')()),
-            ('address_country', self.gf('django.db.models.fields.TextField')()),
-            ('authority_hrn', self.gf('django.db.models.fields.TextField')()),
-            ('created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)),
-        ))
-        db.send_create_signal(u'portal', ['PendingAuthority'])
-
-        # Adding model 'PendingSlice'
-        db.create_table(u'portal_pendingslice', (
-            (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
-            ('slice_name', self.gf('django.db.models.fields.TextField')()),
-            ('user_hrn', self.gf('django.db.models.fields.TextField')()),
-            ('authority_hrn', self.gf('django.db.models.fields.TextField')(null=True)),
-            ('number_of_nodes', self.gf('django.db.models.fields.TextField')(default=0)),
-            ('type_of_nodes', self.gf('django.db.models.fields.TextField')(default='NA')),
-            ('purpose', self.gf('django.db.models.fields.TextField')(default='NA')),
-            ('created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)),
-        ))
-        db.send_create_signal(u'portal', ['PendingSlice'])
-
-        # Adding model 'PendingProject'
-        db.create_table(u'portal_pendingproject', (
-            (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
-            ('project_name', self.gf('django.db.models.fields.TextField')()),
-            ('user_hrn', self.gf('django.db.models.fields.TextField')()),
-            ('email', self.gf('django.db.models.fields.TextField')()),
-            ('authority_hrn', self.gf('django.db.models.fields.TextField')(null=True)),
-            ('purpose', self.gf('django.db.models.fields.TextField')(default='NA')),
-            ('created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)),
-        ))
-        db.send_create_signal(u'portal', ['PendingProject'])
-
-        # Adding model 'PendingJoin'
-        db.create_table(u'portal_pendingjoin', (
-            (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
-            ('user_hrn', self.gf('django.db.models.fields.TextField')()),
-            ('email', self.gf('django.db.models.fields.TextField')()),
-            ('project_name', self.gf('django.db.models.fields.TextField')(null=True)),
-            ('authority_hrn', self.gf('django.db.models.fields.TextField')()),
-            ('created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)),
-        ))
-        db.send_create_signal(u'portal', ['PendingJoin'])
-
-
-    def backwards(self, orm):
-        # Deleting model 'Institution'
-        db.delete_table(u'portal_institution')
-
-        # Deleting model 'PendingUser'
-        db.delete_table(u'portal_pendinguser')
-
-        # Deleting model 'PendingAuthority'
-        db.delete_table(u'portal_pendingauthority')
-
-        # Deleting model 'PendingSlice'
-        db.delete_table(u'portal_pendingslice')
-
-        # Deleting model 'PendingProject'
-        db.delete_table(u'portal_pendingproject')
-
-        # Deleting model 'PendingJoin'
-        db.delete_table(u'portal_pendingjoin')
-
-
-    models = {
-        u'portal.institution': {
-            'Meta': {'object_name': 'Institution'},
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'name': ('django.db.models.fields.TextField', [], {})
-        },
-        u'portal.pendingauthority': {
-            'Meta': {'object_name': 'PendingAuthority'},
-            'address_city': ('django.db.models.fields.TextField', [], {}),
-            'address_country': ('django.db.models.fields.TextField', [], {}),
-            'address_line1': ('django.db.models.fields.TextField', [], {}),
-            'address_line2': ('django.db.models.fields.TextField', [], {}),
-            'address_line3': ('django.db.models.fields.TextField', [], {}),
-            'address_postalcode': ('django.db.models.fields.TextField', [], {}),
-            'address_state': ('django.db.models.fields.TextField', [], {}),
-            'authority_hrn': ('django.db.models.fields.TextField', [], {}),
-            'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'site_abbreviated_name': ('django.db.models.fields.TextField', [], {}),
-            'site_authority': ('django.db.models.fields.TextField', [], {}),
-            'site_latitude': ('django.db.models.fields.TextField', [], {}),
-            'site_longitude': ('django.db.models.fields.TextField', [], {}),
-            'site_name': ('django.db.models.fields.TextField', [], {}),
-            'site_url': ('django.db.models.fields.TextField', [], {})
-        },
-        u'portal.pendingjoin': {
-            'Meta': {'object_name': 'PendingJoin'},
-            'authority_hrn': ('django.db.models.fields.TextField', [], {}),
-            'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
-            'email': ('django.db.models.fields.TextField', [], {}),
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'project_name': ('django.db.models.fields.TextField', [], {'null': 'True'}),
-            'user_hrn': ('django.db.models.fields.TextField', [], {})
-        },
-        u'portal.pendingproject': {
-            'Meta': {'object_name': 'PendingProject'},
-            'authority_hrn': ('django.db.models.fields.TextField', [], {'null': 'True'}),
-            'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
-            'email': ('django.db.models.fields.TextField', [], {}),
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'project_name': ('django.db.models.fields.TextField', [], {}),
-            'purpose': ('django.db.models.fields.TextField', [], {'default': "'NA'"}),
-            'user_hrn': ('django.db.models.fields.TextField', [], {})
-        },
-        u'portal.pendingslice': {
-            'Meta': {'object_name': 'PendingSlice'},
-            'authority_hrn': ('django.db.models.fields.TextField', [], {'null': 'True'}),
-            'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'number_of_nodes': ('django.db.models.fields.TextField', [], {'default': '0'}),
-            'purpose': ('django.db.models.fields.TextField', [], {'default': "'NA'"}),
-            'slice_name': ('django.db.models.fields.TextField', [], {}),
-            'type_of_nodes': ('django.db.models.fields.TextField', [], {'default': "'NA'"}),
-            'user_hrn': ('django.db.models.fields.TextField', [], {})
-        },
-        u'portal.pendinguser': {
-            'Meta': {'object_name': 'PendingUser'},
-            'authority_hrn': ('django.db.models.fields.TextField', [], {}),
-            'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
-            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75'}),
-            'email_hash': ('django.db.models.fields.TextField', [], {}),
-            'first_name': ('django.db.models.fields.TextField', [], {}),
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'last_name': ('django.db.models.fields.TextField', [], {}),
-            'login': ('django.db.models.fields.TextField', [], {}),
-            'password': ('django.db.models.fields.TextField', [], {}),
-            'pi': ('django.db.models.fields.TextField', [], {}),
-            'private_key': ('django.db.models.fields.TextField', [], {}),
-            'public_key': ('django.db.models.fields.TextField', [], {}),
-            'status': ('django.db.models.fields.TextField', [], {}),
-            'user_hrn': ('django.db.models.fields.TextField', [], {})
-        }
-    }
-
-    complete_apps = ['portal']
\ No newline at end of file