Merge branch 'onelab' of ssh://git.onelab.eu/git/myslice into onelab
authorLoic Baron <loic.baron@lip6.fr>
Mon, 9 Nov 2015 17:49:28 +0000 (18:49 +0100)
committerLoic Baron <loic.baron@lip6.fr>
Mon, 9 Nov 2015 17:49:28 +0000 (18:49 +0100)
Conflicts:
rest/sfa_api.py

30 files changed:
activity/__init__.py
manifoldapi/manifoldproxy.py
manifoldapi/static/js/manifold.js
myslice/configengine.py
myslice/urls.py
plugins/sladialog/static/js/sladialog.js
plugins/sladialog/templates/sladialog.html
portal/migrations/0001_initial.py
portal/migrations/0002_extend_slice.py [deleted file]
portal/migrations/0003_extend_slice.py [deleted file]
portal/migrations/0004_extend_user.py [deleted file]
portal/migrations/0005_extend_user.py [deleted file]
portal/migrations/0006_extend_slice.py [deleted file]
portal/migrations/0007_extend_slice_user.py [deleted file]
portal/migrations/0008_extend_user.py [deleted file]
portal/migrations/0009_initial.py [deleted file]
portal/migrations/0010_project.py [deleted file]
portal/migrations/0011_join.py [deleted file]
portal/projectrequestview.py
portal/slicerequestview.py
portal/slicetabcloud.py [new file with mode: 0644]
portal/templates/_footer.html
portal/templates/projectrequest_view.html
portal/templates/slice-tab-cloud.html [new file with mode: 0644]
portal/templates/slice-tab-info.html
portal/templates/slicerequest_view.html
rest/sfa_api.py
sla/slaclient/restclient.py
sla/slicetabsla.py
sla/urls.py

index b749672..be5779d 100644 (file)
@@ -15,7 +15,11 @@ import time
 import datetime
 from myslice.configengine import ConfigEngine
 from myslice.settings import logger
-
+import random
+import os
+import sqlite3 as lite
+import json
+import syslog
 
 config = ConfigEngine()
 if config.activity and config.activity.apikey :
@@ -52,7 +56,7 @@ def logWrite(request, action, message, objects = None):
         "client_ip" : ip,
         "host"      : request.get_host(),
         "referrer"  : request.META.get('HTTP_REFERER'),
-        "user"      : request.user,
+        "user"      : request.user.username,
         "action"    : action,
         "message"   : message,
         "apikey"    : apikey,
@@ -73,10 +77,31 @@ def logWrite(request, action, message, objects = None):
         result = urllib2.urlopen(server, urllib.urlencode(log))
         logger.info("===============>> activity: {} <{}> {}".format(action, request.user,message))
         content = result.read()
+
+        #checking for not sent data and sending it (50% probability)
+        if random.randint(0,100) < 50:
+            logCheck()
+
     except urllib2.URLError as e:
         logger.error("===============>> activity: connection to {} impossible, could not log action".format(server))
         logger.error(e.strerror)
 
+        dbfile = ''.join([os.path.dirname(os.path.abspath(__file__)), "/errors.db"])
+        conn = None
+        try:
+            conn = lite.connect(dbfile)
+            cur = conn.cursor()
+            cur.execute("""INSERT INTO logs(log) values('%s')""" % json.dumps(log))
+            conn.commit()
+        except lite.Error, e:
+            # this means that writing log into db also failed :(
+            # Last chance to preserve log is to send it to system syslog
+            # however there is no mechanism to pull it from this log - just manually.
+            logger.error('[activity] Error while inserting into sql db: %s' % str(e.args))
+            logger.error("[activity] data to send: '%s'" % json.dumps(log))
+        if conn:
+            conn.close()
+
 def log(request, action, message, objects = None):
     # Create a new thread in Daemon mode to send the log entry
     t = threading.Thread(target=logWrite, args=(request, action, message, objects))
@@ -95,3 +120,38 @@ def getClientIp(request):
 # sign the request with the secret key
 def sign(secret, message):
     return hmac.new(secret, msg=message, digestmod=hashlib.sha256).hexdigest()
+
+#
+# sending the logs cached in sqlite database
+
+def logCheck():
+    """Checking local database for logs adn sending it to monitoring server"""
+    dbfile = ''.join([os.path.dirname(os.path.abspath(__file__)), "/errors.db"])
+    conn = None
+
+    #trying to connect local db adn pull unsent logs
+    try:
+        conn = lite.connect(dbfile)
+        cur = conn.cursor()
+        cur.execute("SELECT rowid, log from logs")
+        notsent = cur.fetchall()
+        for row in notsent:
+            #trying to send unsent data from sqlite db
+            try :
+                urllib2.urlopen(config.activity.server, urllib.urlencode(json.loads(row[1])))
+                #delete those who were sent
+                cur.execute("""DELETE FROM logs where rowid = %s""" % row[0] )
+                conn.commit()
+            except urllib2.URLError as e:
+                # this is just to inform that DB is not working properly
+                logger.error('[activity] Error while sending stats')
+                logger.error(e.strerror)
+
+    except lite.Error, e:
+        #this need to be updated to store information via syslog
+        logger.error('[activity] Error while pulling from local sqlite3 db: %s' % str(e.args))
+        logger.error(e.strerror)
+    if conn:
+        conn.close()
+
+    return
index eba37bb..0f700bf 100644 (file)
@@ -10,7 +10,6 @@ from manifold.core.query        import Query
 from manifold.core.result_value import ResultValue
 from manifoldapi                import ManifoldAPI
 from manifoldresult             import ManifoldException
-from manifold.util.log          import Log
 
 # from unfold.sessioncache import SessionCache
 
index f8d299a..5b5e6af 100644 (file)
@@ -1703,6 +1703,8 @@ case TYPE_LIST_OF_VALUES:
 
         query = query_ext.query;
 
+        var testbeds_with_sla = localStorage.getItem("sla_testbeds").split(",");
+
         switch(query.object) {
 
             case 'resource':
@@ -1748,9 +1750,9 @@ case TYPE_LIST_OF_VALUES:
                     }
                 }
 
-                /*var urn_regexp = /\+(.*?)\+/;
+                var urn_regexp = /\+(.*?)\+/;
                 var testbed_urn = urn_regexp.exec(record.urn)[1];
-                var has_sla = $.inArray(testbed_urn, localStorage.getItem("sla_testbeds").split(",")) != -1;
+                var has_sla = $.inArray(testbed_urn, testbeds_with_sla) != -1;
 
                 if (has_sla) {
                     // var warnings = manifold.query_store.get_record_state(query.query_uuid, record_key, STATE_WARNINGS);
@@ -1761,7 +1763,7 @@ case TYPE_LIST_OF_VALUES:
                     } else {
                         delete warnings[CONSTRAINT_SLA];
                     }
-                }*/
+                }
 
                 manifold.query_store.set_record_state(query.query_uuid, record_key, STATE_WARNINGS, warnings);
                 // Signal the change to plugins (even if the constraint does not apply, so that the plugin can display a checkmark)
index 4b40cb2..c8ff197 100644 (file)
@@ -19,7 +19,25 @@ from myslice.settings import ROOT
 #api_key=theapikeyasprovidedbygoogle
 
 # use a singleton instead of staticmethods
-from manifold.util.singleton    import Singleton
+#-------------------------------------------------------------------------
+# Class Singleton
+#
+# Classes that inherit from Singleton can be instanciated only once 
+#-------------------------------------------------------------------------
+
+class Singleton(type):
+    def __init__(cls, name, bases, dic):
+        super(Singleton,cls).__init__(name,bases,dic)
+        cls.instance=None
+
+    def __call__(cls, *args, **kw):
+        if cls.instance is None:
+            cls.instance=super(Singleton,cls).__call__(*args,**kw)
+        return cls.instance
+
+
+# See also
+# http://stackoverflow.com/questions/6760685/creating-a-singleton-in-python
 
 class ConfigEngine(object):
     __metaclass__ = Singleton
index 61f779f..b2e88bb 100644 (file)
@@ -46,6 +46,7 @@ import portal.sliceresourceview
 import portal.resources
 
 import portal.slicetabexperiment
+import portal.slicetabcloud
 import portal.slicetabinfo
 import portal.slicetabtestbeds
 import portal.slicetabusers
@@ -116,6 +117,7 @@ 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'^cloud/(?P<slicename>[^/]+)/?$', portal.slicetabcloud.CloudView.as_view()),
     
     
     url(r'^about/?$', portal.about.AboutView.as_view(), name='about'),
index 2773df0..01eb0af 100644 (file)
@@ -1,13 +1,10 @@
 /**
- * MyPlugin:    demonstration plugin
- * Version:     0.1
- * Description: Template for writing new plugins and illustrating the different
- *              possibilities of the plugin API.
- *              This file is part of the Manifold project 
+ * SlaDialog
+ * Description: Plugin to allow SLA acceptance and creation to MySlice portal
+ *              in Fed4FIRE
  * Requires:    js/plugin.js
- * URL:         http://www.myslice.info
- * Author:      Jordan Augé <jordan.auge@lip6.fr>
- * Copyright:   Copyright 2012-2013 UPMC Sorbonne Universités
+ * Author:      Javier García Lloreda <javier.garcial.external@atos.net>
+ * Copyright:   Copyright Atos Spain S.A.
  * License:     GPLv3
  */
 
         accepted_slas: {},
         queries: [],
 
-        /** XXX to check
-         * @brief Plugin constructor
-         * @param options : an associative array of setting values
-         * @param element : 
-         * @return : a jQuery collection of objects on which the plugin is
-         *     applied, which allows to maintain chainability of calls
-         */
         init: function(options, element) {
-           // for debugging tools
-           this.classname="SlaDialog";
-            // Call the parent constructor, see FAQ when forgotten
+               this.classname = "SlaDialog";
             this._super(options, element);
 
             /* Member variables */
             /* Plugin events */
 
             /* Setup query and record handlers */
-
-            // Explain this will allow query events to be handled
-            // What happens when we don't define some events ?
-            // Some can be less efficient
             this.listen_query(options.query_uuid);
             
             /* GUI setup and event binding */
-            // call function
-            this.button_binding();
-
             // Get testbeds with sla and store them in localStorage
-            //this.get_testbeds_with_sla();
+            this.get_testbeds_with_sla();
 
+            // call function
+            //this.button_binding();
         },
 
         get_testbeds_with_sla: function () {
+            var self = this;
             return $.get('/sla/testbeds/', function(data) {
                 if (typeof(Storage) !== "undefined") {
                     if (!localStorage.getItem("sla_testbeds")) {
                         localStorage.setItem("sla_testbeds", testbeds);
                     }
                 }
+            }).done(function(data) {
+                self.get_sla_templates(data);
             });
         },
 
