Merge branch 'onelab' of ssh://git.onelab.eu/git/myslice into onelab
authorCiro Scognamiglio <ciro.scognamiglio@cslash.net>
Tue, 27 Jan 2015 17:43:26 +0000 (18:43 +0100)
committerCiro Scognamiglio <ciro.scognamiglio@cslash.net>
Tue, 27 Jan 2015 17:43:26 +0000 (18:43 +0100)
Conflicts:
portal/actions.py
portal/static/js/myslice.js

1  2 
.settings/org.eclipse.core.resources.prefs
myslice/settings.py
portal/actions.py
portal/models.py
portal/projectrequestview.py
portal/static/css/fed4fire.css
portal/static/js/myslice.js
portal/templates/_widget-slice-sections.html
portal/templates/fed4fire/fed4fire_projectrequest_view.html
portal/templates/management-tab-requests.html
portal/templates/slice-resource-view.html

@@@ -2,7 -2,7 +2,10 @@@ eclipse.preferences.version=
  encoding//portal/django_passresetview.py=utf-8
  encoding//portal/forms.py=utf-8
  encoding//portal/migrations/0002_extend_slice.py=utf-8
++encoding//portal/migrations/0005_extend_user.py=utf-8
++encoding//portal/migrations/0008_extend_user.py=utf-8
++encoding//portal/migrations/0009_initial.py=utf-8
++encoding//portal/migrations/0010_project.py=utf-8
  encoding//portal/models.py=utf-8
  encoding//portal/urls.py=utf-8
  encoding//portal/validationview.py=utf-8
--encoding//portal/views.py=utf-8
@@@ -47,7 -47,7 +47,7 @@@ except
  # assume we have ./static present already
  HTTPROOT="/var/myslice-f4f"
  # the place to store local data, like e.g. the sqlite db
--DATAROOT="/var/unfold"
++DATAROOT="/Users/moray/Sites/upmc/myslice"
  # if not there, then we assume it's from a devel tree
  if not os.path.isdir (os.path.join(HTTPROOT,"static")):
      HTTPROOT=ROOT
@@@ -1,17 -1,19 +1,19 @@@
- from django.http                import HttpResponse
- from manifold.core.query        import Query
- from manifoldapi.manifoldapi    import execute_query,execute_admin_query
- from portal.models              import PendingUser, PendingSlice, PendingAuthority, PendingProject
+ from django.http                    import HttpResponse
+ from manifold.core.query            import Query
+ from manifoldapi.manifoldapi        import execute_query,execute_admin_query
 -from portal.models                  import PendingUser, PendingSlice, PendingAuthority
++from portal.models                  import PendingUser, PendingSlice, PendingAuthority, PendingProject
+ from unfold.page                    import Page
  import json
  
- from django.contrib.auth.models  import User
- from django.contrib.sites.models import Site
- from django.contrib.auth        import get_user_model
- from django.template.loader     import render_to_string
- from django.core.mail           import EmailMultiAlternatives, send_mail
+ from django.contrib.auth.models     import User
+ from django.contrib.sites.models    import Site
+ from django.contrib.auth            import get_user_model
+ from django.template.loader         import render_to_string
+ from django.core.mail               import EmailMultiAlternatives, send_mail
  
- from myslice.theme              import ThemeView
- from myslice.configengine       import ConfigEngine
+ from myslice.theme                  import ThemeView
+ from myslice.configengine           import ConfigEngine
  
  
  theme = ThemeView()
@@@ -96,3 -96,3 +96,10 @@@ class PendingSlice(models.Model)
      type_of_nodes   = models.TextField(default='NA')
      purpose         = models.TextField(default='NA')
      created         = models.DateTimeField(auto_now_add = True)
++    
++class PendingProject(models.Model):
++    project_name    = models.TextField()
++    user_hrn        = models.TextField()
++    authority_hrn   = models.TextField(null=True)
++    purpose         = models.TextField(default='NA')
++    created         = models.DateTimeField(auto_now_add = True)
  from django.shortcuts           import render
  from django.contrib.sites.models import Site
  
