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
# 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
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
request['purpose'] = slice.purpose
return request
+def make_request_project(project):
+ request = {}
+ request['type'] = 'project'
+ request['user_hrn'] = project.user_hrn
+ request['timestamp'] = project.created
+ request['authority_hrn'] = project.authority_hrn
+ request['project_name'] = project.project_name
+ request['purpose'] = project.purpose
+ return request
+
def make_request_authority(authority):
request = {}
request['type'] = 'authority'
request['timestamp'] = authority.created
return request
-def make_requests(pending_users, pending_slices, pending_authorities):
+def make_requests(pending_users, pending_slices, pending_authorities, pending_projects):
requests = []
for user in pending_users:
requests.append(make_request_user(user))
requests.append(make_request_slice(slice))
for authority in pending_authorities:
requests.append(make_request_authority(authority))
+ for project in pending_projects:
+ requests.append(make_request_project(project))
return requests
def get_request_by_id(ids):
pending_users = PendingUser.objects.filter(status__iexact = 'True')
pending_slices = PendingSlice.objects.all()
pending_authorities = PendingAuthority.objects.all()
+ pending_projects = PendingProject.objects.all()
+ print "$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$" , pending_projects
else:
pending_users = PendingUser.objects
pending_slices = PendingSlice.objects
pending_authorities = PendingAuthority.objects
+ pending_projects = PendingProject.objects
from django.db.models import Q
list_user_Q = list()
list_slice_Q = list()
list_auth_Q = list()
+ list_proj_Q = list()
for hrn in authority_hrns:
list_user_Q.append(Q(authority_hrn__startswith=hrn, status__iexact = 'True'))
list_slice_Q.append(Q(authority_hrn__startswith=hrn))
list_auth_Q.append(Q(site_authority__startswith=hrn))
+ list_proj_Q.append(Q(authority_hrn__startswith=hrn))
+ print "$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$" , list_proj_Q
print "startswith hrn = ",hrn
from operator import __or__ as OR
pending_users = pending_users.filter(reduce(OR, list_user_Q))
pending_slices = pending_slices.filter(reduce(OR, list_slice_Q))
pending_authorities = pending_authorities.filter(reduce(OR, list_auth_Q))
+ pending_projects = pending_projects.filter(reduce(OR, list_auth_Q))
#pending_authorities = pending_authorities.all() #filter(reduce(OR, list_Q))
- return make_requests(pending_users, pending_slices, pending_authorities)
+ return make_requests(pending_users, pending_slices, pending_authorities, pending_projects)
# XXX Is it in sync with the form fields ?
except Exception, e:
print "Failed to send email, please check the mail templates and the SMTP configuration of your server"
+
+def create_pending_project(wsgi_request, request):
+ """
+ """
+
+ # Insert an entry in the PendingProject table
+ s = PendingProject(
+ project_name = request['project_name'],
+ user_hrn = request['user_hrn'],
+ authority_hrn = request['authority_hrn'],
+ purpose = request['purpose'],
+ )
+ s.save()
+
+# try:
+# # Send an email: the recipients are the PI of the authority
+# recipients = authority_get_pi_emails(wsgi_request, request['authority_hrn'])
+#
+# theme.template_name = 'slice_request_email.txt'
+# text_content = render_to_string(theme.template, request)
+#
+# theme.template_name = 'slice_request_email.html'
+# html_content = render_to_string(theme.template, request)
+#
+# theme.template_name = 'slice_request_email_subject.txt'
+# subject = render_to_string(theme.template, request)
+# subject = subject.replace('\n', '')
+#
+# sender = email
+# msg = EmailMultiAlternatives(subject, text_content, sender, recipients)
+# msg.attach_alternative(html_content, "text/html")
+# msg.send()
+# except Exception, e:
+# print "Failed to send email, please check the mail templates and the SMTP configuration of your server"
+
+
#-------------------------------------------------------------------------------
# REQUESTS - Users
#-------------------------------------------------------------------------------
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,
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;
},
+
getSlices: function(name) {
},
<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>
<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 > 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> <<a href="mailto:{{request.email}}">{{request.email}}</a>>
{% 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 %}
<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>