-        find_row: function(key)
-        {
-            // key in third position, column id = 2
-            var KEY_POS = 2;
-
-            var cols = $.grep(this.table.fnSettings().aoData, function(col) {
-                return (col._aData[KEY_POS] == key);
-            } );
-
-            if (cols.length == 0)
-                return null;
-            if (cols.length > 1)
-                throw "Too many same-key rows in ResourceSelected plugin";
+        get_sla_templates: function (testbeds) {
+            var self = this;
 
-            return cols[0];
+            testbeds.forEach(function(testbed, index, array) {
+
+                if(testbed=="omf:netmode") { // TODO: Remove
+
+                    $.ajax('/sla/agreements/templates/' + testbed)
+                     .always(function(data) {
+                        $(".modal-body #sla_template").html(data.responseText.replace(/<|>/g, ""));
+
+                        var content =
+                        "<div id=" + testbed.replace(/\.|:/g, "-") + " class='row' data-urns='[]' style='display: none'>" +
+                            "<div class='col-md-6'>" +
+                                "<p>Testbed <span class='provider'>" + testbed + "</span> offers the following SLA for its resources</p>" +
+                            "</div>" +
+                            "<div class='col-md-1'>" +
+                                "<button class='sla-info-button btn btn-default' data-toggle='modal' data-target='#sla_template_modal'>" +
+                                "<span class='glyphicon glyphicon-info-sign'></span>" +
+                                    "Details" +
+                                "</button>" +
+                            "</div>" +
+                            "<div class='col-md-1'>" +
+                                "<button class='sla-accept-button btn btn-default' data-complete-text='Accepted' autocomplete='off'>" +
+                                "<span class='glyphicon glyphicon-ok'></span>" +
+                                    "Accept" +
+                                "</button>" +
+                            "</div>" +
+                        "</div>";
+
+                        $("#sla_offers").append(content);
+
+                        self.button_binding();
+                    });
+                }
+            });
         },
 
         check_template_status: function() {
@@ -88,8 +95,6 @@
         },
 
         /* PLUGIN EVENTS */
-        // on_show like in querytable
-
 
         /* GUI EVENTS */
 
 
                 if (is_ok) {
                     // remove warnings
-                    // var warnings = manifold.query_store.get_record_state(resource_query.query_uuid, resource_key, STATE_WARNINGS);
+                    $('#' + id).data("urns").forEach(function (urn, index, array) {
+                        data = {
+                            state: STATE_SET,
+                            key  : "resource",
+                            op   : STATE_SET_REMOVE,
+                            value: urn
+                        }
+
+                        manifold.raise_event(self.query_uuid, STATUS_REMOVE_WARNING, data);
+                    });
                 }
             });
 
 
                 var data = {
                     "SLIVER_INFO_AGGREGATE_URN": record.resource[0].component_manager_id,
-                    "SLIVER_INFO_EXPIRATION": record.lease[0].end_time,     // FIXME: only working with leases
+                    "SLIVER_INFO_EXPIRATION": record.lease[0].end_time,  // FIXME: only working with leases
                     "SLIVER_INFO_SLICE_URN": record.slice_urn,
                     "SLIVER_INFO_CREATOR_URN": record.users[0],
                     "SLIVER_INFO_URN": urns,
 //            });
         },
 
-        // a function to bind events here: click change
-        // how to raise manifold events
-        set_state: function(data, username)
-        {
-            
-        },
-
-        post_agreement: function()
-        {
-            console.log(this.options.user);
-        },
-
-        /* GUI MANIPULATION */
-
-        // We advise you to write function to change behaviour of the GUI
-        // Will use naming helpers to access content _inside_ the plugin
-        // always refer to these functions in the remaining of the code
-
-        show_hide_button: function() 
-        {
-            // this.id, this.el, this.cl, this.elts
-            // same output as a jquery selector with some guarantees
-        },
-
-        /* TEMPLATES */
-
-        // see in the html template
-        // How to load a template, use of mustache
-
-        /* QUERY HANDLERS */
-
-        // How to make sure the plugin is not desynchronized
-        // He should manifest its interest in filters, fields or records
-        // functions triggered only if the proper listen is done
-
-        // no prefix
-
         on_filter_added: function(filter)
         {
 
         on_field_state_changed: function(data)
         {
             var self = this;
+            self.query_uuid = self.options.query_uuid;
+
+            var testbeds = localStorage.getItem("sla_testbeds").split(",");
+            var urn_regexp = /\+(.*?)\+/;
             // this.set_state(result, this.options.username);
 
              switch(data.state) {
                         case STATE_SET_IN_PENDING:
                             if (typeof(data.value) == 'string') {
                                 // data.value = urn
-                                this._supports_sla(data.value)
-                                    .done( function(testbeds) {
-                                        var urn_regexp = /\+(.*?)\+/;
-                                        var urn = urn_regexp.exec(data.value)[1];
-                                        var pos = $.inArray(urn, testbeds);
-                                        if ( pos != -1) {
-                                            var id_ref = testbeds[pos].replace(/\.|:/g, "-");
-                                            $("#" + id_ref).data("urns").push(data.value);
-                                            $("#" + id_ref).show();
-                                            self.accepted_slas[id_ref] = false;
-                                            //$( "#sla_offers_list" ).append(
-                                            //    $("<li>").text("Testbed " + testbeds[pos] + " offers SLA for its resources")
-                                            //);
-                                        }
-                                    });
+                                var urn = urn_regexp.exec(data.value)[1];
+                                var pos = $.inArray(urn, testbeds);
+                                if ( pos != -1) {
+                                    var id_ref = testbeds[pos].replace(/\.|:/g, "-");
+                                    $("#" + id_ref).data("urns").push(data.value);
+                                    $("#" + id_ref).show();
+                                    self.accepted_slas[id_ref] = false;
+                                    //$( "#sla_offers_list" ).append(
+                                    //    $("<li>").text("Testbed " + testbeds[pos] + " offers SLA for its resources")
+                                    //);
+                                }
                             }
                             break;
                         case STATE_SET_OUT:
                             // data.value = urn
                             if (typeof(data.value) == 'string') {
                                 // data.value = urn
-                                this._supports_sla(data.value)
-                                    .done( function(testbeds) {
-                                        var urn_regexp = /\+(.*?)\+/;
-                                        var urn = urn_regexp.exec(data.value)[1];
-                                        var pos = $.inArray(urn, testbeds);
-                                        if ( pos != -1) {
-                                            var id_ref = testbeds[pos].replace(/\.|:/g, "-");
-                                            var array = $("#" + id_ref).data("urns");
-                                            array.splice(array.indexOf(data.value), 1);
-
-                                            if ($("#" + id_ref).data("urns").length == 0) {
-                                                $("#" + id_ref).hide();
-                                                delete self.accepted_slas[id_ref];
-                                                $(".sla-accept-button").button("reset");
-                                                $(".sla-accept-button").prop("disabled", false);
-                                            }
-                                            //$( "#sla_offers_list" ).append(
-                                            //    $("<li>").text("Testbed " + testbeds[pos] + " offers SLA for its resources")
-                                            //);
-                                        }
-                                    });
+                                var urn = urn_regexp.exec(data.value)[1];
+                                var pos = $.inArray(urn, testbeds);
+                                if ( pos != -1) {
+                                    var id_ref = testbeds[pos].replace(/\.|:/g, "-");
+                                    var array = $("#" + id_ref).data("urns");
+                                    array.splice(array.indexOf(data.value), 1);
+
+                                    if ($("#" + id_ref).data("urns").length == 0) {
+                                        $("#" + id_ref).hide();
+                                        delete self.accepted_slas[id_ref];
+                                        $(".sla-accept-button").button("reset");
+                                        $(".sla-accept-button").prop("disabled", false);
+                                    }
+                                    //$( "#sla_offers_list" ).append(
+                                    //    $("<li>").text("Testbed " + testbeds[pos] + " offers SLA for its resources")
+                                    //);
+                                }
                             }
                             break;
                     }
              }
         }, 
 
-        // ... be sure to list all events here
-
         /* RECORD HANDLERS */
         on_all_new_record: function(record)
         {
         },
 
         /* INTERNAL FUNCTIONS */
-        _dummy: function() {
-            // only convention, not strictly enforced at the moment
-        },
 
         _supports_sla: function(resource_urn) {
             return $.ajax("/sla/testbeds/");
         },
 
-
-
         _getUUID: function() {
             return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
                 var r = Math.random()*16|0, v = c === 'x' ? r : (r&0x3|0x8);
     /* Plugin registration */
     $.plugin('SlaDialog', SlaDialog);
 
-    // TODO Here use cases for instanciating plugins in different ways like in the pastie.
-
 })(jQuery);
index b1a9ab2..8886ae3 100644 (file)
@@ -8,7 +8,7 @@
                 </div>
                 <div class="modal-body">
                     <p>Testbed offers:</p>
-                    <p>99% availability for 99% of the selected resources</p>
+                    <p id="sla_template"></p>
                 </div>
                 <div class="modal-footer">
                     <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
             <strong>Accepted!</strong> The SLA has been accepted.
         </div>
     </div>