--
--from unfold.page                import Page
--
  from manifold.core.query        import Query
  from manifoldapi.manifoldapi    import execute_admin_query, execute_query
  
--from portal.actions             import is_pi, create_slice, create_pending_slice, clear_user_creds
--#from portal.forms               import SliceRequestForm
  from unfold.loginrequired       import LoginRequiredAutoLogoutView
--from ui.topmenu                 import topmenu_items_live, the_user
++
++from portal.actions import create_pending_project
++
++from portal.models import PendingProject
  
  from myslice.theme import ThemeView
  
  import json, time, re
  
--import activity.user
--
--class ProjectRequestView (LoginRequiredAutoLogoutView, ThemeView):
++class ProjectRequestView(LoginRequiredAutoLogoutView, ThemeView):
      template_name = 'projectrequest_view.html'
      
--    # because we inherit LoginRequiredAutoLogoutView that is implemented by redefining 'dispatch'
--    # we cannot redefine dispatch here, or we'd lose LoginRequired and AutoLogout behaviours
--    def post (self, request):
--        return self.get_or_post (request, 'POST')
++    def getAuthorities(self, request):
++        authorities_query = Query.get('authority').select('name', 'authority_hrn')
++        authorities = execute_admin_query(request, authorities_query)
++        if authorities is not None:
++            authorities = sorted(authorities, key=lambda k: k['authority_hrn'])
++            authorities = sorted(authorities, key=lambda k: k['name'])
++        return authorities
++    
++    def getUserAuthority(self, request):
++        # Get user_email (XXX Would deserve to be simplified)
++        user_query  = Query().get('local:user').select('email','config')
++        user_details = execute_query(request, user_query)
++        for user_detail in user_details:
++            user_config = json.loads(user_detail['config'])
++            user_authority = user_config.get('authority','N/A')
++        return user_authority
++    
++    def getUserHrn(self, request):
++        user_hrn = None
++        
++        account_query  = Query().get('local:account').select('user_id','platform_id','auth_type','config')
++        account_details = execute_query(request, account_query)
++
++        platform_query  = Query().get('local:platform').select('platform_id','platform','gateway_type','disabled')
++        platform_details = execute_query(request, platform_query)
++        
++        # getting user_hrn from local:account
++        for account_detail in account_details:
++            for platform_detail in platform_details:
++                if platform_detail['platform_id'] == account_detail['platform_id']:
++                    # taking user_hrn only from myslice account
++                    # NOTE: we should later handle accounts filter_by auth_type= managed OR user
++                    if 'myslice' in platform_detail['platform']:
++                        account_config = json.loads(account_detail['config'])
++                        user_hrn = account_config.get('user_hrn','N/A')
++        return user_hrn        
++                   
++    def post(self, request):
++        return self.handle_request(request, 'POST')
  
--    def get (self, request):
--        return self.get_or_post (request, 'GET')
++    def get(self, request):
++        return self.handle_request(request, 'GET')
  
