From: Loic Baron <loic.baron@lip6.fr> Date: Wed, 4 Nov 2015 11:30:24 +0000 (+0100) Subject: Plugin Cloud wip X-Git-Url: http://git.onelab.eu/?a=commitdiff_plain;h=4a034c2a5701c9fbb38da8670d25d7ebe8f339ac;p=myslice.git Plugin Cloud wip --- diff --git a/myslice/urls.py b/myslice/urls.py index 61f779f3..b2e88bb6 100644 --- a/myslice/urls.py +++ b/myslice/urls.py @@ -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'), diff --git a/portal/slicetabcloud.py b/portal/slicetabcloud.py new file mode 100644 index 00000000..5526a187 --- /dev/null +++ b/portal/slicetabcloud.py @@ -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 FreeAccessView + +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 (FreeAccessView, 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)) + diff --git a/portal/templates/slice-tab-cloud.html b/portal/templates/slice-tab-cloud.html new file mode 100644 index 00000000..913b6ddc --- /dev/null +++ b/portal/templates/slice-tab-cloud.html @@ -0,0 +1,244 @@ +{% extends "layout_wide.html" %} + +{% block head %} +<script type="text/javascript"> + +var global_list = {}; + +/* 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:white;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(); + $("[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 */ + toogle_div(platform, this.value, 'flavor'); + /* 3) Disable Images, Enable only compatible ones in selectImage */ + console.log(this.value); + console.log(global_list[platform][this.value]); + $("#"+platform+"_selectImage option[value=0]").prop('selected', true); + $("[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); + }); + } + 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); + 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"]); + 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","50%"); + //$("#"+platform+"_selectImage").css("width","50%"); +} +function is_finished(len_platforms, pf_status){ + if(len_platforms == pf_status){ + return true; + }else{ + return false; + } +} +function send_delete(platform, sliver_name){ + jQuery('#'+platform+'_vm').val(sliver_name); + jQuery('#'+platform+'_form_delete').submit(); +} +function render_node(platform, node){ + if('openstack:sliver' in node){ + sliver = node['openstack:sliver'] + var d = platform+'_existing_'+sliver['@sliver_name']; + d = d.replace(/ /g, ''); + id = d.replace( /(:|\.|\[|\])/g, "\\$1" ); + $("#"+platform+"_existing").append("<div id='"+platform+'_existing_'+sliver['@sliver_name']+"' class='row'></div>"); + //$("#"+id).append("<input type='hidden' name='"+platform+"_"+sliver['@sliver_name']+"' value='"+sliver['@sliver_name']+"'>"); + $("#"+id).append("<div class='col-md-2' style='margin-left:15px;'>"+sliver['@sliver_name']+"</div>"); + $("#"+id).append("<div class='col-md-4'>"+sliver['openstack:flavor']['@name']+"</div>"); + $("#"+id).append("<div class='col-md-4'>"+sliver['openstack:flavor']['openstack:image']['@name']+"</div>"); + $("#"+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>"); + /* + sliver['openstack:address'] + sliver['openstack:flavor'] + */ + } +} + +$(document).ready(function() { + var data = Array(); + var platform_status = Array(); + var platform_empty = Array(); +{% for platform in platforms %} + console.log('{{platform}}'); + {% if platform in cloud_platforms %} + $.post("/sfa/Describe",{'hrn':'{{slicename}}', 'type':'slice', 'platform':['{{platform}}']}, function( data ) { + console.log(data); + if('parsed' in data['{{platform}}'] && 'rspec' in data['{{platform}}']['parsed']){ + rspec = data['{{platform}}']['parsed']['rspec']; + if('node' in rspec){ + if(rspec['node'] instanceof Array) { + jQuery.each( rspec['node'], function( i, node ) { + render_node('{{platform}}',node); + }); + }else{ + render_node('{{platform}}',rspec['node']); + } + } + } + }); + $.post("/sfa/ListResources",{'platform':['{{platform}}']}, function( d ) { + $.extend(data,d); + console.log(data); + if('parsed' in data['{{platform}}'] && 'rspec' in data['{{platform}}']['parsed']){ + rspec = data['{{platform}}']['parsed']['rspec']; + if('node' in rspec){ + if(rspec['node'] instanceof Array) { + jQuery.each( rspec['node'], function( i, node ) { + render_cloud('{{platform}}',node); + }); + }else{ + render_cloud('{{platform}}',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(); + } + } + }); + + {% endif %} +{% endfor %} +}); +</script> +{% endblock %} + +{% block content %} +{{post_values}} +{% for platform in platforms %} + {% if platform in cloud_platforms %} + <div style="padding-left:20px;padding-top:20px;padding-right:20px;padding-bottom:20px;border-style:solid;border-width:1px;width:700px;"> + <h2>{{ platform }}</h2> + <form id="{{platform}}_form_add" method="post"> + {% csrf_token %} + <div id="{{platform}}_input" class="row"> + <div class="col-md-1"> + <input type="text" maxlength="2" id="{{platform}}_number" name="{{platform}}_number" style="width:2.2em;min-width:2.2em;"> + </div> + <div id="{{platform}}_select" class="col-md-11"></div> + </div> + <div id="{{platform}}_add" class="row" style="display:none;"> + <div class="col-md-1" style="padding-top:50px;"> + <input type="hidden" name="action" id="action" value="add"> + <input type="hidden" name="platform" id="platform" value="{{platform}}"> + <input type="submit" form="{{platform}}_form_add" value="Add" onclick="this.form.submit();"> + </div> + </div> + </form> + <br> + // display only if VMs already in slice + <form id="{{platform}}_form_delete" method="post"> + {% csrf_token %} + <div id="{{platform}}_existing" class="row"> + <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> + <br> + // display only pending changes + <br> + <form id="{{platform}}_form_reserve" method="post"> + {% csrf_token %} + <div id="{{platform}}_pending" class="row"></div> + <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="Reserve" onclick="this.form.submit();"> + </form> + </div> + {% endif %} +{% endfor %} +{% endblock %}