-    <div id="sla_offers" class="container">
-        <div id="fuseco-fokus-fraunhofer-de" class="row" data-urns="[]" style="display: none">
-            <div class="col-md-6">
-                <p>Testbed <span class="provider">fuseco.fokus.fraunhofer.de</span> offers the following SLA for its resources</p>
-            </div>
-            <div class="col-md-1">
-                <button class="sla-info-button btn btn-default" data-toggle="modal" data-target="#sla_template_modal">
-                    <span class="glyphicon glyphicon-info-sign"></span>
-                    Details
-                </button>
-            </div>
-            <div class="col-md-1">
-                <button class="sla-accept-button btn btn-default" data-complete-text="Accepted" autocomplete="off">
-                    <span class="glyphicon glyphicon-ok"></span>
-                    Accept
-                </button>
-            </div>
-        </div>
-        <div id="omf-netmode" class="row" data-urns="[]" style="display: none">
-            <div class="col-md-6">
-                <p>Testbed <span class="provider">omf:netmode</span> offers the following SLA for its resources</p>
-            </div>
-            <div class="col-md-1">
-                <button class="sla-info-button btn btn-default" data-toggle="modal" data-target="#sla_template_modal">
-                    <span class="glyphicon glyphicon-info-sign"></span>
-                    Details
-                </button>
-            </div>
-            <div class="col-md-1">
-                <button class="sla-accept-button btn btn-default" data-complete-text="Accepted" autocomplete="off">
-                    <span class="glyphicon glyphicon-ok"></span>
-                    Accept
-                </button>
-            </div>
-        </div>
-        <div id="wilab2-ilabt-iminds-be" class="row" data-urns="[]" style="display: none">
-            <div class="col-md-6">
-                <p>Testbed <span class="provider">wilab2.ilabt.iminds.be</span> offers the following SLA for its resources</p>
-            </div>
-            <div class="col-md-1">
-                <button class="sla-info-button btn btn-default" data-toggle="modal" data-target="#sla_template_modal">
-                    <span class="glyphicon glyphicon-info-sign"></span>
-                    Details
-                </button>
-            </div>
-            <div class="col-md-1">
-                <button class="sla-accept-button btn btn-default" data-complete-text="Accepted" autocomplete="off">
-                    <span class="glyphicon glyphicon-ok"></span>
-                    Accept
-                </button>
-            </div>
-        </div>
-        <div id="wall2-ilabt-iminds-be" class="row" data-urns="[]" style="display: none">
-            <div class="col-md-6">
-                <p>Testbed <span class="provider">wall2.ilabt.iminds.be</span> offers the following SLA for its resources</p>
-            </div>
-            <div class="col-md-1">
-                <button class="sla-info-button btn btn-default" data-toggle="modal" data-target="#sla_template_modal">
-                    <span class="glyphicon glyphicon-info-sign"></span>
-                    Details
-                </button>
-            </div>
-            <div class="col-md-1">
-                <button class="sla-accept-button btn btn-default" data-complete-text="Accepted" autocomplete="off">
-                    <span class="glyphicon glyphicon-ok"></span>
-                    Accept
-                </button>
-            </div>
-        </div>
-    </div>
+    <div id="sla_offers" class="container"></div>
 </div>
\ No newline at end of file
index 2c1fd6d..9b58fae 100644 (file)
@@ -22,18 +22,75 @@ class Migration(SchemaMigration):
             ('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')()),
-            ('keypair', 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'
@@ -42,9 +99,18 @@ class Migration(SchemaMigration):
         # 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': {
@@ -52,21 +118,72 @@ class Migration(SchemaMigration):
             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'}),
-            'slice_name': ('django.db.models.fields.TextField', [], {})
+            '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'}),
-            'keypair': ('django.db.models.fields.TextField', [], {}),
             'last_name': ('django.db.models.fields.TextField', [], {}),
-            'password': ('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']
+    complete_apps = ['portal']
\ No newline at end of file
diff --git a/portal/migrations/0002_extend_slice.py b/portal/migrations/0002_extend_slice.py
deleted file mode 100644 (file)
index c6de6c5..0000000
+++ /dev/null
@@ -1,46 +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 field 'PendingSlice.authority_hrn'
-        db.add_column(u'portal_pendingslice', 'authority_hrn',
-                      self.gf('django.db.models.fields.TextField')(null=True),
-                      keep_default=False)
-
-
-    def backwards(self, orm):
-        # Deleting field 'PendingSlice.authority_hrn'
-        db.delete_column(u'portal_pendingslice', 'authority_hrn')
-
-
-    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.pendingslice': {
-            'Meta': {'object_name': 'PendingSlice'},
-            'authority_hrn': ('django.db.models.fields.TextField', [], {'null': 'True'}),
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'slice_name': ('django.db.models.fields.TextField', [], {})
-        },
-        u'portal.pendinguser': {
-            'Meta': {'object_name': 'PendingUser'},
-            'authority_hrn': ('django.db.models.fields.TextField', [], {}),
-            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75'}),
-            'first_name': ('django.db.models.fields.TextField', [], {}),
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'keypair': ('django.db.models.fields.TextField', [], {}),
-            'last_name': ('django.db.models.fields.TextField', [], {}),
-            'password': ('django.db.models.fields.TextField', [], {})
-        }
-    }
-
-    complete_apps = ['portal']
diff --git a/portal/migrations/0003_extend_slice.py b/portal/migrations/0003_extend_slice.py
deleted file mode 100644 (file)
index 10fe0fa..0000000
+++ /dev/null
@@ -1,65 +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 field 'PendingSlice.number_of_nodes'
-        db.add_column(u'portal_pendingslice', 'number_of_nodes',
-                      self.gf('django.db.models.fields.TextField')(default=0),
-                      keep_default=False)
-
-        # Adding field 'PendingSlice.type_of_nodes'
-        db.add_column(u'portal_pendingslice', 'type_of_nodes',
-                      self.gf('django.db.models.fields.TextField')(default='NA'),
-                      keep_default=False)
-
-        # Adding field 'PendingSlice.purpose'
-        db.add_column(u'portal_pendingslice', 'purpose',
-                      self.gf('django.db.models.fields.TextField')(default='NA'),
-                      keep_default=False)
-
-
-    def backwards(self, orm):
-        # Deleting field 'PendingSlice.number_of_nodes'
-        db.delete_column(u'portal_pendingslice', 'number_of_nodes')
-
-        # Deleting field 'PendingSlice.type_of_nodes'
-        db.delete_column(u'portal_pendingslice', 'type_of_nodes')
-
-        # Deleting field 'PendingSlice.purpose'
-        db.delete_column(u'portal_pendingslice', 'purpose')
-
-
-    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.pendingslice': {
-            'Meta': {'object_name': 'PendingSlice'},
-            'authority_hrn': ('django.db.models.fields.TextField', [], {'null': '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'"})
-        },
-        u'portal.pendinguser': {
-            'Meta': {'object_name': 'PendingUser'},
-            'authority_hrn': ('django.db.models.fields.TextField', [], {}),
-            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75'}),
-            'first_name': ('django.db.models.fields.TextField', [], {}),
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'keypair': ('django.db.models.fields.TextField', [], {}),
-            'last_name': ('django.db.models.fields.TextField', [], {}),
-            'password': ('django.db.models.fields.TextField', [], {})
-        }
-    }
-
-    complete_apps = ['portal']
diff --git a/portal/migrations/0004_extend_user.py b/portal/migrations/0004_extend_user.py
deleted file mode 100644 (file)
index 50be2b9..0000000
+++ /dev/null
@@ -1,50 +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 field 'PendingUser.login'
-        db.add_column(u'portal_pendinguser', 'login',
-                      self.gf('django.db.models.fields.TextField')(default='dummy'),
-                      keep_default=False)
-
-
-    def backwards(self, orm):
-        # Deleting field 'PendingUser.login'
-        db.delete_column(u'portal_pendinguser', 'login')
-
-
-    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.pendingslice': {
-            'Meta': {'object_name': 'PendingSlice'},
-            'authority_hrn': ('django.db.models.fields.TextField', [], {'null': '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'"})
-        },
-        u'portal.pendinguser': {
-            'Meta': {'object_name': 'PendingUser'},
-            'authority_hrn': ('django.db.models.fields.TextField', [], {}),
-            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75'}),
-            'first_name': ('django.db.models.fields.TextField', [], {}),
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'keypair': ('django.db.models.fields.TextField', [], {}),
-            'last_name': ('django.db.models.fields.TextField', [], {}),
-            'login': ('django.db.models.fields.TextField', [], {}),
-            'password': ('django.db.models.fields.TextField', [], {})
-        }
-    }
-
-    complete_apps = ['portal']
\ No newline at end of file
diff --git a/portal/migrations/0005_extend_user.py b/portal/migrations/0005_extend_user.py
deleted file mode 100644 (file)
index c3725b1..0000000
+++ /dev/null
@@ -1,51 +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 field 'PendingUser.created'
-        db.add_column(u'portal_pendinguser', 'created',
-                      self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, default=datetime.datetime(2013, 10, 25, 0, 0), blank=True),
-                      keep_default=False)
-
-
-    def backwards(self, orm):
-        # Deleting field 'PendingUser.created'
-        db.delete_column(u'portal_pendinguser', 'created')
-
-
-    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.pendingslice': {
-            'Meta': {'object_name': 'PendingSlice'},
-            'authority_hrn': ('django.db.models.fields.TextField', [], {'null': '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'"})
-        },
-        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'}),
-            'first_name': ('django.db.models.fields.TextField', [], {}),
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'keypair': ('django.db.models.fields.TextField', [], {}),
-            'last_name': ('django.db.models.fields.TextField', [], {}),
-            'login': ('django.db.models.fields.TextField', [], {}),
-            'password': ('django.db.models.fields.TextField', [], {})
-        }
-    }
-
-    complete_apps = ['portal']
\ No newline at end of file
diff --git a/portal/migrations/0006_extend_slice.py b/portal/migrations/0006_extend_slice.py
deleted file mode 100644 (file)
index b2c593d..0000000
+++ /dev/null
@@ -1,52 +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 field 'PendingSlice.created'
-        db.add_column(u'portal_pendingslice', 'created',
-                      self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, default=datetime.datetime(2013, 10, 25, 0, 0), blank=True),
-                      keep_default=False)
-
-
-    def backwards(self, orm):
-        # Deleting field 'PendingSlice.created'
-        db.delete_column(u'portal_pendingslice', 'created')
-
-
-    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.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'"})
-        },
-        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'}),
-            'first_name': ('django.db.models.fields.TextField', [], {}),
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'keypair': ('django.db.models.fields.TextField', [], {}),
-            'last_name': ('django.db.models.fields.TextField', [], {}),
-            'login': ('django.db.models.fields.TextField', [], {}),
-            'password': ('django.db.models.fields.TextField', [], {})
-        }
-    }
-
-    complete_apps = ['portal']
\ No newline at end of file
diff --git a/portal/migrations/0007_extend_slice_user.py b/portal/migrations/0007_extend_slice_user.py
deleted file mode 100644 (file)
index b065781..0000000
+++ /dev/null
@@ -1,105 +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 '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 field 'PendingSlice.user_hrn'
-        db.add_column(u'portal_pendingslice', 'user_hrn',
-                      self.gf('django.db.models.fields.TextField')(default=''),
-                      keep_default=False)
-
-        # Adding field 'PendingUser.pi'
-        db.add_column(u'portal_pendinguser', 'pi',
-                      self.gf('django.db.models.fields.TextField')(default=''),
-                      keep_default=False)
-
-
-    def backwards(self, orm):
-        # Deleting model 'PendingAuthority'
-        db.delete_table(u'portal_pendingauthority')
-
-        # Deleting field 'PendingSlice.user_hrn'
-        db.delete_column(u'portal_pendingslice', 'user_hrn')
-
-        # Deleting field 'PendingUser.pi'
-        db.delete_column(u'portal_pendinguser', 'pi')
-
-
-    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.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'}),
-            'first_name': ('django.db.models.fields.TextField', [], {}),
-            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
-            'keypair': ('django.db.models.fields.TextField', [], {}),
-            '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', [], {})
-        }
-    }
-
-    complete_apps = ['portal']
\ No newline at end of file
diff --git a/portal/migrations/0008_extend_user.py b/portal/migrations/0008_extend_user.py
deleted file mode 100644 (file)
index 579584e..0000000
+++ /dev/null
@@ -1,99 +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):
-        # Deleting field 'PendingUser.keypair'
-        db.delete_column(u'portal_pendinguser', 'keypair')
-
-        # Adding field 'PendingUser.user_hrn'
-        db.add_column(u'portal_pendinguser', 'user_hrn',
-                      self.gf('django.db.models.fields.TextField')(default=''),
-                      keep_default=False)
-
-        # Adding field 'PendingUser.public_key'
-        db.add_column(u'portal_pendinguser', 'public_key',
-                      self.gf('django.db.models.fields.TextField')(default=''),
-                      keep_default=False)
-
-        # Adding field 'PendingUser.private_key'
-        db.add_column(u'portal_pendinguser', 'private_key',
-                      self.gf('django.db.models.fields.TextField')(default=''),
-                      keep_default=False)
-
-
-    def backwards(self, orm):
-        # Adding field 'PendingUser.keypair'
-        db.add_column(u'portal_pendinguser', 'keypair',
-                      self.gf('django.db.models.fields.TextField')(default=''),
-                      keep_default=False)
-
-        # Deleting field 'PendingUser.user_hrn'
-        db.delete_column(u'portal_pendinguser', 'user_hrn')
-
-        # Deleting field 'PendingUser.public_key'
-        db.delete_column(u'portal_pendinguser', 'public_key')
-
-        # Deleting field 'PendingUser.private_key'
-        db.delete_column(u'portal_pendinguser', 'private_key')
-
-
-    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.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'}),
-            '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', [], {}),
-            'user_hrn': ('django.db.models.fields.TextField', [], {})
-        }
-    }
-
-    complete_apps = ['portal']
\ No newline at end of file
diff --git a/portal/migrations/0009_initial.py b/portal/migrations/0009_initial.py
deleted file mode 100644 (file)
index 4e7e20a..0000000
+++ /dev/null
@@ -1,141 +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'])
-
-
-    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')
-
-
-    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.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
diff --git a/portal/migrations/0010_project.py b/portal/migrations/0010_project.py
deleted file mode 100644 (file)
index 7046204..0000000
+++ /dev/null
@@ -1,92 +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 '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')()),
-            ('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'])
-
-
-    def backwards(self, orm):
-        # Deleting model 'PendingProject'
-        db.delete_table(u'portal_pendingproject')
-
-
-    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.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'}),
-            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
diff --git a/portal/migrations/0011_join.py b/portal/migrations/0011_join.py
deleted file mode 100644 (file)
index f403289..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-# -*- coding: utf-8 -*-
-import datetime
-from south.db import db
-from south.v2 import DataMigration
-from django.db import models
-
-class Migration(DataMigration):
-
-    def forwards(self, orm):
-        "Write your forwards methods here."
-        # Note: Remember to use orm['appname.ModelName'] rather than "from appname.models..."
-
-    def backwards(self, orm):
-        "Write your backwards methods here."
-
-    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']
-    symmetrical = True
index 1f6e921..2757b94 100644 (file)
@@ -106,6 +106,7 @@ class ProjectRequestView(LoginRequiredAutoLogoutView, ThemeView):
                     'authority_hrn'     : wsgi_request.POST.get('authority_name', ''),
                     'project_name'      : project_name,
                     'purpose'           : wsgi_request.POST.get('purpose', ''),