--    def get_or_post  (self, wsgi_request, method):
++    def handle_request(self, wsgi_request, method):
++        errors = []
++        authority_hrn = None
++        authority_name = None
++        
++        user_hrn = self.getUserHrn(wsgi_request)
++        
++        authorities = self.getAuthorities(wsgi_request)
++        
++        user_authority = self.getUserAuthority(wsgi_request)
++        
++        # getting the org from authority
++        for authority in authorities:
++            if authority['authority_hrn'] == user_authority:
++                authority_name = authority['name']
++        
++        if method == 'POST' :
++           
++            post = {
++                'user_hrn'          : user_hrn,
++                'authority_hrn'     : wsgi_request.POST.get('authority_name', ''),
++                'project_name'      : wsgi_request.POST.get('project_name', ''),
++                'purpose'           : wsgi_request.POST.get('purpose', ''),
++            }
++        
++#             # create slice_hrn based on authority_hrn and slice_name
++#             #             slice_name = slice_request['slice_name']
++#             req_slice_hrn = authority_hrn + '.' + slice_name
++#             # comparing requested slice_hrn with the existing slice_hrn 
++#             slice_query  = Query().get('myslice:slice').select('slice_hrn','parent_authority').filter_by('parent_authority','==',authority_hrn)
++#             slice_details_sfa = execute_admin_query(wsgi_request, slice_query)
++#             for _slice in slice_details_sfa:
++#                 if _slice['slice_hrn'] == req_slice_hrn:
++#                     errors.append('Slice already exists. Please use a different slice name.')
++            
++
++            # What kind of slice name is valid?
++            if (post['project_name'] is None or post['project_name'] == ''):
++                errors.append('Project name is mandatory')
++            
++            if (re.search(r'^[A-Za-z0-9_]*$', post['project_name']) == None):
++                errors.append('Project name may contain only letters, numbers, and underscore.')
++            
++            if (post['authority_hrn'] is None or post['authority_hrn'] == ''):
++                errors.append('Organization is mandatory')
++    
++            if (post['purpose'] is None or post['purpose'] == ''):
++                errors.append('Experiment purpose is mandatory')
++
++            if not errors:
++                create_pending_project(wsgi_request, post)
++        
++        # retrieves the pending projects list
++        pending_projects = PendingProject.objects.all().filter(user_hrn=user_hrn)
++                    
++        env = {
++               'errors':        errors,
++               'username':      wsgi_request.user,
++               'theme':         self.theme,
++               'authorities':   authorities,
++               'authority_hrn': user_authority,
++               'pending_projects': pending_projects,
++        }
++        return render(wsgi_request, self.template, env)
++    
++        
++    
          """
          """
          errors = []
          #
          platform_query  = Query().get('local:platform').select('platform_id','platform','gateway_type','disabled')
          platform_details = execute_query(wsgi_request, platform_query)
++        
          user_hrn = None
          # getting user_hrn from local:account
          for account_detail in account_details:
  
  
          # Page rendering
--        page = Page(wsgi_request)
--        page.add_js_files  ( [ "js/jquery.validate.js", "js/jquery-ui.js" ] )
--        page.add_css_files ( [ "https://code.jquery.com/ui/1.10.3/themes/smoothness/jquery-ui.css" ] )
--        page.expose_js_metadata()
++        page = Page(wsgi_request)
++        page.add_js_files  ( [ "js/jquery.validate.js", "js/jquery-ui.js" ] )
++        page.add_css_files ( [ "https://code.jquery.com/ui/1.10.3/themes/smoothness/jquery-ui.css" ] )
++        page.expose_js_metadata()
  
          if method == 'POST':
              # The form has been submitted
  
              # get the domain url
--            current_site = Site.objects.get_current()
--            current_site = current_site.domain
++            current_site = Site.objects.get_current()
++            current_site = current_site.domain
              
              # getting the authority_hrn from the selected organization
              for authority in authorities:
              }
              
              # create slice_hrn based on authority_hrn and slice_name
--            slice_name = slice_request['slice_name']
++            slice_name = slice_request['slice_name']
              req_slice_hrn = authority_hrn + '.' + slice_name
              # comparing requested slice_hrn with the existing slice_hrn 
              slice_query  = Query().get('myslice:slice').select('slice_hrn','parent_authority').filter_by('parent_authority','==',authority_hrn)
  
          template_env = {
              'username': wsgi_request.user.email,
--            'topmenu_items': topmenu_items_live('Request a slice', page),
              'errors': errors,
              'slice_name': slice_name,
              'purpose': purpose,
@@@ -31,6 -31,6 +31,20 @@@ h3 
      color:#201E62;
  }
  
++input[type=text], input[type=password], input[type=email], input[type=tel], input[type=number] {
++    min-width:260px;
++    padding:6px;
++    border:1pt solid #CCCCCC;
++    vertical-align:bottom;
++    border-radius:0;
++}
++
++textarea {
++    padding:6px;
++    border:1pt solid #CCCCCC !important;
++    border-radius:0 !important;
++}
++
  div.wrapper {
      width:980px;
      margin:0 auto;
@@@ -187,36 -210,7 +210,8 @@@ var myslice = 
          }
  
        },
