1 {% extends "layout_wide.html" %}
4 <script type="text/javascript">
8 var ad_rspec = Array();
9 var request_rspec = Array();
10 var manifest_rspec = Array();
11 var deleted_nodes = {};
14 var len_platforms = {{len_platforms}};
16 /* render_flavor & render_image */
17 function render_option(obj){
18 var option = document.createElement("option");
19 option.text = obj["@name"];
20 option.value = obj["@name"];
23 function render_description(platform, obj, type){
24 if($('#'+platform+'_'+type).length==0){
25 $('#'+platform+'_add').append("<div id='"+platform+"_"+type+"'>");
27 var d = platform+'_'+type+'_'+obj['@name'];
28 d = d.replace(/ /g, '');
29 id = d.replace( /(:|\.|\[|\])/g, "\\$1" );
30 if($('#'+id).length==0){
31 $('#'+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>");
33 if($('#'+id+' div').length==0){
34 jQuery.each(obj, function(key,val){
35 if (key != 'openstack:image'){
36 $('#'+id).append("<div>"+key.replace('@','')+": "+val+"</div>");
41 function toogle_div(platform, value, type){
42 $("#"+platform+"_add").show();
43 // show the add button only if image is selected
44 if($("#"+platform+"_selectImage").val()!=null && $("#"+platform+"_selectImage").val()!=0 && value!=0){
45 $("#"+platform+"_add_button").show();
47 $("#"+platform+"_add_button").hide();
49 $("[id^='"+platform+"_"+type+"_"+"']").hide();
50 d = platform+'_'+type+'_'+value;
51 d = d.replace(/ /g, '');
52 id = d.replace( /(:|\.|\[|\])/g, "\\$1" );
55 function render_cloud(platform, node){
56 elm = document.getElementById(platform+'_select');
57 //newElement = document.createElement('p');
58 //elm.appendChild(newElement);
59 global_list[platform]={};
60 if('openstack:sliver' in node){
61 selectFlavor = document.createElement('select');
62 selectFlavor.id = platform+"_selectFlavor";
63 selectFlavor.name = platform+"_selectFlavor";
64 selectFlavor.onchange = function(){
65 /* 1) Display corresponding Flavor div - hide others - reset selectImage value */
66 $("#"+platform+"_selectImage option[value=0]").prop('selected', true);
67 toogle_div(platform, this.value, 'flavor');
68 /* 3) Disable Images, Enable only compatible ones in selectImage */
69 $("[id^='"+platform+"_image_"+"']").hide();
70 $("#"+platform+"_selectImage option").attr("disabled",true);
71 $.each(global_list[platform][this.value], function (i,v){
72 $("#"+platform+"_selectImage option[value='" + v + "']").attr("disabled",false);
74 $("#"+platform+"_selectImage").attr("disabled",false);
76 var option = document.createElement("option");
77 option.text = "-- select a flavor --";
79 selectFlavor.appendChild(option);
80 jQuery.each( node['openstack:sliver'], function( i, sliver ) {
81 if('openstack:flavor' in sliver){
82 f = render_option(sliver['openstack:flavor']);
83 selectFlavor.appendChild(f);
84 flavor = sliver["openstack:flavor"];
85 /* 1) create hidden div to explain caracteristics of the flavor */
86 render_description(platform, flavor, 'flavor');
87 flavor_name = flavor['@name'];
88 global_list[platform][flavor_name]=[];
89 if ("openstack:image" in flavor){
90 selectImage = document.createElement('select');
91 selectImage.id = platform+"_selectImage";
92 selectImage.name = platform+"_selectImage";
93 selectImage.onchange = function(){
94 /* 2) display corresponding Image div - hide others */
95 toogle_div(platform, this.value, 'image');
97 var option = document.createElement("option");
98 option.text = "-- select an image --";
100 selectImage.appendChild(option);
101 if(flavor["openstack:image"] instanceof Array){
102 jQuery.each( flavor["openstack:image"], function( i, img ) {
103 image = render_option(img);
104 image.disabled = true;
105 selectImage.appendChild(image);
106 /* 2) create hidden div to explain caracteristics of the image */
107 render_description(platform, img, 'image');
108 global_list[platform][flavor_name].push(img['@name']);
111 image = render_option(flavor["openstack:image"]);
112 image.disabled = true;
113 selectImage.appendChild(image);
114 /* 2) create hidden div to explain caracteristics of the image */
115 render_description(platform, flavor["openstack:image"], 'image');
116 global_list[platform][flavor_name].push(flavor['openstack:image']['@name']);
122 elm.appendChild(selectFlavor);
123 elm.appendChild(selectImage);
125 $("#"+platform+"_selectFlavor").css("width","100px");
126 $("#"+platform+"_selectFlavor").css("height","30px");
127 $("#"+platform+"_selectImage").css("width","30px");
128 $("#"+platform+"_selectImage").css("height","30px");
130 function is_finished(len_platforms, pf_status){
131 if(len_platforms == pf_status){
137 function sliver_name_exists(sliver_name){
138 if(sliver_name in added_nodes){
142 if (sliver_name in deleted_nodes){
148 function find_sliver_name(sliver_name, num){
149 for (j=Object.keys(added_nodes).length; j<Object.keys(added_nodes).length+num; i++){
150 vm_name = sliver_name+'_'+j;
151 if(!sliver_name_exists(vm_name)){
157 function send_add(platform){
158 $('#'+platform+'_pending_add').show();
159 sliver_name = $('#'+platform+'_sliver_name').val();
160 sliver_name = sliver_name.replace(' ','_');
161 flavor_name = $('#'+platform+'_selectFlavor').val();
162 image_name = $('#'+platform+'_selectImage').val();
164 num = $('#'+platform+'_number').val();
166 for (i = 0; i < num; i++){
167 // XXX Check if the name already exist in existing VMs and added_nodes
168 vm_name = sliver_name+"_"+i;
169 if (sliver_name_exists(vm_name)){
170 vm_name = find_sliver_name(sliver_name, num);
172 node = get_node(vm_name, flavor_name, image_name);
173 request_rspec['rspec']['node'].push(node);
174 render_node(platform, node, 'pending_add');
175 added_nodes[vm_name]=node;
178 if (sliver_name_exists(sliver_name)){
179 sliver_name = find_sliver_name(sliver_name, num);
181 node = get_node(sliver_name, flavor_name, image_name);
182 request_rspec['rspec']['node'].push(node);
183 render_node(platform, node, 'pending_add');
184 added_nodes[sliver_name]=node;
186 toogle_div(platform, flavor_name, 'flavor');
187 toogle_div(platform, image_name, 'image');
188 flavor_name = $('#'+platform+'_selectFlavor').val(0);
189 image_name = $('#'+platform+'_selectImage').val(0);
190 $('#'+platform+'_add').hide();
191 $('#'+platform+'_add_button').hide();
192 $('#'+platform+'_div_pending').show();
193 console.log(request_rspec);
194 //jQuery('#'+platform+'_form_delete').submit();
196 function get_node(vm_name, flavor_name, image_name){
198 if(ad_rspec['rspec']['node'] instanceof Array) {
199 // Deep copy of the Array to avoid reference
200 node = jQuery.extend(true, {}, ad_rspec['rspec']['node'][0]);
202 // Deep copy of the Array to avoid reference
203 node = jQuery.extend(true, {}, ad_rspec['rspec']['node']);
205 if(node['openstack:sliver'] instanceof Array) {
206 node['openstack:sliver'] = node['openstack:sliver'][0];
208 node['openstack:sliver']['@sliver_name'] = vm_name;
209 console.log(vm_name);
211 if(node['openstack:sliver']['openstack:flavor'] instanceof Array) {
212 node['openstack:sliver']['openstack:flavor'] = node['openstack:sliver']['openstack:flavor'][0];
214 node['openstack:sliver']['openstack:flavor'] = Array();
215 node['openstack:sliver']['openstack:flavor'] = {'@name':flavor_name,'openstack:image':{'@name':image_name}};
217 $.each(node['openstack:sliver']['openstack:security_group'], function(i, group){
218 if(group['@name']=='default'){
219 node['openstack:sliver']['openstack:security_group'] = group;
226 function send_delete(platform, sliver_name){
227 $('#'+platform+'_pending_delete').show();
228 jQuery('#'+platform+'_vm').val(sliver_name);
229 jQuery('#'+platform+'_existing_'+sliver_name).hide();
230 node = remove_node_from_request_rspec(sliver_name);
231 deleted_nodes[sliver_name]=node;
232 render_node(platform, node, 'pending_delete');
233 $('#'+platform+'_div_pending').show();
234 console.log(request_rspec);
236 function remove_node_from_request_rspec(sliver_name){
237 var save_node = Array();
238 jQuery.each( request_rspec['rspec']['node'], function( i, node ) {
239 if(node['openstack:sliver']['@sliver_name']==sliver_name){
240 request_rspec['rspec']['node'].splice(i,1);
247 function cancel_add(platform,sliver_name){
248 // remove the canceled node from the pending list
249 $('#'+platform+'_pending_add_'+sliver_name).remove();
250 // remove the canceled node from the request rspec
251 node = remove_node_from_request_rspec(sliver_name);
252 delete added_nodes[sliver_name];
253 // hide the pending div if there are no more nodes
254 if ($('#'+platform+'_pending_add div').length==0){
255 $('#'+platform+'_pending_add').hide();
256 if ($('#'+platform+'_pending_delete div').length==0){
257 $('#'+platform+'_div_pending').hide();
261 function cancel_delete(platform,sliver_name){
262 // display the canceled node back in existing nodes
263 $('#'+platform+'_existing_'+sliver_name).show();
264 // remove the canceled node from the pending list
265 $('#'+platform+'_pending_delete_'+sliver_name).remove();
266 // Cancel the deletion of an existing node -> push it back to the request rspec
267 request_rspec['rspec']['node'].push(deleted_nodes[sliver_name]);
268 delete deleted_nodes[sliver_name];
269 // hide the pending div if there are no more nodes
270 if ($('#'+platform+'_pending_delete div').length==0){
271 $('#'+platform+'_pending_delete').hide();
272 if ($('#'+platform+'_pending_add div').length==0){
273 $('#'+platform+'_div_pending').hide();
278 function public_ip(platform,sliver_name,is_public){
279 // XXX Change ip status in request_rspec
281 // external_ip="true"
282 node = remove_node_from_request_rspec(sliver_name);
283 node['external_ip']="true";
284 added_nodes[sliver_name]['external_ip']="true";
285 request_rspec['rspec']['node'].push(node);
287 console.log(sliver_name+' NOT public ');
288 // external_ip="false"
289 node = remove_node_from_request_rspec(sliver_name);
290 node['external_ip']="false";
291 added_nodes[sliver_name]['external_ip']="false";
292 request_rspec['rspec']['node'].push(node);
296 function render_node(platform, node, state){
297 if('openstack:sliver' in node){
298 sliver = node['openstack:sliver']
299 var d = platform+'_'+state+'_'+sliver['@sliver_name'];
300 d = d.replace(/ /g, '');
301 id = d.replace( /(:|\.|\[|\])/g, "\\$1" );
302 $("#"+platform+"_"+state).append("<div id='"+platform+'_'+state+'_'+sliver['@sliver_name']+"' class='row'></div>");
303 //$("#"+id).append("<input type='hidden' name='"+platform+"_"+sliver['@sliver_name']+"' value='"+sliver['@sliver_name']+"'>");
304 if(state=='pending_add'){
305 $("#"+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>");
307 $("#"+id).append("<div class='col-md-1' style='margin-left:0px;!important;'> </div>");
309 $("#"+id).append("<div class='col-md-2' style='padding-left:0px;'>"+sliver['@sliver_name']+"</div>");
310 $("#"+id).append("<div class='col-md-3'>"+sliver['openstack:flavor']['@name']+"</div>");
311 $("#"+id).append("<div class='col-md-3'>"+sliver['openstack:flavor']['openstack:image']['@name']+"</div>");
313 if(state=='existing'){
314 $("#"+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>");
315 }else if(state=='pending_add'){
316 $("#"+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>");
317 }else if (state=='pending_delete'){
318 $("#"+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>");
320 console.log("state: "+state+" not impemented");
323 sliver['openstack:address']
324 sliver['openstack:flavor']
329 function allocate(platform, slicename){
330 $.post("/sfa/Allocate",{'hrn':slicename, 'type':'slice', 'platform':[platform], 'rspec':JSON.stringify(request_rspec)}, function( result ) {
332 clear_data(platform);
333 load_data(platform,slicename);
334 mysliceAlert('Success: changes applied','success', true);
337 function clear_data(platform){
338 $('#'+platform+'_existing').children().remove();
339 $('#'+platform+'_pending_delete').children().remove();
340 $("#"+platform+"_selectFlavor").remove();
341 $("#"+platform+"_selectImage").remove();
342 $('#'+platform+'_pending_add').children().remove();
343 $('#'+platform+'_div_pending').hide();
345 function load_data(platform, slicename){
346 var platform_status = Array();
347 var platform_empty = Array();
349 $.post("/sfa/Describe",{'hrn':slicename, 'type':'slice', 'platform':[platform]}, function( d ) {
352 if('parsed' in data[platform] && 'rspec' in data[platform]['parsed']){
353 manifest_rspec = data[platform]['parsed']['rspec'];
354 request_rspec = data[platform]['parsed'];
355 request_rspec['rspec']['@type']='request';
356 if('node' in manifest_rspec){
357 if(manifest_rspec['node'] instanceof Array) {
358 jQuery.each( manifest_rspec['node'], function( i, node ) {
359 render_node(platform,node, 'existing');
362 render_node(platform,manifest_rspec['node'], 'existing');
364 $('#'+platform+'_existing').show();
368 $.post("/sfa/ListResources",{'platform':[platform]}, function( d ) {
371 if('parsed' in d[platform] && 'rspec' in d[platform]['parsed']){
372 ad_rspec = d[platform]['parsed'];
373 if('node' in ad_rspec['rspec']){
374 if(ad_rspec['rspec']['node'] instanceof Array) {
375 jQuery.each( ad_rspec['rspec']['node'], function( i, node ) {
376 render_cloud(platform,node);
379 render_cloud(platform,ad_rspec['rspec']['node']);
382 platform_empty.push(platform);
385 platform_empty.push(platform);
387 platform_status.push(platform);
388 if(is_finished(len_platforms,platform_status.length)){
389 $("#loading").hide();
390 if(platform_empty.length == len_platforms){
391 $("#warning_message").show();
396 $(document).ready(function() {
397 {% for platform in platforms %}
398 {% if platform in cloud_platforms %}
399 load_data('{{platform}}', '{{slicename}}');
408 {% for platform in platforms %}
409 {% if platform in cloud_platforms %}
410 <div style="padding-left:20px;padding-top:20px;padding-right:20px;padding-bottom:20px;border-style:solid;border-width:1px;width:700px;">
411 <h2>{{ platform }}</h2>
412 // display only if VMs already in slice
413 <h4>VMs in slice {{slicename}}</h4>
414 <form id="{{platform}}_form_delete" method="post">
416 <div id="{{platform}}_existing" class="row alert alert-info" style="display:none;">
417 <input type="hidden" name="{{platform}}_vm" id="{{platform}}_vm">
418 <input type="hidden" name="action" id="action" value="delete">
419 <input type="hidden" name="platform" id="platform" value="{{platform}}">
422 <h4><a href="#" onclick="$('#{{platform}}_div_add').toggle();"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span> Create new VMs</a></h4>
423 <div id="{{platform}}_div_add" class="alert" style="background-color:#f1f1f1;display:none;margin-bottom:0px !important;padding-bottom:6px !important;">
424 <form id="{{platform}}_form_add" method="post" class="form-inline">
426 <div id="{{platform}}_input" class="row">
427 <div class="col-md-1"></div>
428 <div class="col-md-3"><label for="{{platform}}_number">number:</label>
429 <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>
431 <div class="col-md-8"><label for="{{platform}}_sliver_name">name:</label>
432 <div class="form-group">
433 <input type="text" name="{{platform}}_sliver_name" id="{{platform}}_sliver_name" value="VM" maxlength="12" class="form-control" style="height:30px;" required>
436 <div class="col-md-1"></div>
437 <div id="{{platform}}_select" class="col-md-11"></div>
439 <div id="{{platform}}_add" class="row">
440 <div class="col-md-1">
441 <input type="hidden" name="action" id="action" value="add">
442 <input type="hidden" name="platform" id="platform" value="{{platform}}">
445 <div class="row" style="padding-top:6px;">
446 <div class="col-md-1"> </div>
447 <div class="col-md-11" id="{{platform}}_add_button" style="display:none;">
448 <input type="submit" form="{{platform}}_form_add" value="Add" onclick="send_add('{{platform}}');">
454 <div id="{{platform}}_div_pending" style="display:none;">
455 // display only pending changes
456 <h4>Pending changes</h4>
457 <form id="{{platform}}_form_reserve" method="post">
459 <div id="{{platform}}_pending_add" class="row alert alert-success" style="display:none;margin-bottom:3px !important;"></div>
460 <div id="{{platform}}_pending_delete" class="row alert alert-danger" style="display:none;margin-bottom:3px !important;"></div>
462 <input type="hidden" name="action" id="action" value="reserve">
463 <input type="hidden" name="platform" id="platform" value="{{platform}}">
464 <input type="submit" form="{{platform}}_form_reserve" value="Apply changes" onclick="allocate('{{platform}}','{{slicename}}');">