var query, data;
query = query_ext.query;
-
- var testbeds_with_sla = localStorage.getItem("sla_testbeds").split(",");
-
+ var testbeds_with_sla = Array();
+ if(localStorage.getItem("sla_testbeds")!=null){
+ testbeds_with_sla = localStorage.getItem("sla_testbeds").split(",");
+ }
switch(query.object) {
case 'resource':
import portal.resources
import portal.slicetabexperiment
+import portal.slicetabcloud
import portal.slicetabinfo
import portal.slicetabtestbeds
import portal.slicetabusers
(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'),
'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
errors = []
slice_name =''
- purpose=''
- url=''
+ #purpose=''
+ #url=''
authority_hrn = None
authority_name = None
# Retrieve the list of authorities
'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
}
- 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):
'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,
--- /dev/null
+# 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))
+
Copyrights © 2015 UPMC Sorbonne Universités. All rights reserved.
</div>
<div class="col-md-3 copy">
- powerd by <a href="http://myslice.info" target="_blank"><img src="//myslice.info/images/logo.png" style="width:50px;"></a>
+ powered by <a href="http://myslice.info" target="_blank"><img src="//myslice.info/images/logo.png" style="width:50px;"></a>
<a href="/portal/release_notes" id="portal_version"></a>
</div>
</div>
{% 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>
--- /dev/null
+{% 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;'> </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">
+ <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"> </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 %}
</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>
+-->
<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">
</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>
import json
import ConfigParser
import datetime
-from time import mktime
+from time import mktime
+import time
import xmltodict
-from django.shortcuts import render_to_response
-from django.http import HttpResponse
+from django.shortcuts import render_to_response
+from django.http import HttpResponse,QueryDict
-from sfa.trust.certificate import Keypair, Certificate
-from sfa.client.sfaserverproxy import SfaServerProxy
-from sfa.client.return_value import ReturnValue
-from sfa.util.xrn import Xrn, get_leaf, get_authority, hrn_to_urn, urn_to_hrn
+from sfa.trust.certificate import Keypair, Certificate
+from sfa.client.sfaserverproxy import SfaServerProxy
+from manifold.gateways.sfa.proxy import SFAProxy
+from sfa.client.return_value import ReturnValue
+from sfa.util.xrn import Xrn, get_leaf, get_authority, hrn_to_urn, urn_to_hrn
-from manifold.core.query import Query
+from manifold.core.query import Query
-from manifoldapi.manifoldapi import execute_admin_query
+from manifoldapi.manifoldapi import execute_admin_query
-from unfold.loginrequired import LoginRequiredView
+from unfold.loginrequired import LoginRequiredView
-from myslice.settings import logger, config
+from myslice.settings import logger, config
-from rest.json_encoder import MyEncoder
+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 = ''
- urn = ''
- object_type = ''
- rspec = ''
+ hrn = None
+ urn = None
+ object_type = None
+ rspec = None
+ output_format = None
recursive = False
- options = dict()
- platforms = list()
+ # Have to be hashable for lru_cache
+ options = frozenset() # dict()
+ platforms = frozenset() # list()
results = dict()
display = None
elif request.method == 'GET':
req_items = request.GET
- for el in req_items.items():
- if el[0].startswith('rspec'):
- rspec += el[1]
- elif el[0].startswith('platform'):
- platforms = req_items.getlist('platform[]')
- #elif el[0].startswith('options'):
- # options += 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)
- results = sfa_client(request, method, hrn=hrn, urn=urn, object_type=object_type, recursive=recursive, options=options, platforms=platforms)
+ 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=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})
else:
return accounts[0]
-def sfa_client(request, method, hrn=None, urn=None, object_type=None, rspec=None, recursive=None, options=None, platforms=None, admin=False):
+#@lru_cache(100)
+def sfa_client(request, method, hrn=None, urn=None, object_type=None, rspec=None, recursive=False, options=None, platforms=None, output_format=None, admin=False):
Config = ConfigParser.ConfigParser()
monitor_file = os.path.abspath(os.path.dirname(__file__) + '/../myslice/monitor.ini')
object_type = ''
if rspec is None:
rspec = ''
+ else:
+ logger.debug("RSPEC = %s" % rspec)
if recursive is None:
recursive = False
if options is None:
data = []
columns = []
api_options = {}
- api_options['geni_rspec_version'] = {'type': 'GENI', 'version': '3'}
api_options['list_leases'] = 'all'
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']
return {'error' : '-2'}
server = SfaServerProxy(server_url, pkey, cert)
+ #server = SFAProxy(server_url, pkey, cert)
+ if 'geni_rspec_version' in options:
+ # GetVersion to know if the AM supports the requested version
+ # if not ask for the default GENI v3
+ start_time = time.time()
+ result = server.GetVersion()
+ logger.debug("EXEC TIME - GetVersion() - %s sec." % (time.time() - start_time))
+ if 'geni_ad_rspec_versions' in result['value']:
+ for v in result['value']['geni_ad_rspec_versions']:
+ if v['type'] == options['geni_rspec_version']:
+ api_options['geni_rspec_version'] = {'type': options['geni_rspec_version']}
+ break
+ else:
+ api_options['geni_rspec_version'] = {'type': 'GENI', 'version': '3'}
+ else:
+ api_options['geni_rspec_version'] = {'type': 'GENI', 'version': '3'}
try:
# Get user config from Manifold
user_config = get_user_config(request, user_email, pf)
if 'delegated_user_credential' in user_config:
+ logger.debug('delegated_user_credential')
user_cred = user_config['delegated_user_credential']
elif 'user_credential' in user_config:
+ logger.debug('user_credential')
user_cred = user_config['user_credential']
else:
logger.error("no user credentials for user = ", user_email)
if object_type:
if 'delegated_%s_credentials'%object_type in user_config:
+ logger.debug('delegated_%s_credentials'%object_type)
for obj_name, cred in user_config['delegated_%s_credentials'%object_type].items():
if obj_name == hrn:
object_cred = cred
elif '%s_credentials'%object_type in user_config:
+ logger.debug('%s_credentials'%object_type)
for obj_name, cred in user_config['%s_credentials'%object_type].items():
if obj_name == hrn:
object_cred = cred
# Both AM & Registry
if method == "GetVersion":
+ start_time = time.time()
result = server.GetVersion()
+ logger.debug("EXEC TIME - GetVersion() - %s sec." % (time.time() - start_time))
else:
# AM API Calls
if server_am:
if method == "ListResources":
+ logger.debug(api_options)
+ #logger.debug(user_cred)
+ start_time = time.time()
result = server.ListResources([user_cred], api_options)
- logger.debug(result)
+ logger.debug("EXEC TIME - ListResources() - %s sec." % (time.time() - start_time))
+ #logger.debug(result)
dict_result = xmltodict.parse(result['value'])
result['parsed'] = dict_result
if isinstance(dict_result['rspec']['node'], list):
columns.extend(dict_result['rspec']['node'].keys())
elif method == "Describe":
+ start_time = time.time()
version = server.GetVersion()
+ logger.debug("EXEC TIME - GetVersion() - %s sec." % (time.time() - start_time))
logger.debug(version['geni_api'])
# if GetVersion = v2
if version['geni_api'] == 2:
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)
#return HttpResponse(json.dumps({'error' : '-3','msg':'method not supported by Registry'}), content_type="application/json")
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
+ start_time = time.time()
+ result = translate(result['value'],output_format)
+ logger.debug("EXEC TIME - translate() - %s sec." % (time.time() - start_time))
results[pf] = result
if dict_result:
import traceback
logger.error(traceback.format_exc())
logger.error(e)
- results[pf] = {'error':'-3', 'error_msg': str(e)}
+ results[pf] = {'error':'-3', 'result':result,'error_msg': str(e)}
results['columns'] = columns
return results
+@lru_cache(100)
+def translate(rspec, output_format):
+ import urllib
+ import urllib2
+
+ values = {'content' : rspec}
+ url = 'https://demo.fiteagle.org/omnweb/convert/to/' + output_format
+ data = urllib.urlencode(values)
+ req = urllib2.Request(url, data)
+ 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 {}