-       loadProjects: function(fn) {
-           var u = localStorage.getItem('user');
-           if (u !== 'undefined') {
-             var user = JSON.parse(u);
-             var projects = localStorage.getItem('projects');
-             if($.isEmptyObject(projects)){
-                 if($.isEmptyObject(user) || $.isEmptyObject(user.parent_authority)){
-                       $.post("/rest/myslice:user/",{'filters':{'user_hrn':'$user_hrn'},'fields':['parent_authority']}, function( data ) {
-                         parent_authority = data[0].parent_authority;
-     
-                     });
-                 }else{
-                     parent_authority = user.parent_authority;
-                 }
-                 // REGISTRY ONLY TO BE REMOVED WITH MANIFOLD-V2
-                 $.post("/rest/myslice:authority/",{'fields':['authority_hrn'],'filters':{'authority_hrn':'CONTAINS'+parent_authority}}, function( data ) {
-                     localStorage.setItem('projects', JSON.stringify(data));
-                     if(isFunction(fn)){
-                         fn();
-                     }
-                 });
-             }else{
-                 if(isFunction(fn)){
-                     fn();
-                 }
-             }
-         }
  
-       },
 +
      getSlices: function(name) {
        
      },
@@@ -4,7 -4,7 +4,7 @@@
        <li><a href="/slice/{{ slice }}#testbeds">Testbeds</a></li>
        <li class="active"><a class="link" href="/resources/{{ slice }}">Resources</a></li>
        <li><a href="/slice/{{ slice }}#users">Users</a></li>
--      <!--<li><a href="/slice/{{ slice }}#statistics">Statistics</a></li> -->
++      <li><a href="/slice/{{ slice }}#statistics">Statistics</a></li>
        <li><a href="/slice/{{ slice }}#measurements">Measurements</a></li>
        <li><a href="/slice/{{ slice }}#experiment" data-toggle="tab">Experiment</a></li>
        <li><a href="/slice/{{ slice }}#sla">SLA</a></li>
@@@ -15,7 -15,7 +15,7 @@@
        <li class="testbeds"><a href="#testbeds">Testbeds</a></li>
        <li><a class="link" href="/resources/{{ slice }}">Resources</a></li>
        <li class="users"><a href="#users">Users</a></li>
--<!--  <li class="statistics"><a href="#statistics">Statistics</a></li> -->
++      <li class="statistics"><a href="#statistics">Statistics</a></li>
        <li class="measurements"><a href="#measurements">Measurements</a></li>
        <li class="experiment"><a href="#experiment" data-toggle="tab">Experiment</a></li>
        <li class="sla"><a href="#sla" data-toggle="tab">SLA</a></li>
  {% load i18n %}
  
  {% block content %}
--      <div class="row">
--              <div class="col-md-12">
--                       <div class="breadcrumbs">
--                               Experiment &nbsp;>&nbsp; Request a new Project or Join an existing one
--                       </div>
--              </div>
--      </div>
++<br />
++<div class="row">
++    <div class="col-md-12">
++        <ul class="nav nav-tabs nav-section">
++            <li class="active"><a href="#existing">Join existing Project</a></li>
++            <li><a href="#new">Create new Project</a></li>
++            
++        </ul>
++    </div>
++</div>
  
