1 {% extends "layout_wide.html" %}
2 {% load portal_filters %}
8 background-color: #999999;
13 <script type="text/javascript">
17 var ad_rspec = Object();
18 var request_rspec = Object();
19 var manifest_rspec = Object();
20 var deleted_nodes = {};
22 var len_platforms = {{len_platforms}};
25 var key_slivername = '';
28 /* render_flavor & render_image */
29 function render_option(obj){
30 var option = document.createElement("option");
31 if(obj instanceof Object){
32 obj_name = obj["@name"];
36 option.text = obj_name;
37 option.value = obj_name;
40 function render_description(platform, obj, type, node_name){
41 if($('#'+platform+'_'+type).length==0){
42 $('#'+platform+'_add_'+node_name).append("<div id='"+platform+"_"+type+"'>");
44 if(obj instanceof Array){
45 obj_name = obj["@name"];
49 var d = platform+'_'+type+'_'+obj_name;
50 d = d.replace(/ /g, '');
51 id = d.replace( /(:|\.|\[|\])/g, "\\$1" );
52 if($('#'+id).length==0){
53 $('#'+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>");
55 if($('#'+id+' div').length==0){
56 if(obj instanceof Array){
57 jQuery.each(obj, function(key,val){
58 if (key != 'openstack:image' && key != 'disk_image'){
59 $('#'+id).append("<div>"+key.replace('@','')+": "+val+"</div>");
67 function toogle_div(platform, value, type, node_name){
68 $("#"+platform+"_add_"+node_name).show();
69 if ( $("#"+platform+"_selectImage_"+node_name).length ) {
70 // show the add button only if image is selected
71 if($("#"+platform+"_selectImage_"+node_name).val()!=null && $("#"+platform+"_selectImage").val()!=0 && value!=0){
72 $("#"+platform+"_add_button_"+node_name).show();
74 $("#"+platform+"_add_button_"+node_name).hide();
77 $("#"+platform+"_add_button_"+node_name).show();
79 $("[id^='"+platform+"_"+type+"_"+"']").hide();
80 d = platform+'_'+type+'_'+value;
81 d = d.replace(/ /g, '');
82 id = d.replace( /(:|\.|\[|\])/g, "\\$1" );
85 function render_cloud(platform, node){
87 if ('@component_name' in node){
88 node_name = node['@component_name']
90 node_name = node['@component_id'].split('+').pop();
92 elm = document.getElementById(platform+'_select_'+node_name);
93 //newElement = document.createElement('p');
94 //elm.appendChild(newElement);
95 global_list[platform][node_name]={};
96 if('openstack:sliver' in node){
97 key_sliver = 'openstack:sliver';
98 key_slivername = '@sliver_name';
99 }else if('sliver_type' in node){
100 key_sliver = 'sliver_type';
101 key_slivername = '@name';
103 if (key_sliver != ''){
104 selectFlavor = document.createElement('select');
105 selectFlavor.id = platform+"_selectFlavor_-_"+node_name;
106 selectFlavor.name = platform+"_selectFlavor_-_"+node_name;
107 selectFlavor.onchange = function(){
108 /* 1) Display corresponding Flavor div - hide others - reset selectImage value */
109 name = this.id.split("_-_").pop();
110 toogle_div(platform, this.value, 'flavor', name);
111 if ( $("#"+platform+"_selectImage_"+name).length ) {
112 $("#"+platform+"_selectImage_"+name+" option[value=0]").prop('selected', true);
113 /* 3) Disable Images, Enable only compatible ones in selectImage */
114 $("[id^='"+platform+"_image_"+name+"']").hide();
115 $("#"+platform+"_selectImage_"+name+" option").attr("disabled",true);
116 $.each(global_list[platform][name][this.value], function (i,v){
117 $("#"+platform+"_selectImage_"+name+" option[value='" + v + "']").attr("disabled",false);
119 $("#"+platform+"_selectImage_"+name).attr("disabled",false);
122 var option = document.createElement("option");
123 option.text = "-- select a flavor --";
125 selectFlavor.appendChild(option);
126 jQuery.each( node[key_sliver], function( i, sliver ) {
127 flavor = get_flavor(sliver);
128 f = render_option(flavor);
129 selectFlavor.appendChild(f);
130 /* 1) create hidden div to explain caracteristics of the flavor */
131 render_description(platform, flavor, 'flavor', node_name);
132 if(flavor instanceof Object){
133 flavor_name = flavor['@name'];
135 flavor_name = flavor;
137 global_list[platform][node_name][flavor_name]=[];
138 if(flavor instanceof Object){
139 if ("openstack:image" in flavor){
140 images = flavor['openstack:image'];
141 key_image = 'openstack:image';
142 }else if("disk_image" in flavor){
143 images = flavor['disk_image'];
144 key_image = 'disk_image';
152 selectImage = document.createElement('select');
153 selectImage.id = platform+"_selectImage_"+node_name;
154 selectImage.name = platform+"_selectImage_"+node_name;
155 selectImage.onchange = function(){
156 /* 2) display corresponding Image div - hide others */
157 toogle_div(platform, this.value, 'image', node_name);
159 var option = document.createElement("option");
160 option.text = "-- select an image --";
162 selectImage.appendChild(option);
163 if(images instanceof Array){
164 jQuery.each( images, function( i, img ) {
165 image = render_option(img);
166 image.disabled = true;
167 selectImage.appendChild(image);
168 /* 2) create hidden div to explain caracteristics of the image */
169 render_description(platform, img, 'image', node_name);
170 global_list[platform][node_name][flavor_name].push(img['@name']);
173 image = render_option(images);
174 image.disabled = true;
175 selectImage.appendChild(image);
176 /* 2) create hidden div to explain caracteristics of the image */
177 render_description(platform, images, 'image', node_name);
178 global_list[platform][node_name][flavor_name].push(images['@name']);
182 elm.appendChild(selectFlavor);
184 elm.appendChild(selectImage);
187 $("#"+platform+"_selectFlavor_-_"+node_name).css("width","100px");
188 $("#"+platform+"_selectFlavor_-_"+node_name).css("height","30px");
190 $("#"+platform+"_selectImage_"+node_name).css("width","100px");
191 $("#"+platform+"_selectImage_"+node_name).css("height","30px");
194 function get_flavor(sliver){
195 if(typeof sliver === 'string' || sliver instanceof String){
197 } else if('openstack:flavor' in sliver){
198 return sliver['openstack:flavor'];
203 function is_finished(len_platforms, pf_status){
204 if(len_platforms == pf_status){
210 function sliver_name_exists(sliver_name){
211 if(sliver_name in added_nodes){
215 if (sliver_name in deleted_nodes){
221 function find_sliver_name(sliver_name, num){
222 for (j=Object.keys(added_nodes).length; j<Object.keys(added_nodes).length+num; i++){
223 vm_name = sliver_name+'_'+j;
224 if(!sliver_name_exists(vm_name)){
230 function send_add(platform, node_name){
231 $('#'+platform+'_pending_add').show();
232 sliver_name = $('#'+platform+'_sliver_name_'+node_name).val();
233 sliver_name = sliver_name.replace(' ','_');
234 flavor_name = $('#'+platform+'_selectFlavor_-_'+node_name).val();
235 image_name = $('#'+platform+'_selectImage_'+node_name).val();
237 num = $('#'+platform+'_number_'+node_name).val();
239 for (i = 0; i < num; i++){
240 // XXX Check if the name already exist in existing VMs and added_nodes
241 vm_name = sliver_name+"_"+i;
242 if (sliver_name_exists(vm_name)){
243 vm_name = find_sliver_name(sliver_name, num);
245 node = get_node(vm_name, flavor_name, image_name, node_name);
246 add_to_request_rspec(node);
247 render_node(platform, node, 'pending_add');
248 added_nodes[vm_name]=node;
251 if (sliver_name_exists(sliver_name)){
252 sliver_name = find_sliver_name(sliver_name, num);
254 node = get_node(sliver_name, flavor_name, image_name, node_name);
255 add_to_request_rspec(node);
256 render_node(platform, node, 'pending_add');
257 added_nodes[sliver_name]=node;
259 toogle_div(platform, flavor_name, 'flavor', node_name);
260 toogle_div(platform, image_name, 'image', node_name);
261 flavor_name = $('#'+platform+'_selectFlavor_-_'+node_name).val(0);
262 image_name = $('#'+platform+'_selectImage_'+node_name).val(0);
263 $('#'+platform+'_add_'+node_name).hide();
264 $('#'+platform+'_add_button_'+node_name).hide();
265 $('#'+platform+'_div_pending').show();
266 console.log(request_rspec);
267 //jQuery('#'+platform+'_form_delete').submit();
269 function get_node(vm_name, flavor_name, image_name, node_name){
271 if(ad_rspec['rspec']['node'] instanceof Array) {
272 // Deep copy of the Array to avoid reference
274 jQuery.each(ad_rspec['rspec']['node'], function(x, n){
275 if(n['@component_name']==node_name){
280 node = jQuery.extend(true, {}, ad_rspec['rspec']['node'][i]);
282 // Deep copy of the Array to avoid reference
283 node = jQuery.extend(true, {}, ad_rspec['rspec']['node']);
285 if(node[key_sliver] instanceof Array) {
286 node[key_sliver] = node[key_sliver][0];
288 node[key_sliver][key_slivername] = vm_name;
289 node["@client_id"] = vm_name;
290 console.log(vm_name);
294 if('openstack:flavor' in node[key_sliver]){
295 flavor = {'@name':flavor_name,'openstack:image':{'@name':image_name}};
296 node[key_sliver]['openstack:flavor']=flavor;
298 if(typeof image_name === "undefined"){
299 flavor = {'@name':flavor_name};
301 flavor = {'@name':flavor_name,'disk_image':{'@name':image_name}};
303 node[key_sliver]=flavor;
306 if('openstack:security_group' in node[key_sliver]){
307 $.each(node[key_sliver]['openstack:security_group'], function(i, group){
308 if(group['@name']=='default'){
309 node[key_sliver]['openstack:security_group'] = group;
316 function send_delete(platform, sliver_name){
317 $('#'+platform+'_pending_delete').show();
318 jQuery('#'+platform+'_vm').val(sliver_name);
319 jQuery('#'+platform+'_existing_'+sliver_name).hide();
320 node = remove_node_from_request_rspec(sliver_name);
321 deleted_nodes[sliver_name]=node;
322 render_node(platform, node, 'pending_delete');
323 $('#'+platform+'_div_pending').show();
324 console.log(request_rspec);
326 function add_to_request_rspec(node){
327 if(request_rspec['rspec']['node'] instanceof Array) {
328 request_rspec['rspec']['node'].push(node);
330 n = request_rspec['rspec']['node'];
331 request_rspec['rspec']['node'] = Array();
332 request_rspec['rspec']['node'].push(n);
333 request_rspec['rspec']['node'].push(node);
336 function remove_node_from_request_rspec(sliver_name){
337 var save_node = Array();
338 jQuery.each( request_rspec['rspec']['node'], function( i, node ) {
339 if(node[key_sliver][key_slivername]==sliver_name){
340 request_rspec['rspec']['node'].splice(i,1);
347 function cancel_add(platform,sliver_name){
348 // remove the canceled node from the pending list
349 $('#'+platform+'_pending_add_'+sliver_name).remove();
350 // remove the canceled node from the request rspec
351 node = remove_node_from_request_rspec(sliver_name);
352 delete added_nodes[sliver_name];
353 // hide the pending div if there are no more nodes
354 if ($('#'+platform+'_pending_add div').length==0){
355 $('#'+platform+'_pending_add').hide();
356 if ($('#'+platform+'_pending_delete div').length==0){
357 $('#'+platform+'_div_pending').hide();
358 $('#'+platform+'_pending_delete').hide();
362 function cancel_delete(platform,sliver_name){
363 // display the canceled node back in existing nodes
364 $('#'+platform+'_existing_'+sliver_name).show();
365 // remove the canceled node from the pending list
366 $('#'+platform+'_pending_delete_'+sliver_name).remove();
367 // Cancel the deletion of an existing node -> push it back to the request rspec
368 request_rspec['rspec']['node'].push(deleted_nodes[sliver_name]);
369 delete deleted_nodes[sliver_name];
370 // hide the pending div if there are no more nodes
371 if ($('#'+platform+'_pending_delete div').length==0){
372 $('#'+platform+'_pending_delete').hide();
373 if ($('#'+platform+'_pending_add div').length==0){
374 $('#'+platform+'_div_pending').hide();
375 $('#'+platform+'_pending_add').hide();
380 function public_ip(platform,sliver_name,is_public){
381 // XXX Change ip status in request_rspec
383 // external_ip="true"
384 node = remove_node_from_request_rspec(sliver_name);
385 node['external_ip']="true";
386 added_nodes[sliver_name]['external_ip']="true";
387 request_rspec['rspec']['node'].push(node);
389 console.log(sliver_name+' NOT public ');
390 // external_ip="false"
391 node = remove_node_from_request_rspec(sliver_name);
392 node['external_ip']="false";
393 added_nodes[sliver_name]['external_ip']="false";
394 request_rspec['rspec']['node'].push(node);
398 function render_node(platform, node, state){
399 if(key_sliver in node){
400 sliver = node[key_sliver];
401 if(sliver instanceof Array){
402 client_id = sliver['@name'];
404 if ('@sliver_name' in sliver){
405 client_id = sliver['@sliver_name'];
407 client_id = node['@client_id'];
410 if ('@component_name' in node){
411 node_name = node['@component_name']
413 node_name = node['@component_id'].split('+').pop();
416 var d = platform+'_'+state+'_'+client_id;
417 d = d.replace(/ /g, '');
418 id = d.replace( /(:|\.|\[|\])/g, "\\$1" );
419 $("#"+platform+"_"+state).append("<div id='"+platform+'_'+state+'_'+client_id+"' class='row'></div>");
420 //$("#"+id).append("<input type='hidden' name='"+platform+"_"+client_id+"' value='"+client_id+"'>");
421 if(state=='pending_add'){
422 $("#"+id).append("<div class='col-md-1' style='width:40px;margin-left:0px;!important;'><input type='checkbox' id='publicip_"+platform+"_"+client_id+"' onclick=public_ip('"+platform+"','"+client_id+"',this.checked);></div>");
424 $("#"+id).append("<div class='col-md-1' style='width:40px;margin-left:0px;!important;'> </div>");
426 $("#"+id).append("<div class='col-md-2'>"+node_name+"</div>");
427 $("#"+id).append("<div class='col-md-2'>"+client_id+"</div>");
428 if('openstack:flavor' in node[key_sliver]){
429 $("#"+id).append("<div class='col-md-2'>"+sliver['openstack:flavor']['@name']+"</div>");
430 $("#"+id).append("<div class='col-md-3'>"+sliver['openstack:flavor']['openstack:image']['@name']+"</div>");
432 $("#"+id).append("<div class='col-md-2'>"+sliver['@name']+"</div>");
433 if('disk_image' in sliver){
434 $("#"+id).append("<div class='col-md-3'>"+sliver['disk_image']['@name']+"</div>");
436 $("#"+id).append("<div class='col-md-3'> </div>");
440 if(state=='existing'){
441 $("#"+id).append("<div class='col-md-1'><input id='"+platform+"_delete_"+client_id+"' type='submit' form='"+platform+"_form_delete' value='Delete' onclick=send_delete('"+platform+"','"+client_id+"');></div>");
442 }else if(state=='pending_add'){
443 $("#"+id).append("<div class='col-md-1'><input id='"+platform+"_cancel_"+client_id+"' type='submit' form='"+platform+"_form_cancel' value='Cancel' onclick=cancel_add('"+platform+"','"+client_id+"');></div>");
444 }else if (state=='pending_delete'){
445 $("#"+id).append("<div class='col-md-1'><input id='"+platform+"_cancel_"+client_id+"' type='submit' form='"+platform+"_form_cancel' value='Cancel' onclick=cancel_delete('"+platform+"','"+client_id+"');></div>");
447 console.log("state: "+state+" not impemented");
450 sliver['openstack:address']
451 sliver['openstack:flavor']
456 function allocate(platform, slicename){
457 $("#"+platform+"_main").addClass("disabled");
458 $("#"+platform+"_wait").show();
459 $("#"+platform+"_wait").spin();
460 console.log("allocate rspec = ")
461 console.log(request_rspec);
462 console.log("allocate json = ")
463 console.log(JSON.stringify(request_rspec));
464 $.post("/sfa/Allocate",{'hrn':slicename, 'type':'slice', 'platform':[platform], 'rspec':JSON.stringify(request_rspec)}, function( result ) {
466 clear_data(platform);
467 load_data(platform,slicename);
468 $("#"+platform+"_main").removeClass("disabled");
469 $("#"+platform+"_wait").hide();
470 if('error' in result[platform]){
471 mysliceAlert('Error: '+result[platform]['error_msg'],'danger', true);
472 }else if('code' in result[platform] && result[platform]['code']['am_code']==-1){
473 mysliceAlert('Error: '+result[platform]['output'],'danger', true);
475 mysliceAlert('Success: changes applied','success', true);
479 function clear_data(platform){
480 $('#'+platform+'_existing').children().remove();
481 $('#'+platform+'_pending_delete').children().remove();
482 $('#'+platform+'_pending_delete').hide();
483 $("[id^="+platform+"_selectFlavor]").remove();
484 $("[id^="+platform+"_selectImage]").remove();
485 $('#'+platform+'_pending_add').children().remove();
486 $('#'+platform+'_pending_add').hide();
487 $('#'+platform+'_div_pending').hide();
489 function load_data(platform, slicename){
490 var platform_status = Array();
491 var platform_empty = Array();
493 $.post("/sfa/Describe",{'hrn':slicename, 'type':'slice', 'platform':[platform]}, function( d ) {
495 $("#"+platform+"_main").spin(false);
497 if('parsed' in data[platform] && 'rspec' in data[platform]['parsed']){
498 manifest_rspec = data[platform]['parsed']['rspec'];
499 request_rspec = data[platform]['parsed'];
500 request_rspec['rspec']['@type']='request';
501 if('node' in manifest_rspec){
502 if(manifest_rspec['node'] instanceof Array) {
503 jQuery.each( manifest_rspec['node'], function( i, node ) {
504 render_node(platform, node, 'existing');
507 render_node(platform, manifest_rspec['node'], 'existing');
509 $('#'+platform+'_existing').show();
512 // Let's build a default request_rspec
513 request_rspec['rspec']=Object();
514 request_rspec['rspec']['@type']='request';
515 request_rspec['rspec']['node']=Array();
518 $.post("/sfa/ListResources",{'platform':[platform]}, function( d ) {
521 global_list[platform]={};
522 if('parsed' in d[platform] && 'rspec' in d[platform]['parsed']){
523 ad_rspec = d[platform]['parsed'];
524 if('node' in ad_rspec['rspec']){
525 if(ad_rspec['rspec']['node'] instanceof Array) {
526 jQuery.each( ad_rspec['rspec']['node'], function( i, node ) {
527 render_cloud(platform,node);
530 render_cloud(platform,ad_rspec['rspec']['node']);
533 platform_empty.push(platform);
536 platform_empty.push(platform);
538 platform_status.push(platform);
539 if(is_finished(len_platforms,platform_status.length)){
540 $("#loading").hide();
541 if(platform_empty.length == len_platforms){
542 $("#warning_message").show();
547 $(document).ready(function() {
548 {% for platform in platforms %}
549 {% if platform in cloud_platforms %}
550 $("#{{platform}}_main").spin();
551 load_data('{{platform}}', '{{slicename}}');
560 {% for platform in platforms %}
561 {% if platform in cloud_platforms %}
563 <div id="{{platform}}_wait" style="display:none;margin-top:35px;position:absolute;margin-left:50%;"></div>
564 <div id="{{platform}}_main" style="padding-left:20px;padding-top:20px;padding-right:20px;padding-bottom:20px;border-style:solid;border-width:1px;">
565 <h2>{{ platform }}</h2>
566 // display only if VMs already in slice
567 <h4>VMs in slice {{slicename}}</h4>
568 <div id="{{platform}}_existing" class="row alert alert-info" style='display:none;margin-left:0px;!important;margin-right:0px;!important;'>
569 <input type="hidden" name="{{platform}}_vm" id="{{platform}}_vm">
570 <input type="hidden" name="action" id="action" value="delete">
571 <input type="hidden" name="platform" id="platform" value="{{platform}}">
573 <div id="{{platform}}_div_nodes">
574 {% for key, value in result.items %}
575 {% if key == platform %}
576 {% if value.parsed.rspec.node|get_type == 'list' %}
577 {% for node in value.parsed.rspec.node %}
578 {% for k,node_urn in node.items %}
579 {% if k == '@component_id' %}
580 {% widget '_widget-cloud-node.html' %}
585 {% for k,node_urn in value.parsed.rspec.node.items %}
586 {% if k == '@component_id' %}
587 {% widget '_widget-cloud-node.html' %}
595 <div id="{{platform}}_div_pending" style="display:none;">
596 // display only pending changes
597 <h4>Pending changes</h4>
598 <form id="{{platform}}_form_reserve" method="post">
600 <div id="{{platform}}_pending_add" class="row alert alert-success" style="display:none;margin-bottom:3px !important;margin-left:0px;!important;margin-right:0px;!important;"></div>
601 <div id="{{platform}}_pending_delete" class="row alert alert-danger" style="display:none;margin-bottom:3px !important;margin-left:0px;!important;margin-right:0px;!important;"></div>
603 <input type="hidden" name="action" id="action" value="reserve">
604 <input type="hidden" name="platform" id="platform" value="{{platform}}">
605 <input type="submit" form="{{platform}}_form_reserve" value="Apply changes" onclick="allocate('{{platform}}','{{slicename}}');">