+                    'url'               : wsgi_request.POST.get('url', ''),
                 }
 
                 # for new projects max project_name length is 10
index a2b0dd0..9ccaf76 100644 (file)
@@ -39,8 +39,8 @@ class SliceRequestView (LoginRequiredAutoLogoutView, ThemeView):
 
         errors = []
         slice_name =''
-        purpose=''
-        url=''
+        #purpose=''
+        #url=''
         authority_hrn = None
         authority_name = None
         # Retrieve the list of authorities
@@ -138,8 +138,8 @@ class SliceRequestView (LoginRequiredAutoLogoutView, ThemeView):
                 'authority_hrn'     : authority_hrn,
                 'organization'      : request.POST.get('org_name', ''),
                 'slice_name'        : slice_name,
-                'url'               : request.POST.get('url', ''),
-                'purpose'           : request.POST.get('purpose', ''),
+                #'url'               : request.POST.get('url', ''),
+                #'purpose'           : request.POST.get('purpose', ''),
                 'current_site'      : current_site
             }
 
@@ -174,11 +174,11 @@ class SliceRequestView (LoginRequiredAutoLogoutView, ThemeView):
 
 
     
-            purpose = slice_request['purpose']
-            if purpose is None or purpose == '':
-                errors.append('Experiment purpose is mandatory')
+           # purpose = slice_request['purpose']
+           # if purpose is None or purpose == '':
+           #     errors.append('Experiment purpose is mandatory')
 
-            url = slice_request['url']
+            #url = slice_request['url']
 
             if not errors:
                 if is_pi(request, user_hrn, authority_hrn):
@@ -203,10 +203,10 @@ class SliceRequestView (LoginRequiredAutoLogoutView, ThemeView):
             'topmenu_items': topmenu_items_live('Request a slice', page),
             'errors': errors,
             'slice_name': slice_name,
-            'purpose': purpose,
+            #'purpose': purpose,
             'email': user_email,
             'user_hrn': user_hrn,
-            'url': url,
+            #'url': url,
             'pi': pi,
             'authority_name': authority_name,        
             'authority_hrn': user_authority,        
diff --git a/portal/slicetabcloud.py b/portal/slicetabcloud.py
new file mode 100644 (file)
index 0000000..ce1dc31
--- /dev/null
@@ -0,0 +1,86 @@
+# this somehow is not used anymore - should it not be ?
+from django.core.context_processors import csrf
+from django.http import HttpResponseRedirect
+from django.contrib.auth import authenticate, login, logout
+from django.template import RequestContext
+from django.shortcuts import render_to_response
+from django.shortcuts import render
+
+from unfold.loginrequired import LoginRequiredView
+
+from manifold.core.query        import Query
+from manifoldapi.manifoldapi    import execute_query
+from manifoldapi.manifoldresult import ManifoldResult
+from ui.topmenu import topmenu_items, the_user
+from myslice.configengine import ConfigEngine
+
+from myslice.theme import ThemeView
+from myslice.configengine import ConfigEngine
+from myslice.settings import logger
+
+from sfa.planetlab.plxrn import hash_loginbase
+
+import urllib2,json
+
+class CloudView (LoginRequiredView, ThemeView):
+    # parent View is portal/sliceview.py
+
+    def get_platforms (self, request):
+        username = self.request.user    
+        
+        pf_query = Query().get('local:platform').filter_by('disabled', '==', '0').filter_by('gateway_type', '==', 'sfa').select('platform')
+        res_platforms = execute_query(request, pf_query)
+        platforms = [p['platform'] for p in res_platforms]
+        return platforms
+
+
+    template_name = 'slice-tab-cloud.html'
+    def post (self, request, slicename):
+        logger.debug("---------------- POST CloudView ------------------")
+        logger.debug(request.POST)
+
+        username = self.request.user    
+        platforms = self.get_platforms(request)
+        cloud_platforms = ["onelab-cloud"]
+        len_platforms = len(platforms)
+
+        #if 'action' in request.POST:
+        #    if request.POST['action'] == 'add':
+
+        #    elif request.POST['action'] == 'delete':
+        #        for key,val in request.POST:
+        #            if key.endswith('_vm'):
+        #                request.POST['platform']
+        #                
+        #    elif request.POST['action'] == 'reserve':
+        #    
+        #    else:
+        #        log.error("action %s not supported" % request.POST['action'])
+
+        env = { 'theme' : self.theme,
+                'slicename':slicename,
+                'platforms':platforms,
+                'cloud_platforms':cloud_platforms,
+                'len_platforms': len_platforms,
+                'post_values': request.POST,
+                'request':self.request,
+              }
+        return render_to_response(self.template, env, context_instance=RequestContext(request))
+
+
+    def get (self, request, slicename, state=None):
+  
+        username = self.request.user    
+        platforms = self.get_platforms(request)
+        cloud_platforms = ["onelab-cloud"]
+        len_platforms = len(platforms)
+
+        env = { 'theme' : self.theme,
+                'slicename':slicename, 
+                'platforms':platforms,
+                'cloud_platforms':cloud_platforms,
+                'len_platforms': len_platforms,
+                'request':self.request,
+              }
+        return render_to_response(self.template, env, context_instance=RequestContext(request))
+
index 6bf5bb8..be7462e 100644 (file)
@@ -12,7 +12,7 @@
             Copyrights &copy; 2015 UPMC Sorbonne Universit&eacute;s. All rights reserved.
         </div>
         <div class="col-md-3 copy">
-        powerd by &nbsp;<a href="http://myslice.info" target="_blank"><img src="//myslice.info/images/logo.png" style="width:50px;"></a>&nbsp;&nbsp;
+        powered by &nbsp;<a href="http://myslice.info" target="_blank"><img src="//myslice.info/images/logo.png" style="width:50px;"></a>&nbsp;&nbsp;
         <a href="/portal/release_notes" id="portal_version"></a>
         </div>
     </div>
index 8558228..aabda75 100644 (file)
                         {% endif %}
                         </select>
                     </div>
-                  
+                    <div class="form-group">
+                        <label>
+                            Provide an URL for your project (not required)
+                        </label>
+                        <input type="text" class="form-control" name="url" id="url" style="width:100%" placeholder="Experiment URL (if one exists)"
+                        title="Please provide the url of your project" value="{{url}}">
+                    </div> 
                     <label>
                         Please provide a description of the purpose for your project
                     </label>