--      {% if errors %}
--      <div class="row">
--              <div class="col-md-12">
--              <ul class="error">
--                {% for error in errors %}
--                <li>{{ error }}</li>
--                {% endfor %}
--              </ul>
--              </div>
--      </div>
--      {% endif %}
--      
--      <div class="row">
--              <div class="col-md-8 el">
--                      <form role="form" method="post">
--                      {% csrf_token %}
--                        <div class="form-group" style="display:none">
--                          <input type="email" class="form-control" id="email" style="width:300px" value="{{ email }}" readonly="readonly">
--                        </div>
--                        <div class="form-group">
--                              <select id="org_name" name="org_name" class="form-control" style="width:590px" value="{{ organization }}" required> 
--                {% if authorities %}
--                    {% for authority in authorities %}
--                        {% if authority.name %}
--                            <option value="{{ authority.authority_hrn }}">{{authority.name}}</option>
--                        {% else %}
--                            <option value="{{ authority.authority_hrn }}">{{authority.authority_hrn}}</option>
--                        {% endif %}
--                    {% endfor %} 
--                {% endif %}
--                </select>
--                        </div>
--                        <div class="form-group">
--                <input type="text">New Project</input>
--                        </div>
--                        <div class="form-group">
--                <input type="text">Existing Project</input>
--                        </div>
--                        <div class="form-group">
--                              <textarea id="purpose" name="purpose" class="form-control" rows="6" placeholder="Project purpose" style="width:300px" 
--                              title="Purpose of your project (informative)" required="required">{{ purpose }}</textarea>
--                        </div>
--                        {%if 'is_pi'  in pi %}        
--                        <button type="submit" id=submit_pi class="btn btn-onelab"><span class="glyphicon glyphicon-plus"></span> Create slice</button>
--                        {%else%}
--                        <button type="submit" class="btn btn-onelab"><span class="glyphicon glyphicon-plus"></span> Request slice</button>
--                        {%endif%}     
--                      </form>
--      
--              </div>
--      </div>
++{% if errors %}
++<div class="row">
++    <div class="col-md-12">
++    <ul class="error">
++      {% for error in errors %}
++      <li>{{ error }}</li>
++      {% endfor %}
++    </ul>
++    </div>
++</div>
++{% endif %}
++
++<div class="container tab-content">
++    
++      <div class="tab-pane active" id="existing"> 
++        <div class="row">
++            <div class="col-md-6">
++                 <h3>Join an existing Project</h3>
++            </div>
++            <div class="col-md-6">
++                 <h3>List of projects you are part of</h3>
++            </div>
++        </div>
++        <div class="row">
++            <div class="col-md-6">
++                <form role="form" method="post">
++                {% csrf_token %}
++                <select id="projects"></select> <button type="submit" class="btn">Join</button>
++                </form>
++            </div>
++            <div class="col-md-6">
++                <table class="table project-list">
++                    {% for pending in pending_projects %}
++                    <tr><td>(PENDING) {{ pending.project_name }}</td><td>{{ pending.authority_hrn }}</td><td>{{ pending.created|date:"d/m/Y" }}</td></tr>
++                    {% endfor %}
++                </table>
++            </div>
++        </div>
++    </div>
++    
++    <div class="tab-pane" id="new"> 
++        <div class="row">
++            <div class="col-md-12">
++                 <h3>Create a new Project</h3>
++            </div>
++        </div>
++    
++        
++        <div class="row">
++            <div class="col-md-12">
++                <form role="form" method="post" action="/portal/project_request">
++                {% csrf_token %}
++                  <div class="form-group">
++                    <input type="text" name="project_name" value="" placeholder="Name" required>
++                  </div>
++                  <div class="form-group">
++                    <select id="org_name" name="authority_name" class="form-control" style="width:590px" value="{{ organization }}" required> 
++                    {% if authorities %}
++                        {% for authority in authorities %}
++                            {% if authority.name %}
++                                <option value="{{ authority.authority_hrn }}">{{authority.name}}</option>
++                            {% else %}
++                                <option value="{{ authority.authority_hrn }}">{{authority.authority_hrn}}</option>
++                            {% endif %}
++                        {% endfor %} 
++                    {% endif %}
++                    </select>
++                  </div>
++                  
++                  
++                  <div class="form-group">
++                    <textarea id="purpose" name="purpose" class="form-control" rows="6" placeholder="Description" style="width:300px" title="Purpose of your project (informative)" required="required"></textarea>
++                  </div>
++                  <button type="submit" class="btn btn-onelab"><span class="glyphicon glyphicon-plus"></span> Send Request</button>
++                </form>
++        
++            </div>
++        </div>
++    </div>
++    
++</div>
                
  <script>
