1 {% extends "layout_wide.html" %}
7 background-color: #999999;
12 <script type="text/javascript">
16 var ad_rspec = Array();
17 var request_rspec = Array();
18 var manifest_rspec = Array();
19 var deleted_nodes = {};
22 var len_platforms = {{len_platforms}};
24 /* render_flavor & render_image */
25 function render_option(obj){
26 var option = document.createElement("option");
27 option.text = obj["@name"];
28 option.value = obj["@name"];
31 function render_description(platform, obj, type){
32 if($('#'+platform+'_'+type).length==0){
33 $('#'+platform+'_add').append("<div id='"+platform+"_"+type+"'>");
35 var d = platform+'_'+type+'_'+obj['@name'];
36 d = d.replace(/ /g, '');
37 id = d.replace( /(:|\.|\[|\])/g, "\\$1" );
38 if($('#'+id).length==0){
39 $('#'+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>");
41 if($('#'+id+' div').length==0){
42 jQuery.each(obj, function(key,val){
43 if (key != 'openstack:image'){
44 $('#'+id).append("<div>"+key.replace('@','')+": "+val+"</div>");
49 function toogle_div(platform, value, type){
50 $("#"+platform+"_add").show();
51 // show the add button only if image is selected
52 if($("#"+platform+"_selectImage").val()!=null && $("#"+platform+"_selectImage").val()!=0 && value!=0){
53 $("#"+platform+"_add_button").show();
55 $("#"+platform+"_add_button").hide();
57 $("[id^='"+platform+"_"+type+"_"+"']").hide();
58 d = platform+'_'+type+'_'+value;
59 d = d.replace(/ /g, '');
60 id = d.replace( /(:|\.|\[|\])/g, "\\$1" );
63 function render_cloud(platform, node){
64 elm = document.getElementById(platform+'_select');
65 //newElement = document.createElement('p');
66 //elm.appendChild(newElement);
67 global_list[platform]={};
68 if('openstack:sliver' in node){
69 selectFlavor = document.createElement('select');
70 selectFlavor.id = platform+"_selectFlavor";
71 selectFlavor.name = platform+"_selectFlavor";
72 selectFlavor.onchange = function(){
73 /* 1) Display corresponding Flavor div - hide others - reset selectImage value */
74 $("#"+platform+"_selectImage option[value=0]").prop('selected', true);
75 toogle_div(platform, this.value, 'flavor');
76 /* 3) Disable Images, Enable only compatible ones in selectImage */
77 $("[id^='"+platform+"_image_"+"']").hide();
78 $("#"+platform+"_selectImage option").attr("disabled",true);
79 $.each(global_list[platform][this.value], function (i,v){
80 $("#"+platform+"_selectImage option[value='" + v + "']").attr("disabled",false);
82 $("#"+platform+"_selectImage").attr("disabled",false);
84 var option = document.createElement("option");
85 option.text = "-- select a flavor --";
87 selectFlavor.appendChild(option);
88 jQuery.each( node['openstack:sliver'], function( i, sliver ) {
89 if('openstack:flavor' in sliver){
90 f = render_option(sliver['openstack:flavor']);
91 selectFlavor.appendChild(f);
92 flavor = sliver["openstack:flavor"];
93 /* 1) create hidden div to explain caracteristics of the flavor */
94 render_description(platform, flavor, 'flavor');
95 flavor_name = flavor['@name'];
96 global_list[platform][flavor_name]=[];
97 if ("openstack:image" in flavor){
98 selectImage = document.createElement('select');
99 selectImage.id = platform+"_selectImage";
100 selectImage.name = platform+"_selectImage";
101 selectImage.onchange = function(){
102 /* 2) display corresponding Image div - hide others */
103 toogle_div(platform, this.value, 'image');
105 var option = document.createElement("option");
106 option.text = "-- select an image --";
108 selectImage.appendChild(option);
109 if(flavor["openstack:image"] instanceof Array){
110 jQuery.each( flavor["openstack:image"], function( i, img ) {
111 image = render_option(img);
112 image.disabled = true;
113 selectImage.appendChild(image);
114 /* 2) create hidden div to explain caracteristics of the image */
115 render_description(platform, img, 'image');
116 global_list[platform][flavor_name].push(img['@name']);
119 image = render_option(flavor["openstack:image"]);
120 image.disabled = true;
121 selectImage.appendChild(image);
122 /* 2) create hidden div to explain caracteristics of the image */
123 render_description(platform, flavor["openstack:image"], 'image');
124 global_list[platform][flavor_name].push(flavor['openstack:image']['@name']);
130 elm.appendChild(selectFlavor);
131 elm.appendChild(selectImage);
133 $("#"+platform+"_selectFlavor").css("width","100px");
134 $("#"+platform+"_selectFlavor").css("height","30px");
135 $("#"+platform+"_selectImage").css("width","30px");
136 $("#"+platform+"_selectImage").css("height","30px");
138 function is_finished(len_platforms, pf_status){
139 if(len_platforms == pf_status){
145 function sliver_name_exists(sliver_name){
146 if(sliver_name in added_nodes){
150 if (sliver_name in deleted_nodes){
156 function find_sliver_name(sliver_name, num){
157 for (j=Object.keys(added_nodes).length; j<Object.keys(added_nodes).length+num; i++){
158 vm_name = sliver_name+'_'+j;
159 if(!sliver_name_exists(vm_name)){
165 function send_add(platform){
166 $('#'+platform+'_pending_add').show();
167 sliver_name = $('#'+platform+'_sliver_name').val();
168 sliver_name = sliver_name.replace(' ','_');
169 flavor_name = $('#'+platform+'_selectFlavor').val();
170 image_name = $('#'+platform+'_selectImage').val();
172 num = $('#'+platform+'_number').val();
174 for (i = 0; i < num; i++){
175 // XXX Check if the name already exist in existing VMs and added_nodes
176 vm_name = sliver_name+"_"+i;
177 if (sliver_name_exists(vm_name)){
178 vm_name = find_sliver_name(sliver_name, num);
180 node = get_node(vm_name, flavor_name, image_name);
181 request_rspec['rspec']['node'].push(node);
182 render_node(platform, node, 'pending_add');
183 added_nodes[vm_name]=node;
186 if (sliver_name_exists(sliver_name)){
187 sliver_name = find_sliver_name(sliver_name, num);
189 node = get_node(sliver_name, flavor_name, image_name);
190 request_rspec['rspec']['node'].push(node);
191 render_node(platform, node, 'pending_add');
192 added_nodes[sliver_name]=node;
194 toogle_div(platform, flavor_name, 'flavor');
195 toogle_div(platform, image_name, 'image');
196 flavor_name = $('#'+platform+'_selectFlavor').val(0);
197 image_name = $('#'+platform+'_selectImage').val(0);
198 $('#'+platform+'_add').hide();
199 $('#'+platform+'_add_button').hide();
200 $('#'+platform+'_div_pending').show();
201 console.log(request_rspec);
202 //jQuery('#'+platform+'_form_delete').submit();
204 function get_node(vm_name, flavor_name, image_name){
206 if(ad_rspec['rspec']['node'] instanceof Array) {
207 // Deep copy of the Array to avoid reference
208 node = jQuery.extend(true, {}, ad_rspec['rspec']['node'][0]);
210 // Deep copy of the Array to avoid reference
211 node = jQuery.extend(true, {}, ad_rspec['rspec']['node']);
213 if(node['openstack:sliver'] instanceof Array) {
214 node['openstack:sliver'] = node['openstack:sliver'][0];
216 node['openstack:sliver']['@sliver_name'] = vm_name;
217 console.log(vm_name);
219 if(node['openstack:sliver']['openstack:flavor'] instanceof Array) {
220 node['openstack:sliver']['openstack:flavor'] = node['openstack:sliver']['openstack:flavor'][0];
222 node['openstack:sliver']['openstack:flavor'] = Array();
223 node['openstack:sliver']['openstack:flavor'] = {'@name':flavor_name,'openstack:image':{'@name':image_name}};
225 $.each(node['openstack:sliver']['openstack:security_group'], function(i, group){
226 if(group['@name']=='default'){
227 node['openstack:sliver']['openstack:security_group'] = group;
234 function send_delete(platform, sliver_name){
235 $('#'+platform+'_pending_delete').show();
236 jQuery('#'+platform+'_vm').val(sliver_name);
237 jQuery('#'+platform+'_existing_'+sliver_name).hide();
238 node = remove_node_from_request_rspec(sliver_name);
239 deleted_nodes[sliver_name]=node;
240 render_node(platform, node, 'pending_delete');
241 $('#'+platform+'_div_pending').show();
242 console.log(request_rspec);
244 function remove_node_from_request_rspec(sliver_name){
245 var save_node = Array();
246 jQuery.each( request_rspec['rspec']['node'], function( i, node ) {
247 if(node['openstack:sliver']['@sliver_name']==sliver_name){
248 request_rspec['rspec']['node'].splice(i,1);
255 function cancel_add(platform,sliver_name){
256 // remove the canceled node from the pending list
257 $('#'+platform+'_pending_add_'+sliver_name).remove();
258 // remove the canceled node from the request rspec
259 node = remove_node_from_request_rspec(sliver_name);
260 delete added_nodes[sliver_name];
261 // hide the pending div if there are no more nodes
262 if ($('#'+platform+'_pending_add div').length==0){
263 $('#'+platform+'_pending_add').hide();
264 if ($('#'+platform+'_pending_delete div').length==0){
265 $('#'+platform+'_div_pending').hide();
269 function cancel_delete(platform,sliver_name){
270 // display the canceled node back in existing nodes
271 $('#'+platform+'_existing_'+sliver_name).show();
272 // remove the canceled node from the pending list
273 $('#'+platform+'_pending_delete_'+sliver_name).remove();
274 // Cancel the deletion of an existing node -> push it back to the request rspec
275 request_rspec['rspec']['node'].push(deleted_nodes[sliver_name]);
276 delete deleted_nodes[sliver_name];
277 // hide the pending div if there are no more nodes
278 if ($('#'+platform+'_pending_delete div').length==0){
279 $('#'+platform+'_pending_delete').hide();
280 if ($('#'+platform+'_pending_add div').length==0){
281 $('#'+platform+'_div_pending').hide();
286 function public_ip(platform,sliver_name,is_public){
287 // XXX Change ip status in request_rspec
289 // external_ip="true"
290 node = remove_node_from_request_rspec(sliver_name);
291 node['external_ip']="true";
292 added_nodes[sliver_name]['external_ip']="true";
293 request_rspec['rspec']['node'].push(node);
295 console.log(sliver_name+' NOT public ');
296 // external_ip="false"
297 node = remove_node_from_request_rspec(sliver_name);
298 node['external_ip']="false";
299 added_nodes[sliver_name]['external_ip']="false";
300 request_rspec['rspec']['node'].push(node);
304 function render_node(platform, node, state){
305 if('openstack:sliver' in node){
306 sliver = node['openstack:sliver']
307 var d = platform+'_'+state+'_'+sliver['@sliver_name'];
308 d = d.replace(/ /g, '');
309 id = d.replace( /(:|\.|\[|\])/g, "\\$1" );
310 $("#"+platform+"_"+state).append("<div id='"+platform+'_'+state+'_'+sliver['@sliver_name']+"' class='row'></div>");
311 //$("#"+id).append("<input type='hidden' name='"+platform+"_"+sliver['@sliver_name']+"' value='"+sliver['@sliver_name']+"'>");
312 if(state=='pending_add'){
313 $("#"+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>");
315 $("#"+id).append("<div class='col-md-1' style='margin-left:0px;!important;'> </div>");
317 $("#"+id).append("<div class='col-md-2' style='padding-left:0px;'>"+sliver['@sliver_name']+"</div>");
318 $("#"+id).append("<div class='col-md-3'>"+sliver['openstack:flavor']['@name']+"</div>");
319 $("#"+id).append("<div class='col-md-3'>"+sliver['openstack:flavor']['openstack:image']['@name']+"</div>");
321 if(state=='existing'){
322 $("#"+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>");
323 }else if(state=='pending_add'){
324 $("#"+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>");
325 }else if (state=='pending_delete'){
326 $("#"+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>");
328 console.log("state: "+state+" not impemented");
331 sliver['openstack:address']
332 sliver['openstack:flavor']
337 function allocate(platform, slicename){
338 $("#"+platform+"_main").addClass("disabled");
339 $("#"+platform+"_wait").show();
340 $("#"+platform+"_wait").spin();
341 $.post("/sfa/Allocate",{'hrn':slicename, 'type':'slice', 'platform':[platform], 'rspec':JSON.stringify(request_rspec)}, function( result ) {
343 clear_data(platform);
344 load_data(platform,slicename);
345 $("#"+platform+"_main").removeClass("disabled");
346 $("#"+platform+"_wait").hide();
347 mysliceAlert('Success: changes applied','success', true);
350 function clear_data(platform){
351 $('#'+platform+'_existing').children().remove();
352 $('#'+platform+'_pending_delete').children().remove();
353 $("#"+platform+"_selectFlavor").remove();
354 $("#"+platform+"_selectImage").remove();
355 $('#'+platform+'_pending_add').children().remove();
356 $('#'+platform+'_div_pending').hide();
358 function load_data(platform, slicename){
359 var platform_status = Array();
360 var platform_empty = Array();
362 $.post("/sfa/Describe",{'hrn':slicename, 'type':'slice', 'platform':[platform]}, function( d ) {
365 if('parsed' in data[platform] && 'rspec' in data[platform]['parsed']){
366 manifest_rspec = data[platform]['parsed']['rspec'];
367 request_rspec = data[platform]['parsed'];
368 request_rspec['rspec']['@type']='request';
369 if('node' in manifest_rspec){
370 if(manifest_rspec['node'] instanceof Array) {
371 jQuery.each( manifest_rspec['node'], function( i, node ) {
372 render_node(platform,node, 'existing');
375 render_node(platform,manifest_rspec['node'], 'existing');
377 $('#'+platform+'_existing').show();
381 $.post("/sfa/ListResources",{'platform':[platform]}, function( d ) {
384 if('parsed' in d[platform] && 'rspec' in d[platform]['parsed']){
385 ad_rspec = d[platform]['parsed'];
386 if('node' in ad_rspec['rspec']){
387 if(ad_rspec['rspec']['node'] instanceof Array) {
388 jQuery.each( ad_rspec['rspec']['node'], function( i, node ) {
389 render_cloud(platform,node);
392 render_cloud(platform,ad_rspec['rspec']['node']);
395 platform_empty.push(platform);
398 platform_empty.push(platform);
400 platform_status.push(platform);
401 if(is_finished(len_platforms,platform_status.length)){
402 $("#loading").hide();
403 if(platform_empty.length == len_platforms){
404 $("#warning_message").show();
409 $(document).ready(function() {
410 {% for platform in platforms %}
411 {% if platform in cloud_platforms %}
412 load_data('{{platform}}', '{{slicename}}');
421 {% for platform in platforms %}
422 {% if platform in cloud_platforms %}
423 <div id="{{platform}}_wait" style="display:none;margin-top:20px;position:absolute;margin-left:300px;"></div>
424 <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;">
425 <h2>{{ platform }}</h2>
426 // display only if VMs already in slice
427 <h4>VMs in slice {{slicename}}</h4>
428 <form id="{{platform}}_form_delete" method="post">
430 <div id="{{platform}}_existing" class="row alert alert-info" style="display:none;">
431 <input type="hidden" name="{{platform}}_vm" id="{{platform}}_vm">
432 <input type="hidden" name="action" id="action" value="delete">
433 <input type="hidden" name="platform" id="platform" value="{{platform}}">
436 <h4><a href="#" onclick="$('#{{platform}}_div_add').toggle();"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span> Create new VMs</a></h4>
437 <div id="{{platform}}_div_add" class="alert" style="background-color:#f1f1f1;display:none;margin-bottom:0px !important;padding-bottom:6px !important;">
438 <form id="{{platform}}_form_add" method="post" class="form-inline">
440 <div id="{{platform}}_input" class="row">
441 <div class="col-md-1"></div>
442 <div class="col-md-3"><label for="{{platform}}_number">number:</label>
443 <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>
445 <div class="col-md-8"><label for="{{platform}}_sliver_name">name:</label>
446 <div class="form-group">
447 <input type="text" name="{{platform}}_sliver_name" id="{{platform}}_sliver_name" value="VM" maxlength="12" class="form-control" style="height:30px;" required>
450 <div class="col-md-1"></div>
451 <div id="{{platform}}_select" class="col-md-11"></div>
453 <div id="{{platform}}_add" class="row">
454 <div class="col-md-1">
455 <input type="hidden" name="action" id="action" value="add">
456 <input type="hidden" name="platform" id="platform" value="{{platform}}">
459 <div class="row" style="padding-top:6px;">
460 <div class="col-md-1"> </div>
461 <div class="col-md-11" id="{{platform}}_add_button" style="display:none;">
462 <input type="submit" form="{{platform}}_form_add" value="Add" onclick="send_add('{{platform}}');">
468 <div id="{{platform}}_div_pending" style="display:none;">
469 // display only pending changes
470 <h4>Pending changes</h4>
471 <form id="{{platform}}_form_reserve" method="post">
473 <div id="{{platform}}_pending_add" class="row alert alert-success" style="display:none;margin-bottom:3px !important;"></div>
474 <div id="{{platform}}_pending_delete" class="row alert alert-danger" style="display:none;margin-bottom:3px !important;"></div>
476 <input type="hidden" name="action" id="action" value="reserve">
477 <input type="hidden" name="platform" id="platform" value="{{platform}}">
478 <input type="submit" form="{{platform}}_form_reserve" value="Apply changes" onclick="allocate('{{platform}}','{{slicename}}');">