diff --git a/portal/templates/slice-tab-cloud.html b/portal/templates/slice-tab-cloud.html
new file mode 100644 (file)
index 0000000..436af69
--- /dev/null
@@ -0,0 +1,484 @@
+{% extends "layout_wide.html" %}
+
+{% block head %}
+<style>
+.disabled {
+    z-index: 1000;
+    background-color: #999999;
+    opacity: 0.3;
+    pointer-events: none;
+}
+</style>
+<script type="text/javascript">
+
+var global_list = {};
+var data = Array(); 
+var ad_rspec = Array(); 
+var request_rspec = Array(); 
+var manifest_rspec = Array(); 
+var deleted_nodes = {}; 
+var added_nodes = {}; 
+
+var len_platforms = {{len_platforms}};
+
+/* render_flavor & render_image */
+function render_option(obj){
+    var option = document.createElement("option");
+    option.text = obj["@name"];
+    option.value = obj["@name"];
+    return option;
+}
+function render_description(platform, obj, type){
+    if($('#'+platform+'_'+type).length==0){
+        $('#'+platform+'_add').append("<div id='"+platform+"_"+type+"'>");
+    }
+    var d = platform+'_'+type+'_'+obj['@name'];
+    d = d.replace(/ /g, '');
+    id = d.replace( /(:|\.|\[|\])/g, "\\$1" );
+    if($('#'+id).length==0){
+        $('#'+platform+'_'+type).append("<div id='"+d+"' class='alert-success col-md-5' style='margin-top:10px;display:none;border-style:solid;border-color:#f1f1f1;border-width:2px;'></div>");
+    }
+    if($('#'+id+' div').length==0){
+        jQuery.each(obj, function(key,val){
+            if (key != 'openstack:image'){
+                $('#'+id).append("<div>"+key.replace('@','')+": "+val+"</div>");
+            }
+        });
+    }
+}
+function toogle_div(platform, value, type){
+    $("#"+platform+"_add").show();
+    // show the add button only if image is selected
+    if($("#"+platform+"_selectImage").val()!=null && $("#"+platform+"_selectImage").val()!=0 && value!=0){
+        $("#"+platform+"_add_button").show();
+    }else{
+        $("#"+platform+"_add_button").hide();
+    }
+    $("[id^='"+platform+"_"+type+"_"+"']").hide();
+    d = platform+'_'+type+'_'+value;
+    d = d.replace(/ /g, '');
+    id = d.replace( /(:|\.|\[|\])/g, "\\$1" );
+    $('#'+id).show();
+}
+function render_cloud(platform, node){
+    elm = document.getElementById(platform+'_select');
+    //newElement = document.createElement('p');
+    //elm.appendChild(newElement); 
+    global_list[platform]={};
+    if('openstack:sliver' in node){
+        selectFlavor = document.createElement('select');
+        selectFlavor.id = platform+"_selectFlavor";
+        selectFlavor.name = platform+"_selectFlavor";
+        selectFlavor.onchange = function(){
+            /* 1) Display corresponding Flavor div - hide others - reset selectImage value */
+            $("#"+platform+"_selectImage option[value=0]").prop('selected', true);
+            toogle_div(platform, this.value, 'flavor');
+            /* 3) Disable Images, Enable only compatible ones in selectImage */
+            $("[id^='"+platform+"_image_"+"']").hide();
+            $("#"+platform+"_selectImage option").attr("disabled",true);
+            $.each(global_list[platform][this.value], function (i,v){
+                $("#"+platform+"_selectImage option[value='" + v + "']").attr("disabled",false);
+            });
+            $("#"+platform+"_selectImage").attr("disabled",false);
+        }
+        var option = document.createElement("option");
+        option.text = "-- select a flavor --";
+        option.value = 0;
+        selectFlavor.appendChild(option);
+        jQuery.each( node['openstack:sliver'], function( i, sliver ) {
+            if('openstack:flavor' in sliver){
+                f = render_option(sliver['openstack:flavor']);
+                selectFlavor.appendChild(f);
+                flavor = sliver["openstack:flavor"];
+                /* 1) create hidden div to explain caracteristics of the flavor */
+                render_description(platform, flavor, 'flavor');
+                flavor_name = flavor['@name'];
+                global_list[platform][flavor_name]=[];
+                if ("openstack:image" in flavor){
+                    selectImage = document.createElement('select');
+                    selectImage.id = platform+"_selectImage";
+                    selectImage.name = platform+"_selectImage";
+                    selectImage.onchange = function(){
+                        /* 2) display corresponding Image div - hide others */
+                        toogle_div(platform, this.value, 'image');
+                    }
+                    var option = document.createElement("option");
+                    option.text = "-- select an image --";
+                    option.value = 0;
+                    selectImage.appendChild(option);
+                    if(flavor["openstack:image"] instanceof Array){
+                        jQuery.each( flavor["openstack:image"], function( i, img ) {
+                           image = render_option(img);
+                           image.disabled = true;
+                           selectImage.appendChild(image);
+                           /* 2) create hidden div to explain caracteristics of the image */
+                           render_description(platform, img, 'image');
+                           global_list[platform][flavor_name].push(img['@name']);
+                        });
+                    }else{
+                        image = render_option(flavor["openstack:image"]);
+                        image.disabled = true;
+                        selectImage.appendChild(image);
+                        /* 2) create hidden div to explain caracteristics of the image */
+                        render_description(platform, flavor["openstack:image"], 'image');
+                        global_list[platform][flavor_name].push(flavor['openstack:image']['@name']);
+                    }
+                }
+
+            }
+        });
+        elm.appendChild(selectFlavor); 
+        elm.appendChild(selectImage); 
+    }
+    $("#"+platform+"_selectFlavor").css("width","100px");
+    $("#"+platform+"_selectFlavor").css("height","30px");
+    $("#"+platform+"_selectImage").css("width","30px");
+    $("#"+platform+"_selectImage").css("height","30px");
+}
+function is_finished(len_platforms, pf_status){
+    if(len_platforms == pf_status){
+        return true;
+    }else{
+        return false;
+    }
+}
+function sliver_name_exists(sliver_name){
+    if(sliver_name in added_nodes){
+        return true;
+    }
+    /*
+    if (sliver_name in deleted_nodes){
+        return true;
+    }
+    */
+    return false;
+}
+function find_sliver_name(sliver_name, num){
+    for (j=Object.keys(added_nodes).length; j<Object.keys(added_nodes).length+num; i++){
+        vm_name = sliver_name+'_'+j;
+        if(!sliver_name_exists(vm_name)){
+            return vm_name
+        }
+    }
+}
+
+function send_add(platform){ 
+    $('#'+platform+'_pending_add').show();
+    sliver_name = $('#'+platform+'_sliver_name').val();
+    sliver_name = sliver_name.replace(' ','_');
+    flavor_name = $('#'+platform+'_selectFlavor').val();
+    image_name = $('#'+platform+'_selectImage').val();
+
+    num = $('#'+platform+'_number').val();
+    if (num > 1){
+        for (i = 0; i < num; i++){
+            // XXX Check if the name already exist in existing VMs and added_nodes
+            vm_name = sliver_name+"_"+i;
+            if (sliver_name_exists(vm_name)){
+                vm_name = find_sliver_name(sliver_name, num);
+            }
+            node = get_node(vm_name, flavor_name, image_name);
+            request_rspec['rspec']['node'].push(node);
+            render_node(platform, node, 'pending_add');
+            added_nodes[vm_name]=node;
+        }
+    }else{
+        if (sliver_name_exists(sliver_name)){
+            sliver_name = find_sliver_name(sliver_name, num);
+        }
+        node = get_node(sliver_name, flavor_name, image_name);
+        request_rspec['rspec']['node'].push(node);
+        render_node(platform, node, 'pending_add');
+        added_nodes[sliver_name]=node;
+    }
+    toogle_div(platform, flavor_name, 'flavor');
+    toogle_div(platform, image_name, 'image');
+    flavor_name = $('#'+platform+'_selectFlavor').val(0);
+    image_name = $('#'+platform+'_selectImage').val(0);
+    $('#'+platform+'_add').hide();
+    $('#'+platform+'_add_button').hide();
+    $('#'+platform+'_div_pending').show();
+    console.log(request_rspec);
+    //jQuery('#'+platform+'_form_delete').submit();
+}
+function get_node(vm_name, flavor_name, image_name){
+        var node = {};
+        if(ad_rspec['rspec']['node'] instanceof Array) {
+            // Deep copy of the Array to avoid reference
+            node = jQuery.extend(true, {}, ad_rspec['rspec']['node'][0]);
+        }else{
+            // Deep copy of the Array to avoid reference
+            node = jQuery.extend(true, {}, ad_rspec['rspec']['node']);
+        }
+        if(node['openstack:sliver'] instanceof Array) {
+            node['openstack:sliver'] = node['openstack:sliver'][0];
+        }
+        node['openstack:sliver']['@sliver_name'] = vm_name;
+        console.log(vm_name);
+
+        if(node['openstack:sliver']['openstack:flavor'] instanceof Array) {
+            node['openstack:sliver']['openstack:flavor'] = node['openstack:sliver']['openstack:flavor'][0];
+        }
+        node['openstack:sliver']['openstack:flavor'] = Array();
+        node['openstack:sliver']['openstack:flavor'] = {'@name':flavor_name,'openstack:image':{'@name':image_name}};
+
+        $.each(node['openstack:sliver']['openstack:security_group'], function(i, group){
+            if(group['@name']=='default'){
+                node['openstack:sliver']['openstack:security_group'] = group;
+                return false;
+            }
+        });
+        return node;
+
+}
+function send_delete(platform, sliver_name){
+    $('#'+platform+'_pending_delete').show();
+    jQuery('#'+platform+'_vm').val(sliver_name);
+    jQuery('#'+platform+'_existing_'+sliver_name).hide();
+    node = remove_node_from_request_rspec(sliver_name);
+    deleted_nodes[sliver_name]=node;
+    render_node(platform, node, 'pending_delete');
+    $('#'+platform+'_div_pending').show();
+    console.log(request_rspec);
+}
+function remove_node_from_request_rspec(sliver_name){
+    var save_node = Array();
+    jQuery.each( request_rspec['rspec']['node'], function( i, node ) {
+        if(node['openstack:sliver']['@sliver_name']==sliver_name){
+            request_rspec['rspec']['node'].splice(i,1);
+            save_node = node;
+            return false;
+        }
+    });
+    return save_node;
+}
+function cancel_add(platform,sliver_name){
+    // remove the canceled node from the pending list
+    $('#'+platform+'_pending_add_'+sliver_name).remove();
+    // remove the canceled node from the request rspec
+    node = remove_node_from_request_rspec(sliver_name);
+    delete added_nodes[sliver_name];
+    // hide the pending div if there are no more nodes
+    if ($('#'+platform+'_pending_add div').length==0){
+        $('#'+platform+'_pending_add').hide();
+        if ($('#'+platform+'_pending_delete div').length==0){
+            $('#'+platform+'_div_pending').hide();
+        }
+    }
+}
+function cancel_delete(platform,sliver_name){
+    // display the canceled node back in existing nodes
+    $('#'+platform+'_existing_'+sliver_name).show();
+    // remove the canceled node from the pending list
+    $('#'+platform+'_pending_delete_'+sliver_name).remove();
+    // Cancel the deletion of an existing node -> push it back to the request rspec
+    request_rspec['rspec']['node'].push(deleted_nodes[sliver_name]);
+    delete deleted_nodes[sliver_name];
+    // hide the pending div if there are no more nodes
+    if ($('#'+platform+'_pending_delete div').length==0){
+        $('#'+platform+'_pending_delete').hide();
+        if ($('#'+platform+'_pending_add div').length==0){
+            $('#'+platform+'_div_pending').hide();
+        }
+    }
+}
+
+function public_ip(platform,sliver_name,is_public){
+    // XXX Change ip status in request_rspec
+    if(is_public){
+        // external_ip="true"
+        node = remove_node_from_request_rspec(sliver_name);
+        node['external_ip']="true";
+        added_nodes[sliver_name]['external_ip']="true";
+        request_rspec['rspec']['node'].push(node);        
+    }else{
+        console.log(sliver_name+' NOT public ');
+        // external_ip="false"
+        node = remove_node_from_request_rspec(sliver_name);
+        node['external_ip']="false";
+        added_nodes[sliver_name]['external_ip']="false";
+        request_rspec['rspec']['node'].push(node);        
+    }
+}
+
+function render_node(platform, node, state){
+    if('openstack:sliver' in node){
+        sliver = node['openstack:sliver']
+        var d = platform+'_'+state+'_'+sliver['@sliver_name'];
+        d = d.replace(/ /g, '');
+        id = d.replace( /(:|\.|\[|\])/g, "\\$1" );
+        $("#"+platform+"_"+state).append("<div id='"+platform+'_'+state+'_'+sliver['@sliver_name']+"' class='row'></div>");
+        //$("#"+id).append("<input type='hidden' name='"+platform+"_"+sliver['@sliver_name']+"' value='"+sliver['@sliver_name']+"'>");
+        if(state=='pending_add'){
+            $("#"+id).append("<div class='col-md-1' style='margin-left:0px;!important;'><input type='checkbox' id='publicip_"+platform+"_"+sliver['@sliver_name']+"' onclick=public_ip('"+platform+"','"+sliver['@sliver_name']+"',this.checked);></div>");
+        }else{
+            $("#"+id).append("<div class='col-md-1' style='margin-left:0px;!important;'>&nbsp;</div>");
+        }
+        $("#"+id).append("<div class='col-md-2' style='padding-left:0px;'>"+sliver['@sliver_name']+"</div>");
+        $("#"+id).append("<div class='col-md-3'>"+sliver['openstack:flavor']['@name']+"</div>");
+        $("#"+id).append("<div class='col-md-3'>"+sliver['openstack:flavor']['openstack:image']['@name']+"</div>");
+
+        if(state=='existing'){
+            $("#"+id).append("<div class='col-md-1'><input id='"+platform+"_delete_"+sliver['@sliver_name']+"' type='submit' form='"+platform+"_form_delete' value='Delete' onclick=send_delete('"+platform+"','"+sliver['@sliver_name']+"');></div>");
+        }else if(state=='pending_add'){
+            $("#"+id).append("<div class='col-md-1'><input id='"+platform+"_cancel_"+sliver['@sliver_name']+"' type='submit' form='"+platform+"_form_cancel' value='Cancel' onclick=cancel_add('"+platform+"','"+sliver['@sliver_name']+"');></div>");
+        }else if (state=='pending_delete'){
+            $("#"+id).append("<div class='col-md-1'><input id='"+platform+"_cancel_"+sliver['@sliver_name']+"' type='submit' form='"+platform+"_form_cancel' value='Cancel' onclick=cancel_delete('"+platform+"','"+sliver['@sliver_name']+"');></div>");
+        }else{
+            console.log("state: "+state+" not impemented");
+        }
+        /*
+        sliver['openstack:address']
+        sliver['openstack:flavor']
+        */
+    }
+}
+
+function allocate(platform, slicename){
+    $("#"+platform+"_main").addClass("disabled");
+    $("#"+platform+"_wait").show();
+    $("#"+platform+"_wait").spin();
+    $.post("/sfa/Allocate",{'hrn':slicename, 'type':'slice', 'platform':[platform], 'rspec':JSON.stringify(request_rspec)}, function( result ) {
+        console.log(result);
+        clear_data(platform);
+        load_data(platform,slicename);
+        $("#"+platform+"_main").removeClass("disabled");
+        $("#"+platform+"_wait").hide();
+        mysliceAlert('Success: changes applied','success', true);
+    });
+}
+function clear_data(platform){
+    $('#'+platform+'_existing').children().remove();
+    $('#'+platform+'_pending_delete').children().remove();
+    $("#"+platform+"_selectFlavor").remove();
+    $("#"+platform+"_selectImage").remove();
+    $('#'+platform+'_pending_add').children().remove();
+    $('#'+platform+'_div_pending').hide();
+}
+function load_data(platform, slicename){
+    var platform_status = Array();
+    var platform_empty = Array();
+
+    $.post("/sfa/Describe",{'hrn':slicename, 'type':'slice', 'platform':[platform]}, function( d ) {
+        data = d;
+        console.log(data);
+        if('parsed' in data[platform] && 'rspec' in data[platform]['parsed']){
+           manifest_rspec = data[platform]['parsed']['rspec'];
+           request_rspec = data[platform]['parsed'];
+           request_rspec['rspec']['@type']='request';
+           if('node' in manifest_rspec){
+               if(manifest_rspec['node'] instanceof Array) {
+                   jQuery.each( manifest_rspec['node'], function( i, node ) {
+                       render_node(platform,node, 'existing');
+                   });
+               }else{
+                   render_node(platform,manifest_rspec['node'], 'existing');
+               }
+               $('#'+platform+'_existing').show();
+           }
+        }
+    });
+    $.post("/sfa/ListResources",{'platform':[platform]}, function( d ) {
+        //$.extend(data,d);
+        //console.log(data);
+        if('parsed' in d[platform] && 'rspec' in d[platform]['parsed']){
+           ad_rspec = d[platform]['parsed'];
+           if('node' in ad_rspec['rspec']){
+               if(ad_rspec['rspec']['node'] instanceof Array) {
+                   jQuery.each( ad_rspec['rspec']['node'], function( i, node ) {
+                       render_cloud(platform,node);
+                   });
+               }else{
+                   render_cloud(platform,ad_rspec['rspec']['node']);
+               }
+           }else{
+               platform_empty.push(platform);
+           }
+        }else{
+            platform_empty.push(platform);
+        }
+        platform_status.push(platform);
+        if(is_finished(len_platforms,platform_status.length)){
+            $("#loading").hide();
+            if(platform_empty.length == len_platforms){
+                $("#warning_message").show();
+            }
+        }
+    });
+}
+$(document).ready(function() {
+{% for platform in platforms %}
+    {% if platform in cloud_platforms %}
+    load_data('{{platform}}', '{{slicename}}');
+    {% endif %}
+{% endfor %}
+});
+</script>
+{% endblock %}
+
+{% block content %}
+{{post_values}}
+{% for platform in platforms %}
+    {% if platform in cloud_platforms %}
+    <div id="{{platform}}_wait" style="display:none;margin-top:20px;position:absolute;margin-left:300px;"></div>
+    <div id="{{platform}}_main" style="padding-left:20px;padding-top:20px;padding-right:20px;padding-bottom:20px;border-style:solid;border-width:1px;width:700px;">
+        <h2>{{ platform }}</h2>
+        // display only if VMs already in slice
+        <h4>VMs in slice {{slicename}}</h4>
+        <form id="{{platform}}_form_delete" method="post">
+        {% csrf_token %}
+        <div id="{{platform}}_existing" class="row alert alert-info" style="display:none;">
+        <input type="hidden" name="{{platform}}_vm" id="{{platform}}_vm">
+        <input type="hidden" name="action" id="action" value="delete">
+        <input type="hidden" name="platform" id="platform" value="{{platform}}">
+        </div> 
+        </form>
+        <h4><a href="#" onclick="$('#{{platform}}_div_add').toggle();"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span> Create new VMs</a></h4>
+        <div id="{{platform}}_div_add" class="alert" style="background-color:#f1f1f1;display:none;margin-bottom:0px !important;padding-bottom:6px !important;">
+        <form id="{{platform}}_form_add" method="post" class="form-inline">
+        {% csrf_token %}
+        <div id="{{platform}}_input" class="row">
+            <div class="col-md-1"></div>
+            <div class="col-md-3"><label for="{{platform}}_number">number:</label>
+            <input type="text" maxlength="2" id="{{platform}}_number" name="{{platform}}_number" style="width:2.2em;min-width:2.2em;height:30px;" value="1" class="form-control" required>
+            </div>
+            <div class="col-md-8"><label for="{{platform}}_sliver_name">name:</label>
+            <div class="form-group">
+            <input type="text" name="{{platform}}_sliver_name" id="{{platform}}_sliver_name" value="VM" maxlength="12" class="form-control" style="height:30px;" required>
+            </div>
+            </div>
+            <div class="col-md-1"></div>
+            <div id="{{platform}}_select" class="col-md-11"></div>
+        </div>
+        <div id="{{platform}}_add" class="row">
+            <div class="col-md-1">&nbsp; 
+            <input type="hidden" name="action" id="action" value="add">
+            <input type="hidden" name="platform" id="platform" value="{{platform}}">
+            </div>
+        </div>
+        <div class="row" style="padding-top:6px;">
+            <div class="col-md-1">&nbsp;</div>
+            <div class="col-md-11" id="{{platform}}_add_button" style="display:none;">
+            <input type="submit" form="{{platform}}_form_add" value="Add" onclick="send_add('{{platform}}');">
+            </div>
+        </div>
+        </form>
+        </div>
+        <br>
+        <div id="{{platform}}_div_pending" style="display:none;">
+        // display only pending changes
+        <h4>Pending changes</h4>
+        <form id="{{platform}}_form_reserve" method="post">
+        {% csrf_token %}
+        <div id="{{platform}}_pending_add" class="row alert alert-success" style="display:none;margin-bottom:3px !important;"></div> 
+        <div id="{{platform}}_pending_delete" class="row alert alert-danger" style="display:none;margin-bottom:3px !important;"></div> 
+        <br>
+        <input type="hidden" name="action" id="action" value="reserve">
+        <input type="hidden" name="platform" id="platform" value="{{platform}}">
+        <input type="submit" form="{{platform}}_form_reserve" value="Apply changes" onclick="allocate('{{platform}}','{{slicename}}');">
+        </form>
+        </div>
+    </div>
+    {% endif %}
+{% endfor %}
+{% endblock %}
index 7dfddc9..96e9fc8 100644 (file)
@@ -79,7 +79,9 @@
 
 </script>
 