--jQuery(document).ready(function(){
++$(document).ready(function() {
++    var myprojects = localStorage.getItem('projects');
++    console.log(myprojects);
++    if (myprojects) {
++        
++    } else {
++        $('.project-list').html('<tr><td>no projetcs</td></tr>');
++    }
++    
++    $('.nav-tabs a').click(function (e) {
++        e.preventDefault();
++        $(this).tab('show');
++    });
++    $.post("/rest/myslice:authority/",{'fields':['authority_hrn','pi_users'],'filters':{'authority_hrn':'CONTAINS{{ authority_hrn }}' }}, function( data ) {
++       
++        var projects = [];
++        project_row = "<option value=''> - </option>";
++        projects.push(project_row);
++       
++        $.each( data, function( key, val ) {
++            console.log(val);
++            project_row = "<option value='"+val.authority_hrn+"'>"+val.authority_hrn+"</option>";
++            projects.push(project_row);
++        });
++        $("#projects").html(projects.join( "" ));
++    });
  /*
        
        $("#authority_hrn").load("/rest/user/", {"fields" : ["parent_authority"], "filters": {"user_hrn": "{{ user_hrn }}"}}, function(data) {
                localStorage.clear();
        });
        // auto-complete the form
--    jQuery("#org_name").combobox();
++    //jQuery("#org_name").combobox();
  
  });
  </script>
                  <b>{{request.first_name}} {{request.last_name}}</b> &lt;<a href="mailto:{{request.email}}">{{request.email}}</a>&gt;
              {% elif request.type == 'slice' %}
              <b>{{request.slice_name}}</b> -- Number of nodes: {{request.number_of_nodes}} -- Type of nodes: {{request.type_of_nodes}} -- Purpose: {{request.purpose}}
++            {% elif request.type == 'project' %}
++            <b>{{request.project_name}}</b>  -- {{ request.user_hrn }} -- Purpose: {{request.purpose}}
              {% else %}
              <b>{{request.site_name}}</b> ({{request.site_authority}}) -- {{request.address_city}}, {{request.address_country}}
              {% endif %}
                {% else %}
                    {% if request.type == 'slice' %}
                Slice name: {{request.slice_name}} -- Number of nodes: {{request.number_of_nodes}} -- Type of nodes: {{request.type_of_nodes}} -- Purpose: {{request.purpose}}
++                 {% elif request.type == 'project' %}
++            <b>{{request.project_name}}</b>  -- {{ request.user_hrn }} -- Purpose: {{request.purpose}}   
                    {% else %} {# authority #}
                Authority name: {{request.site_name}} -- authority_hrn: {{request.site_authority}} -- City: {{request.address_city}} -- Country: {{request.address_country}}
                    {% endif %}
                        {% else %}
                            {% if request.type == 'slice' %}
                        Slice name: {{request.slice_name}} -- Number of nodes: {{request.number_of_nodes}} -- Type of nodes: {{request.type_of_nodes}} -- Purpose: {{request.purpose}}
++                          {% elif request.type == 'project' %}
++                    <b>{{request.project_name}}</b>  -- {{ request.user_hrn }} -- Purpose: {{request.purpose}}
                            {% else %} {# authority #}
                        Authority name: {{request.site_name}} -- authority_hrn: {{request.site_authority}} -- City: {{request.address_city}} -- Country: {{request.address_country}}
                            {% endif %}
@@@ -54,9 -54,9 +54,9 @@@ $(document).ready(function() 
                        <ul class="nav nav-tabs">
                          <li class="active"><a href="#resourcelist" role="tab" data-toggle="tab">Table</a></li>
                          <li> <a href="#resourcemap" role="tab" data-toggle="tab">Map</a></li>
--              <li> <a href="#openflowcontroller" role="tab" data-toggle="tab">OpenFlow Controller</a></li>
++              <!-- <li> <a href="#openflowcontroller" role="tab" data-toggle="tab">OpenFlow Controller</a></li>
                <li> <a href="#resourceflowspace" role="tab" data-toggle="tab">Flowspace</a></li>
--                        <li> <a href="#resourcescheduler" role="tab" data-toggle="tab">Scheduler</a></li>
++                        <li> <a href="#resourcescheduler" role="tab" data-toggle="tab">Scheduler</a></li> -->
                        </ul>
                        </div>
                </div>