+<!--
 <div>
     <button id="renewslices" type="button" class="btn btn-primary"><span class="glyphicon glyphicon-refresh"></span> Renew slice</button>
     <button id="deleteslices" type="button" class="btn btn-danger"><span class="glyphicon glyphicon-remove"></span> Delete slice</button>
-</div>
+</div> 
+-->
index 07a4597..fbbd2b1 100644 (file)
                                <input type="text" class="form-control" id="authority_hrn" name="org_name" style="width:100%" placeholder="Project" 
                                        title="Select a project under which you want to create your slice" required="required">
                          </div>
+              <!--  
                          <div class="form-group">
                              <label>
                                  Provide an URL for your experiment (not required)
                              </label>
-                             <input type="text" class="form-control" name="url" id="url" style="width:100%" placeholder="Experiment URL (if one exists)"
+                              <input type="text" class="form-control" name="url" id="url" style="width:100%" placeholder="Experiment URL (if one exists)"
                                        title="Please provide the url of your experiment" value="{{url}}">
                          </div>
                          <div class="form-group">
@@ -57,7 +58,7 @@
                    </label>
                                  <textarea id="purpose" name="purpose" class="form-control" rows="6" placeholder="Experiment description" style="width:100%" 
                                        title="Description of your experiment" required="required">{{ purpose }}</textarea>
-                         </div>
+                         </div> -->
                          <button type="submit" id=submit_pi class="btn btn-onelab"><span class="glyphicon glyphicon-plus"></span> Create slice</button>
                        </form>
        
index 42b26f5..b35fa35 100644 (file)
@@ -26,6 +26,9 @@ from myslice.settings               import logger, config
 from repoze.lru                     import lru_cache
 from rest.json_encoder              import MyEncoder
 
+import uuid
+def unique_call_id(): return uuid.uuid4().urn
+
 def dispatch(request, method):
 
     hrn = None
@@ -46,34 +49,44 @@ def dispatch(request, method):
     elif request.method == 'GET':
         req_items = request.GET
 
-    logger.debug("URL = %s" % request.build_absolute_uri())
-
-    for el in req_items.items():
-        if el[0].startswith('rspec'):
-            rspec += el[1]
-        elif el[0].startswith('platform'):
-            platforms = frozenset(req_items.getlist('platform[]'))
-        elif el[0].startswith('options'):
-            options_url = el[1] #req_items.getlist('options')
-            options = QueryDict(options_url)
-        elif el[0].startswith('output_format'):
-            output_format = el[1] #req_items.getlist('options')
-        elif el[0].startswith('hrn'):
-            hrn = el[1]
-        elif el[0].startswith('urn'):
-            urn = el[1]
-        elif el[0].startswith('type'):
-            object_type = el[1]
-        elif el[0].startswith('recursive'):
-            if el[1] == '1':
+    logger.debug("dispatch got = %s" % req_items.dict())
+    #t = dict(req_items.iterlists())
+    #rspec = req_items.getlist('rspec')
+    #logger.debug("dispatch got = %s" % t)
+
+    platforms = req_items.getlist('platform[]')
+    for k in req_items.dict():
+        logger.debug("key = %s - value = %s" % (k,req_items.get(k)))
+        if k == 'rspec':
+            rspec = req_items.get(k)
+        if k == 'options':
+            options = req_items.get(k)
+        if k == 'output_format':
+            output_format = req_items.get(k)
+        if k == 'hrn':
+            hrn = req_items.get(k)
+        if k == 'urn':
+            urn = req_items.get(k)
+        if k == 'type':
+            object_type = req_items.get(k)
+        if k == 'recursive':
+            if v == '1':
                 recursive = True
             else:
                 recursive = False
-        elif el[0].startswith('display'):
-            display = el[1]
+        if k == 'display':
+            display = req_items.get(k)
+
+    if rspec is not None:
+        try:
+            rspec = json.loads(rspec)
+        except Exception,e:
+            logger.debug("rspec type = %s" % type(rspec))
+        if type(rspec) is dict:
+            rspec = xmltodict.unparse(rspec)
 
     start_time = time.time()
-    results = sfa_client(request, method, hrn, urn, object_type, rspec, recursive, options, platforms, output_format, False)
+    results = sfa_client(request, method, hrn=hrn, urn=urn, object_type=object_type, rspec=rspec, recursive=recursive, options=options, platforms=platforms, output_format=output_format, admin=False)
     logger.debug("EXEC TIME - sfa_client() - %s sec." % (time.time() - start_time))
     if display == 'table':
         return render_to_response('table-default.html', {'data' : data, 'fields' : columns, 'id' : '@component_id', 'options' : None})
@@ -125,6 +138,8 @@ def sfa_client(request, method, hrn=None, urn=None, object_type=None, rspec=None
         object_type = ''
     if rspec is None:
         rspec = ''
+    else:
+        logger.debug("RSPEC = %s" % rspec)
     if recursive is None:
         recursive = False
     if options is None:
@@ -156,17 +171,17 @@ def sfa_client(request, method, hrn=None, urn=None, object_type=None, rspec=None
     server_am = False
     for pf in platforms:
         platform = get_platform_config(request, pf)
-        logger.debug("platform={}".format(platform))
+        if 'rspec_type' in platform and 'rspec_version' in platform:
+            api_options['geni_rspec_version'] = {'type': platform['rspec_type'],'version': platform['rspec_version']}
+        else:
+            api_options['geni_rspec_version'] = {'type': 'GENI', 'version': '3'}
         if 'sm' in platform and len(platform['sm']) > 0:
-            logger.debug('sm')
             server_am = True
             server_url = platform['sm']
         if 'rm' in platform and len(platform['rm']) > 0:
-            logger.debug('rm')
             server_am = False
             server_url = platform['rm']
         if 'registry' in platform and len(platform['registry']) > 0:
-            logger.debug('registry')
             server_am = False
             server_url = platform['registry']
     
@@ -196,8 +211,6 @@ def sfa_client(request, method, hrn=None, urn=None, object_type=None, rspec=None
             start_time = time.time()
             result = server.GetVersion()
             logger.debug("EXEC TIME - GetVersion() - %s sec." % (time.time() - start_time))
-            logger.debug(result)
-            logger.debug(result['value'])
             if 'geni_ad_rspec_versions' in result['value']:
                 for v in result['value']['geni_ad_rspec_versions']:
                     if v['type'] == options['geni_rspec_version']:
@@ -295,24 +308,26 @@ def sfa_client(request, method, hrn=None, urn=None, object_type=None, rspec=None
                     elif method == 'Allocate':
                         api_options['call_id']    = unique_call_id()
                         # List of users comes from the Registry
-                        api_options['sfa_users']  = sfa_users
-                        api_options['geni_users'] = geni_users
+                        users = get_users_in_slice(request, hrn)
+                        api_options['sfa_users']  = users
+                        api_options['geni_users'] = users
                         # if GetVersion = v2
                         version = server.GetVersion()
                         if version['geni_api'] == 2:
                             result = server.CreateSliver([urn] ,[object_cred], rspec, api_options)
                         # else GetVersion = v3
                         else:
-                            result = server.Allocate([urn] ,[object_cred], rspec, api_options)
+                            result = server.Allocate(urn ,[object_cred], rspec, api_options)
                     elif method == 'Provision':
                         # if GetVersion = v2
                         # Nothing it is not supported by v2 AMs
                         version = server.GetVersion()
+                        # List of users comes from the Registry
+                        users = get_users_in_slice(request, hrn)
+                        api_options['sfa_users']  = users
+                        api_options['geni_users'] = users
                         if version['geni_api'] == 3:
                             api_options['call_id']    = unique_call_id()
-                            # List of users comes from the Registry
-                            api_options['sfa_users']  = sfa_users
-                            api_options['geni_users'] = geni_users
                             result = server.Provision([urn] ,[object_cred], api_options)
                     elif method == 'Status':
                         result = server.Status([urn] ,[object_cred], api_options)
@@ -364,6 +379,7 @@ def sfa_client(request, method, hrn=None, urn=None, object_type=None, rspec=None
                         logger.debug('method %s not handled by Registry' % method)
                         result = []
             if output_format is not None:
+                logger.debug("result = " % result)
                 if 'value' in result:
                     # TODO Python Caching 
                     # to avoid translating the same RSpec in the same format several times
@@ -399,6 +415,30 @@ def translate(rspec, output_format):
     response = urllib2.urlopen(req)
     return response.read()
 
+def rename(self,key,new_key):
+    ind = self._keys.index(key)  #get the index of old key, O(N) operation
+    self._keys[ind] = new_key    #replace old key with new key in self._keys
+    self[new_key] = self[key]    #add the new key, this is added at the end of self._keys
+    self._keys.pop(-1)           #pop the last item in self._keys
+
+def get_users_in_slice(request, slice_hrn):
+    # select users.user_hrn, users.user_email, users.keys  
+    # from myslice:slice 
+    # where slice_hrn=='onelab.upmc.r2d2.slice1'
+    users_query  = Query().get('myslice:slice').filter_by('slice_hrn', '==', slice_hrn).select('users.user_hrn', 'users.user_urn', 'users.user_email','users.keys')
+    users = execute_admin_query(request, users_query)
+    rmap = {'user_urn':'urn','user_email':'email','user_hrn':'hrn'}
+    res = list()
+    for u in users[0]['users']:
+        r_user = dict()
+        for k,v in u.items():
+            if k in rmap.keys():
+                r_user[rmap[k]] = v
+            else:
+                r_user[k]=v
+        res.append(r_user)
+    return res
+
 def get_user_config(request, user_email, platform_name):
     account = get_user_account(request, user_email, platform_name)
     return json.loads(account['config']) if account['config'] else {}
index c3dc013..0f08a99 100755 (executable)
@@ -166,7 +166,7 @@ class Client(object):
         kwargs["auth"] = HTTPBasicAuth(settings.SLA_COLLECTOR_USER,
                                       settings.SLA_COLLECTOR_PASSWORD)
 
-        result = requests.post(url, data, **kwargs)
+        result = requests.post(url, data, verify=False, **kwargs)
         location = result.headers["location"] \
             if "location" in result.headers else "<null>"
         print "POST {} {} - Location: {}".format(
@@ -343,12 +343,12 @@ class Templates(object):
         converter = xmlconverter.AgreementConverter()
         self.res = _Resource(resourceurl, converter)
 
-    def getall(self):
+    def getall(self, provider_id):
         """ Get all templates
 
         :rtype : list[wsag_model.Template]
         """
-        return self.res.getall()
+        return self.res.get(path="", params={"testbed": provider_id})
 
     def getbyid(self, provider_id):
         """Get a template
index c9043f6..1dbb428 100755 (executable)
@@ -26,62 +26,6 @@ from django.http import HttpResponse
 
 from myslice.settings import logger, SLA_COLLECTOR_URL
 
-
-# class AgreementsFilter(object):
-# def __init__(self, status=None, provider=None, consumer=None):
-#         self.status = status
-#         self.provider = provider
-#         self.consumer = consumer
-#
-#     def __repr__(self):
-#         return "<AgreementsFilter(status={}, provider={}, consumer={})>".format(
-#             self.status, self.provider, self.consumer
-#         )
-#
-#     @staticmethod
-#     def _check(expectedvalue, actualvalue):
-#         if expectedvalue is None or expectedvalue == '':
-#             return True
-#         else:
-#             return actualvalue == expectedvalue
-#
-#     def check(self, agreement):
-#         """Check if this agreement satisfy the filter.
-#
-#         The agreement must be previously annotated
-#         """
-#         guaranteestatus = agreement.guaranteestatus
-#         provider = agreement.context.provider
-#         consumer = agreement.context.consumer
-#         return (
-#             AgreementsFilter._check(self.status, guaranteestatus) and
-#             AgreementsFilter._check(self.provider, provider) and
-#             AgreementsFilter._check(self.consumer, consumer)
-#         )
-
-
-# class FilterForm(forms.Form):
-#     _attrs = {'class': 'form-control'}
-#     exclude = ()
-#     status = forms.ChoiceField(
-#         choices=[
-#             ('', 'All'),
-#             (wsag_model.AgreementStatus.StatusEnum.FULFILLED, 'Fulfilled'),
-#             (wsag_model.AgreementStatus.StatusEnum.VIOLATED, 'Violated'),
-#             (wsag_model.AgreementStatus.StatusEnum.NON_DETERMINED, 'Non determined')],
-#         widget=forms.Select(attrs=_attrs),
-#         required=False
-#     )
-#     provider = forms.CharField(
-#         widget=forms.TextInput(attrs=_attrs),
-#         required=False
-#     )
-#     consumer = forms.CharField(
-#         widget=forms.TextInput(attrs=_attrs),
-#         required=False
-#     )
-
-
 class SLAView(FreeAccessView, ThemeView):
     template_name = 'slice-tab-sla.html'
 
@@ -89,9 +33,6 @@ class SLAView(FreeAccessView, ThemeView):
 
         page = Page(request)
 
-        # logger.debug("SLA slice name: {}".format(slicename))
-
-        # consumer_id = None
         agreement_id = None
         enforcements = {}
         violations = {}
@@ -100,14 +41,6 @@ class SLAView(FreeAccessView, ThemeView):
                 'ok', 'slivers']
         ag_info = []
 
-        # filter_ = None
-        # form = FilterForm(request.GET)
-        # if form.is_valid():
-        #     filter_ = _get_filter_from_form(form)
-
-        # consumer_id = _get_consumer_id(request)
-
-        # agreements = _get_agreements(agreement_id, consumer_id=consumer_id, filter_=filter_)
         agreements = _get_agreements_by_slice(slicename)
 
         for agreement in agreements:
@@ -118,8 +51,6 @@ class SLAView(FreeAccessView, ThemeView):
             row.append(agreement.context.time_formatted())  # Date
 
             enf = _get_enforcement(agreement.agreement_id, provider)
-            # logger.debug("SLA guarantee status {}: {}".format(agreement.agreement_id,
-            #                                                   agreement.guaranteestatus))
 
             if enf.enabled == 'true':
                 row.append('Evaluating')  # Status
@@ -178,46 +109,6 @@ class SLAView(FreeAccessView, ThemeView):
         return render_to_response(self.template_name, template_env, context_instance=RequestContext(request))
 
 
-# class AgreementsFilter(object):
-#     def __init__(self, status=None, provider=None, consumer=None):
-#         self.status = status
-#         self.provider = provider
-#         self.consumer = consumer
-#
-#     def __repr__(self):
-#         return "<AgreementsFilter(status={}, provider={}, consumer={})>".format(
-#             self.status, self.provider, self.consumer
-#         )
-#
-#     @staticmethod
-#     def _check(expectedvalue, actualvalue):
-#         if expectedvalue is None or expectedvalue == '':
-#             return True
-#         else:
-#             return actualvalue == expectedvalue
-#
-#     def check(self, agreement):
-#         """Check if this agreement satisfy the filter.
-#
-#         The agreement must be previously annotated
-#         """
-#         guaranteestatus = agreement.guaranteestatus
-#         provider = agreement.context.provider
-#         consumer = agreement.context.consumer
-#         return (
-#             AgreementsFilter._check(self.status, guaranteestatus) and
-#             AgreementsFilter._check(self.provider, provider) and
-#             AgreementsFilter._check(self.consumer, consumer)
-#         )
-
-
-# class ContactForm(forms.Form):
-#     subject = forms.CharField(max_length=100)
-#     message = forms.CharField()
-#     sender = forms.EmailField()
-#     cc_myself = forms.BooleanField(required=False)
-
-
 def _get_agreements_client():
     return restclient.Factory.agreements()
 
@@ -246,13 +137,6 @@ def _get_enforcement(agreement_id, testbed):
     return enforcement
 
 
-# def _get_filter_from_form(form):
-#
-#     data = form.cleaned_data
-#     result = AgreementsFilter(
-#         data["status"], data["provider"], data["consumer"])
-#     return result
-
 def agreement_term_violations(request, agreement_id, guarantee_name):
     page = Page(request)
     prelude_env = page.prelude_env()
@@ -290,9 +174,6 @@ def agreement_term_violations(request, agreement_id, guarantee_name):
     return render_to_response('violations_template.html', context, context_instance=RequestContext(request))
 
 
-#     return render(request, 'violations_template.html', context)
-
-
 # TODO Change function to class
 def agreement_details(request, agreement_id):
     page = Page(request)
@@ -318,38 +199,6 @@ def agreement_details(request, agreement_id):
     #return render(request, 'agreement_detail.html', context)
 
 
-# def _get_agreements(agreement_id, slice=None, provider_id=None, consumer_id=None, filter_=None):
-#
-#     agreements_client = _get_agreements_client()
-#     if agreement_id is None:
-#         if consumer_id is not None:
-#             agreements, response = agreements_client.getbyconsumer(consumer_id)
-#         elif provider_id is not None:
-#             agreements, response = agreements_client.getbyprovider(provider_id)
-#         elif slice is not None:
-#             agreements_client = _get_agreements_client("slice")
-#             agreements, response = agreements_client.getbyslice(slice)
-#         else:
-#             raise ValueError(
-#                 "Invalid values: consumer_id and provider_id are None")
-#     else:
-#         agreement, response = agreements_client.getbyid(agreement_id)
-#         agreements = [agreement]
-#
-#     annotator = wsag_helper.AgreementAnnotator()
-#     for agreement in agreements:
-#         id_ = agreement.agreement_id
-#         testbed = agreement.context.provider
-#         status = _get_agreement_status(id_, testbed)
-#         annotator.annotate_agreement(agreement, status)
-#
-#     if filter_ is not None:
-#         print "FILTERING ", repr(filter_)
-#         agreements = filter(filter_.check, agreements)
-#     else:
-#         print "NOT FILTERING"
-#     return agreements
-
 def _get_agreements_by_slice(slice):
     agreements_client = _get_agreements_client()
     agreements, response = agreements_client.getbyslice(slice)
@@ -364,12 +213,6 @@ def _get_agreements_by_slice(slice):
     return agreements
 
 
-# def _get_agreements_by_consumer(consumer_id):
-#
-#     agreements_client = _get_agreements_client()
-#     agreements, response = agreements_client.getbyconsumer(consumer_id)
-#     return agreements
-
 def _get_agreement_status(agreement_id, testbed):
     agreements_client = _get_agreements_client()
     status, response = agreements_client.getstatus(agreement_id, testbed)
@@ -394,6 +237,20 @@ class Testbeds(FreeAccessView, ThemeView):
         return HttpResponse(SLAtestbeds.text, content_type="application/json", status=SLAtestbeds.status_code)
 
 
+class AgreementTemplates(FreeAccessView, ThemeView):
+    def get(self, request, *args, **kwargs):
+        c = restclient.Templates(SLA_COLLECTOR_URL)
+        testbed = kwargs.get('testbed', None)
+
+        templates, response = c.getall(testbed)
+        service_level_objectives = []
+
+        for template in templates:
+            service_level_objectives.append(
+                [v.servicelevelobjective for v in template.guaranteeterms.values()])
+
+        return HttpResponse(service_level_objectives, content_type="application/json", status=response.status_code)
+
 class CreateAgreement(LoginRequiredView, ThemeView):
     def post(self, request, *args, **kwargs):
 
@@ -414,7 +271,7 @@ class CreateAgreement(LoginRequiredView, ThemeView):
         dt = datetime.fromtimestamp(float(tstmp))
         # gmt_2 = pytz.timezone("Etc/GMT-2")
         # dlocal = gmt_2.localize(dt).isoformat()
-        dlocal = dt.isoformat() + "CET" # FIXME: hardcoded for demo purposes
+        dlocal = dt.isoformat() + "CET"
         data["SLIVER_INFO_EXPIRATION"] = dlocal
 
         # logger.debug("SLA Agreement parameters: {}".format(data.dict()))
index 03ab14f..87363ee 100755 (executable)
@@ -13,6 +13,8 @@ urlpatterns = patterns('',
             slicetabsla.agreement_details, name='agreement_details'),
        url(r'^agreements/(?P<agreement_id>[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12})/guarantees/(?P<guarantee_name>\w+)/violations$',
             slicetabsla.agreement_term_violations, name='agreement_term_violations'),
+    url(r'^agreements/templates/(?P<testbed>[^/]+)',
+            slicetabsla.AgreementTemplates.as_view(), name='agreement_templates'),
     url(r'^agreements/create/$',
             slicetabsla.CreateAgreement.as_view(), name="agreement_create"),
        # url(r'^agreements/simplecreate/?$',