root / ui / templates / machines.html @ dddb9274
History | View | Annotate | Download (30.1 kB)
1 |
{% load i18n %} |
---|---|
2 |
|
3 |
<div id="machines" class="seperator"></div> |
4 |
|
5 |
<!-- the create button -->
|
6 |
<a id="create" rel="#wizard" href="#">{% trans "Create New +" %}</a> |
7 |
|
8 |
<!-- changing between standard/list view -->
|
9 |
<div id="view-select"> |
10 |
<a id="standard" class="current" href="/machines">#</a> |
11 |
<span class="view-seperator">|</span> |
12 |
<a id="list" href="/machines/list">=</a> |
13 |
</div>
|
14 |
|
15 |
<!-- the standard view -->
|
16 |
<div id="machinesview" class="standard"> |
17 |
<div id="spinner"></div> |
18 |
<div class="machine" id="machine-template" style="display:none"> |
19 |
<div class="state"> |
20 |
<div class="status">{% trans "Running" %}</div> |
21 |
<div class="indicator"></div> |
22 |
<div class="indicator"></div> |
23 |
<div class="indicator"></div> |
24 |
<div class="indicator"></div> |
25 |
</div>
|
26 |
<img class="logo" src="" /> |
27 |
<a href="#" class="name"> |
28 |
<h5>Νame: <span class="name">node.name</span><span class="rename"></span></h5> |
29 |
</a>
|
30 |
<a href="#" class="ip"> |
31 |
<h5>IP: <span class="public">node.public_ip</span></h5> |
32 |
</a>
|
33 |
<h5 class="settings"> |
34 |
{% trans "Show:" %} <a href="#">{% trans "disks" %}</a> | <a href="#">{% trans "networks" %}</a> | <a href="#">{% trans "group" %}</a> |
35 |
</h5>
|
36 |
<div class="actions"> |
37 |
<a href="#" class="action-start">{% trans "Start" %}</a> |
38 |
<a href="#" class="action-reboot">{% trans "Reboot" %}</a> |
39 |
<a href="#" class="action-shutdown">{% trans "Shutdown" %}</a> |
40 |
<a href="#" class="more">{% trans "more …" %}</a> |
41 |
</div>
|
42 |
<div class="seperator"></div> |
43 |
</div>
|
44 |
|
45 |
<div class="running"></div> |
46 |
<div id="mini" class="seperator"></div> |
47 |
<div class="terminated"></div> |
48 |
</div>
|
49 |
|
50 |
<div id="machines" class="seperator"></div> |
51 |
|
52 |
<!-- the form -->
|
53 |
<form action="#"> |
54 |
<!-- scrollable root element -->
|
55 |
<div class="modal" id="wizard"> |
56 |
<!-- status bar -->
|
57 |
<ul id="status"> |
58 |
<li class="active"><strong>1.</strong> {% trans "Image" %}</li> |
59 |
<li><strong>2.</strong> {% trans "Machine" %}</li> |
60 |
<li><strong>3.</strong> {% trans "Review" %}</li> |
61 |
</ul>
|
62 |
<!-- scrollable items -->
|
63 |
<div class="items"> |
64 |
<!-- pages -->
|
65 |
<div class="page"> |
66 |
<h2>{% trans "Select an OS" %}</h2> |
67 |
<ul class="tabs"> |
68 |
<li><a href="#">{% trans "standard" %}</a></li> |
69 |
<li><a href="#">{% trans "custom" %}</a></li> |
70 |
</ul>
|
71 |
<div class="panes"> |
72 |
<li id="image-template" style="display:none"> |
73 |
<label for="image.id"> |
74 |
<a><div class="image"> |
75 |
<img src="" class="image-logo"/> |
76 |
<strong class="image-title">image.title</strong> |
77 |
<input class="radio" type="radio" name="image-id" id="image-id" /> |
78 |
<br /> |
79 |
<span class="description">image.description</span> |
80 |
<span class="size">?? MB</span> |
81 |
|
82 |
</div></a> |
83 |
</label>
|
84 |
</li>
|
85 |
<ul class="pane" id="standard-images"> |
86 |
<!-- standard images -->
|
87 |
</ul>
|
88 |
<ul class="pane" id="custom-images"> |
89 |
<!-- custom images -->
|
90 |
|
91 |
</ul>
|
92 |
</div>
|
93 |
<button type="button" class="prev" id="cancel">{% trans "Cancel" %}</button> |
94 |
<button type="button" class="next right">{% trans "Next" %} »</button> |
95 |
</div>
|
96 |
<div class="page"> |
97 |
<h2>{% trans "Select CPU, RAM and storage" %}</h2> |
98 |
<ul>
|
99 |
<li>
|
100 |
<div class="machine-type"> |
101 |
<label for="small"> |
102 |
<input type="radio" id="small" name="machine-type" value="small" checked="true" /> |
103 |
<strong>{% trans "small" %}</strong> |
104 |
</label>
|
105 |
</div>
|
106 |
<div class="machine-type"> |
107 |
<label for="medium"> |
108 |
<input type="radio" id="medium" name="machine-type" value="medium" /> |
109 |
<strong>{% trans "medium" %}</strong> |
110 |
</label>
|
111 |
</div>
|
112 |
<div class="machine-type"> |
113 |
<label for="large"> |
114 |
<input type="radio" id="large" name="machine-type" value="large" /> |
115 |
<strong>{% trans "large" %}</strong> |
116 |
</label>
|
117 |
</div>
|
118 |
<div class="machine-type"> |
119 |
<label for="custom"> |
120 |
<input type="radio" name="machine-type" id="custom" value="large" /> |
121 |
<strong>{% trans "custom" %}</strong> |
122 |
</label>
|
123 |
</div>
|
124 |
</li>
|
125 |
<li>
|
126 |
<label><strong class="sliders">CPU (cores)</strong></label> |
127 |
<input type="range" id="cpu" style="display:none" /> |
128 |
<input type="text" class="range" id="cpu-indicator" /> |
129 |
</li>
|
130 |
<li>
|
131 |
<label><strong class="sliders">RAM (MB)</strong></label> |
132 |
<input type="range" id="ram" style="display:none" /> |
133 |
<input type="text" class="range" id="ram-indicator" /> |
134 |
|
135 |
</li>
|
136 |
<li>
|
137 |
<label><strong class="sliders">Storage (GB)</strong></label> |
138 |
<input type="range" id="storage" style="display:none" /> |
139 |
<input type="text" class="range" id="storage-indicator" /> |
140 |
|
141 |
</li>
|
142 |
<li>
|
143 |
<div class="cost"> |
144 |
{% trans "Cost per hour:" %} 20 {% trans "credits" %} | {% trans "Credits currently in account:" %} 10.000 |
145 |
</div>
|
146 |
</li>
|
147 |
</ul>
|
148 |
<button type="button" class="prev">« {% trans "Back" %}</button> |
149 |
<button type="button" class="next right">{% trans "Next" %} »</button> |
150 |
</div>
|
151 |
<div class="page"> |
152 |
<h2>{% trans "Confirm your settings" %}</h2> |
153 |
<ul>
|
154 |
<li class="required"> |
155 |
<label>
|
156 |
<strong>Machine name</strong> |
157 |
<input type="text" class="text" name="machine_name" value="My Ubuntu 10.04 x86_64 server"/> |
158 |
</label>
|
159 |
</li>
|
160 |
<li>
|
161 |
<strong>{% trans "Image:" %}</strong> <span id="machine_image-label">Ubuntu 10.04 x86_64 server</span> |
162 |
</li>
|
163 |
<li>
|
164 |
<strong>{% trans "CPU:" %}</strong> <span id="machine_cpu-label">2</span> <span>{% trans "cores" %}</span> |
165 |
</li>
|
166 |
<li>
|
167 |
<strong>{% trans "RAM:" %}</strong> <span id="machine_ram-label">1024</span><span>MB</span> |
168 |
</li>
|
169 |
<li>
|
170 |
<strong>{% trans "Storage:" %}</strong> <span id="machine_storage-label">10</span><span>GB</span> |
171 |
</li>
|
172 |
<li>
|
173 |
<strong>{% trans "Cost per hour:" %}</strong> <span>20 {% trans "credits" %}</span> |
174 |
</li>
|
175 |
<li>
|
176 |
<strong>{% trans "Remaining credits:" %}</strong> <span>10.000</span> |
177 |
</li>
|
178 |
</ul>
|
179 |
<button type="button" class="prev">« {% trans "Back" %}</button> |
180 |
<button type="button" class="next right" id="start">{% trans "Create VM" %}</button> |
181 |
</div>
|
182 |
</div>
|
183 |
</div>
|
184 |
</form>
|
185 |
|
186 |
<!-- notification after wizard completion -->
|
187 |
<a id="notification" rel="#error-success" href="#"></a> |
188 |
|
189 |
<div class="modal" id="error-success"> |
190 |
<h3>{% trans "Error!/Success!" %}</h3> |
191 |
<p>{% trans "More details about the result"%}</p> |
192 |
</div>
|
193 |
|
194 |
<!-- confirmation before executing an action -->
|
195 |
<a id="confirmation" rel="#yes-no" href="#"></a> |
196 |
|
197 |
<div class="modal" id="yes-no"> |
198 |
<h3>{% trans "You are about to xxx machine yyy" %}</h3> |
199 |
<p>{% trans "Are you sure you want to proceed?" %}</p> |
200 |
<button>{% trans "Yes" %}</button> |
201 |
<button>{% trans "No" %}</button> |
202 |
</div>
|
203 |
|
204 |
<script type="text/javascript"> |
205 |
var TIMEOUT = {{timeout}};
|
206 |
</script>
|
207 |
|
208 |
<script>
|
209 |
// hardcoded image types
|
210 |
var image_tags = {
|
211 |
1: 'archlinux',
|
212 |
2: 'centos',
|
213 |
3: 'debian',
|
214 |
4: 'freebsd',
|
215 |
5: 'gentoo',
|
216 |
6: 'netbsd',
|
217 |
7: 'openbsd',
|
218 |
8: 'redhat',
|
219 |
9: 'slackware',
|
220 |
10: 'suse',
|
221 |
11: 'ubuntu',
|
222 |
12: 'windows',
|
223 |
20: 'ubuntu',
|
224 |
};
|
225 |
|
226 |
// ajax error checking
|
227 |
function ajax_error(jqXHR) {;
|
228 |
// prepare the error message
|
229 |
$("#error-success h3").text('{% trans "Error!" %}');
|
230 |
// check the error code
|
231 |
switch (jqXHR.status) {
|
232 |
case 400: // YY error/message
|
233 |
$("#error-success p").text('{% trans "A Bad Request has been made." %}');
|
234 |
break;
|
235 |
case 404: // YY error/message
|
236 |
$("#error-success p").text('{% trans "Your request has failed." %}');
|
237 |
break;
|
238 |
case 501: // XX error/message
|
239 |
$("#error-success p").text('{% trans "There has been an Internal Error. Our administrators have been notified." %}');
|
240 |
break;
|
241 |
case 503: // XX error/message
|
242 |
$("#error-success p").text('{% trans "This service is unavailble right now, please try again later." %}');
|
243 |
break;
|
244 |
default: // XXYY error/message
|
245 |
$("#error-success p").text('{% trans "An Error has happened. Our administrators have been notified." %}');
|
246 |
}
|
247 |
// bring up error notification
|
248 |
var triggers = $("a#notification").overlay({
|
249 |
// some mask tweaks suitable for modal dialogs
|
250 |
mask: {
|
251 |
color: '#ebecff',
|
252 |
opacity: '0.9'
|
253 |
},
|
254 |
top: 'center',
|
255 |
closeOnClick: false,
|
256 |
oneInstance: false,
|
257 |
load: true,
|
258 |
onClose: function(){
|
259 |
$("div.pane#machines-pane").load($("a#standard").attr("href"));
|
260 |
}
|
261 |
});
|
262 |
return false;
|
263 |
}
|
264 |
|
265 |
// ajax success checking
|
266 |
function ajax_success() {
|
267 |
// prepare the error message
|
268 |
$("#error-success h3").text('Success!');
|
269 |
$("#error-success p").text('Your request has been succefully executed.');
|
270 |
// bring up success notification
|
271 |
var triggers = $("a#notification").overlay({
|
272 |
// some mask tweaks suitable for modal dialogs
|
273 |
mask: {
|
274 |
color: '#ebecff',
|
275 |
opacity: '0.9'
|
276 |
},
|
277 |
top: 'center',
|
278 |
closeOnClick: false,
|
279 |
oneInstance: false,
|
280 |
load: true,
|
281 |
onClose: function(){
|
282 |
$("div.pane#machines-pane").load($("a#standard").attr("href"));
|
283 |
}
|
284 |
});
|
285 |
return false;
|
286 |
}
|
287 |
|
288 |
// confirmation overlay generation
|
289 |
function confirm_action(action_string, action_function, serverID, serverName) {
|
290 |
$("#yes-no h3").text('You are about to ' + action_string + ' vm ' + serverName);
|
291 |
// action confirmation overlay
|
292 |
var triggers = $("a#confirmation").overlay({
|
293 |
// some mask tweaks suitable for modal dialogs
|
294 |
mask: {
|
295 |
color: '#ebecff',
|
296 |
opacity: '0.9'
|
297 |
},
|
298 |
top: 'center',
|
299 |
load: true
|
300 |
});
|
301 |
// yes or no?
|
302 |
var buttons = $("#yes-no button").click(function(e) {
|
303 |
// get user input
|
304 |
var yes = buttons.index(this) === 0;
|
305 |
//close the confirmation window
|
306 |
$("a#confirmation").overlay().close();
|
307 |
// return true=yes or false=no
|
308 |
if (yes) {
|
309 |
action_function(serverID);
|
310 |
} else {
|
311 |
// reload page
|
312 |
$("div.pane#machines-pane").load($("a#standard").attr("href"));
|
313 |
}
|
314 |
});
|
315 |
return false;
|
316 |
}
|
317 |
|
318 |
// get and show a list of running and terminated machines
|
319 |
function update_vms() {
|
320 |
|
321 |
$(".running").text('');
|
322 |
$(".terminated").text('');
|
323 |
$("ul#standard-images").text('');
|
324 |
$("ul#custom-images").text('');
|
325 |
|
326 |
$.ajax({
|
327 |
url: '/api/v1.0/servers/detail',
|
328 |
type: "GET",
|
329 |
timeout: TIMEOUT,
|
330 |
dataType: "json",
|
331 |
error: function(jqXHR, textStatus, errorThrown) {
|
332 |
ajax_error(jqXHR);
|
333 |
return false;
|
334 |
},
|
335 |
success: function(data, textStatus, jqXHR) {
|
336 |
if ($(".running a.name").length + $(".terminated a.name").length == 0) {
|
337 |
|
338 |
$.each(data.servers, function(i,server){
|
339 |
// if the machine is deleted it should not be included in any list
|
340 |
if (server.status == 'DELETED') {
|
341 |
return;
|
342 |
}
|
343 |
var machine = $("#machine-template").clone().attr("id", server.id).fadeIn("slow");
|
344 |
machine.find("input[type='checkbox']").attr("id", "input-" + server.id);
|
345 |
machine.find("input[type='checkbox']").attr("class", server.status);
|
346 |
machine.find("a.name span.name").text(server.name);
|
347 |
machine.find("img.logo").attr("src","static/machines/"+image_tags[server.imageId]+'.png');
|
348 |
machine.find("img.list-logo").attr("src","static/os_logos/"+image_tags[server.imageId]+'.png');
|
349 |
machine.find("img.list-logo").attr("title",image_tags[server.imageId]);
|
350 |
machine.find("span.imagetag").text(image_tags[server.imageId]);
|
351 |
|
352 |
machine.find("a.ip span.public").text(String(server.addresses.public.ip.addr).replace(',',' '));
|
353 |
|
354 |
// TODO: handle SHARE_IP, SHARE_IP_NO_CONFIG, DELETE_IP, REBUILD, QUEUE_RESIZE, PREP_RESIZE, RESIZE, VERIFY_RESIZE, PASSWORD, RESCUE
|
355 |
if (server.status == 'BUILD'){
|
356 |
machine.find(".status").text('Building');
|
357 |
machine.appendTo(".running");
|
358 |
} else if (server.status == 'ACTIVE') {
|
359 |
machine.find(".status").text('Running');
|
360 |
machine.appendTo(".running");
|
361 |
} else if (server.status == 'REBOOT' || server.status == 'HARD_REBOOT') {
|
362 |
machine.find(".status").text('Rebooting');
|
363 |
machine.appendTo(".running");
|
364 |
} else if (server.status == 'STOPPED') {
|
365 |
machine.find(".status").text('Stopped');
|
366 |
machine.find("img.logo").attr("src","static/machines/"+image_tags[server.imageId]+'-off.png');
|
367 |
machine.find("img.list-logo").attr("src","static/os_logos/"+image_tags[server.imageId]+'-off.png');
|
368 |
machine.appendTo(".terminated");
|
369 |
} else if (server.status == 'ERROR') {
|
370 |
machine.find(".status").text('Error');
|
371 |
machine.find("img.logo").attr("src","static/machines/"+image_tags[server.imageId]+'-off.png');
|
372 |
machine.find("img.list-logo").attr("src","static/os_logos/"+image_tags[server.imageId]+'-off.png');
|
373 |
machine.appendTo(".terminated");
|
374 |
}
|
375 |
else {
|
376 |
machine.find(".status").text('Unknown');
|
377 |
machine.find("img.logo").attr("src","static/machines/"+image_tags[server.imageId]+'-off.png');
|
378 |
machine.find("img.list-logo").attr("src","static/os_logos/"+image_tags[server.imageId]+'-off.png');
|
379 |
machine.appendTo(".terminated");
|
380 |
}
|
381 |
});
|
382 |
}
|
383 |
$("#spinner").hide();
|
384 |
$("div.machine:last-child").find("div.seperator").hide();
|
385 |
// if the terminated list is populated then the seperator must be shown
|
386 |
if ($(".terminated a.name").length > 0) {
|
387 |
$("#mini.seperator").fadeIn("slow");
|
388 |
}
|
389 |
// creating the table in list view, if there are machines to show
|
390 |
if ($("div.list table.list-machines tbody").length > 0) {
|
391 |
$("div.list table.list-machines").dataTable({
|
392 |
"bInfo": false,
|
393 |
"bPaginate": false,
|
394 |
"bAutoWidth": false,
|
395 |
"bSort": true,
|
396 |
"bStateSave": true,
|
397 |
//"sScrollY": "250px",
|
398 |
//"sScrollX": "500px",
|
399 |
//"sScrollXInner": "480px",
|
400 |
"aoColumnDefs": [
|
401 |
{ "bSortable": false, "aTargets": [ 0 ] }
|
402 |
]
|
403 |
});
|
404 |
$("div.list table.list-machines").show();
|
405 |
$("div.list div.actions").show();
|
406 |
}
|
407 |
}
|
408 |
});
|
409 |
return false;
|
410 |
}
|
411 |
|
412 |
// get and show a list of anvailable standard and custom images
|
413 |
function update_images() {
|
414 |
$.ajax({
|
415 |
url: '/api/v1.0/images/detail',
|
416 |
type: "GET",
|
417 |
//async: false,
|
418 |
dataType: "json",
|
419 |
timeout: TIMEOUT,
|
420 |
error: function(jqXHR, textStatus, errorThrown) {
|
421 |
ajax_error(jqXHR);
|
422 |
},
|
423 |
success: function(data, textStatus, jqXHR) {
|
424 |
if ($("ul#standard-images li").toArray().length + $("ul#custom-images li").toArray().length == 0) {
|
425 |
$.each(data.images, function(i,image){
|
426 |
var img = $('#image-template').clone().attr("id","img-"+image.id).fadeIn("slow");
|
427 |
img.find("label").attr('for',"img-radio-" + image.id);
|
428 |
img.find(".image-title").text(image.name);
|
429 |
img.find(".description").text(image.description);
|
430 |
img.find(".size").text(image.size);
|
431 |
img.find("input.radio").attr('id',"img-radio-" + image.id);
|
432 |
if (i==0) img.find("input.radio").attr("checked","checked");
|
433 |
img.find("img.image-logo").attr('src','static/os_logos/'+image_tags[image.id]+'.png');
|
434 |
if (image.serverId) {
|
435 |
img.appendTo("ul#custom-images");
|
436 |
} else {
|
437 |
img.appendTo("ul#standard-images");
|
438 |
}
|
439 |
});
|
440 |
}
|
441 |
}
|
442 |
});
|
443 |
return false;
|
444 |
}
|
445 |
|
446 |
var flavors = {}, disks = [], cpus = [], ram = [];
|
447 |
|
448 |
Array.prototype.unique = function () {
|
449 |
var r = new Array();
|
450 |
o:for(var i = 0, n = this.length; i < n; i++)
|
451 |
{
|
452 |
for(var x = 0, y = r.length; x < y; x++)
|
453 |
{
|
454 |
if(r[x]==this[i])
|
455 |
{
|
456 |
continue o;
|
457 |
}
|
458 |
}
|
459 |
r[r.length] = this[i];
|
460 |
}
|
461 |
return r;
|
462 |
}
|
463 |
|
464 |
// get and configure flavor selection
|
465 |
function update_flavors() {
|
466 |
$.ajax({
|
467 |
url: '/api/v1.0/flavors/detail',
|
468 |
type: "GET",
|
469 |
//async: false,
|
470 |
dataType: "json",
|
471 |
timeout: TIMEOUT,
|
472 |
error: function(jqXHR, textStatus, errorThrown) {
|
473 |
ajax_error(jqXHR);
|
474 |
},
|
475 |
success: function(data, textStatus, jqXHR) {
|
476 |
flavors = data.flavors;
|
477 |
$.each(flavors, function(i, flavor) {
|
478 |
cpus[i] = flavor['cpu'];
|
479 |
disks[i] = flavor['disk'];
|
480 |
ram[i] = flavor['ram'];
|
481 |
});
|
482 |
cpus = cpus.unique();
|
483 |
disks = disks.unique();
|
484 |
ram = ram.unique();
|
485 |
// sliders for selecting VM flavor
|
486 |
$("#cpu:range").rangeinput({min:0,
|
487 |
value:0,
|
488 |
step:1,
|
489 |
progress: true,
|
490 |
max:cpus.length-1});
|
491 |
|
492 |
$("#storage:range").rangeinput({min:0,
|
493 |
value:0,
|
494 |
step:1,
|
495 |
progress: true,
|
496 |
max:disks.length-1});
|
497 |
|
498 |
$("#ram:range").rangeinput({min:0,
|
499 |
value:0,
|
500 |
step:1,
|
501 |
progress: true,
|
502 |
max:ram.length-1});
|
503 |
$("#small").click();
|
504 |
|
505 |
}
|
506 |
});
|
507 |
return false;
|
508 |
}
|
509 |
// return flavorId from cpu, disk, ram values
|
510 |
function identify_flavor(cpu, disk, ram){
|
511 |
for (i=0;i<flavors.length;i++){
|
512 |
if (flavors[i]['cpu'] == cpu && flavors[i]['disk']==disk && flavors[i]['ram']==ram) {
|
513 |
return flavors[i]['id']
|
514 |
}
|
515 |
}
|
516 |
return 0;
|
517 |
}
|
518 |
|
519 |
// switch to list view
|
520 |
$("#list").click(function(){
|
521 |
$.cookie("list", '1'); // set list cookie
|
522 |
$("div.standard#machinesview").load($("#list").attr("href"));
|
523 |
$("a#standard")[0].className += ' activelink'
|
524 |
this.style.color = '#5f8dd3';
|
525 |
update_vms();
|
526 |
return false;
|
527 |
});
|
528 |
|
529 |
// switch to standard view
|
530 |
$("a#standard").click(function(){
|
531 |
$.cookie("list", '0');
|
532 |
href=$("a#standard").attr("href");
|
533 |
$("div.pane#machines-pane").load(href);
|
534 |
return false;
|
535 |
});
|
536 |
|
537 |
// redirect to list view if the list cookie is set
|
538 |
if ($.cookie("list") == '1') {
|
539 |
$("#list").click();
|
540 |
} else {
|
541 |
// execute the update function to populate the list
|
542 |
update_vms();
|
543 |
}
|
544 |
|
545 |
// launch VM creation wizard
|
546 |
$("a#create").click(function(){
|
547 |
// populate image list
|
548 |
update_images();
|
549 |
// configure flavors
|
550 |
update_flavors();
|
551 |
// launch the wizard
|
552 |
$("#wizard").scrollable().begin();
|
553 |
});
|
554 |
|
555 |
// create wizard overlay
|
556 |
$(function() {
|
557 |
$("a#create").overlay({
|
558 |
mask: '#000',
|
559 |
effect: 'default',
|
560 |
top: '5%',
|
561 |
oneInstance: false,
|
562 |
closeOnClick: false
|
563 |
});
|
564 |
});
|
565 |
|
566 |
// wizard
|
567 |
$(function() {
|
568 |
var root = $("#wizard").scrollable();
|
569 |
|
570 |
// some variables that we need
|
571 |
var api = root.scrollable();
|
572 |
|
573 |
// rangeinput with default configuration
|
574 |
// validation logic is done inside the onBeforeSeek callback
|
575 |
api.onBeforeSeek(function(event, i) {
|
576 |
// we are going 1 step backwards so no need for validation
|
577 |
if (api.getIndex() < i) {
|
578 |
// 1. get current page
|
579 |
var page = root.find(".page").eq(api.getIndex()),
|
580 |
// 2. .. and all required fields inside the page
|
581 |
inputs = page.find(".required :input").removeClass("error"),
|
582 |
// 3. .. which are empty
|
583 |
empty = inputs.filter(function() {
|
584 |
return $(this).val().replace(/\s*/g, '') == '';
|
585 |
});
|
586 |
// if there are empty fields, then
|
587 |
if (empty.length) {
|
588 |
// add a CSS class name "error" for empty & required fields
|
589 |
empty.addClass("error");
|
590 |
// cancel seeking of the scrollable by returning false
|
591 |
return false;
|
592 |
// everything is good
|
593 |
}
|
594 |
}
|
595 |
// update status bar
|
596 |
$("#status li").removeClass("active").eq(i).addClass("active");
|
597 |
|
598 |
// update confirm step
|
599 |
var image = $("input[type=radio][name=image-id]:checked");
|
600 |
var imageId = image.length ? image[0].id : false
|
601 |
if (imageId) {
|
602 |
var imageName = $("label[for=" + imageId + "] .image-title").text();
|
603 |
$("#machine_image-label")[0].textContent = imageName;
|
604 |
$("input[type=text][name=machine_name]")[0].value = "My " + imageName + " server";
|
605 |
}
|
606 |
$("#machine_cpu-label")[0].textContent = $("#cpu-indicator")[0].value;
|
607 |
$("#machine_ram-label")[0].textContent = $("#ram-indicator")[0].value;
|
608 |
$("#machine_storage-label")[0].textContent = $("#storage-indicator")[0].value;
|
609 |
|
610 |
});
|
611 |
|
612 |
// if tab is pressed on the next button seek to next page
|
613 |
root.find("button.next").keydown(function(e) {
|
614 |
if (e.keyCode == 9) {
|
615 |
// seeks to next tab by executing our validation routine
|
616 |
api.next();
|
617 |
e.preventDefault();
|
618 |
}
|
619 |
});
|
620 |
|
621 |
});
|
622 |
|
623 |
// disable sliders in flavor selection
|
624 |
function disableSliders() {
|
625 |
$("#cpu").attr('disabled',true);
|
626 |
$("#ram").attr('disabled',true);
|
627 |
$("#storage").attr('disabled',true);
|
628 |
}
|
629 |
|
630 |
// selecting the small size
|
631 |
$("#small").click(function(){
|
632 |
$("#cpu").data('rangeinput').setValue(0);
|
633 |
$("#ram").data('rangeinput').setValue(0);
|
634 |
$("#storage").data('rangeinput').setValue(0);
|
635 |
$("#cpu-indicator")[0].value = cpus[0];
|
636 |
$("#ram-indicator")[0].value = ram[0];
|
637 |
$("#storage-indicator")[0].value = disks[0];
|
638 |
});
|
639 |
|
640 |
// selecting the medium size
|
641 |
$("#medium").click(function(){
|
642 |
$("#cpu").data('rangeinput').setValue(1);
|
643 |
$("#ram").data('rangeinput').setValue(1);
|
644 |
$("#storage").data('rangeinput').setValue(1);
|
645 |
$("#cpu-indicator")[0].value = cpus[1];
|
646 |
$("#ram-indicator")[0].value = ram[1];
|
647 |
$("#storage-indicator")[0].value = disks[1];
|
648 |
});
|
649 |
|
650 |
// selecting the large size
|
651 |
$("#large").click(function(){
|
652 |
$("#cpu").data('rangeinput').setValue(2);
|
653 |
$("#ram").data('rangeinput').setValue(2);
|
654 |
$("#storage").data('rangeinput').setValue(2);
|
655 |
$("#cpu-indicator")[0].value = cpus[2];
|
656 |
$("#ram-indicator")[0].value = ram[2];
|
657 |
$("#storage-indicator")[0].value = disks[2];
|
658 |
});
|
659 |
|
660 |
// selecting the custom flavor enables the sliders
|
661 |
$("#custom").click(function(){
|
662 |
$("#cpu").attr('disabled',false);
|
663 |
$("#ram").attr('disabled',false);
|
664 |
$("#storage").attr('disabled',false);
|
665 |
$("strong.sliders").style = 'color: #778899;';
|
666 |
});
|
667 |
|
668 |
// get cpu value for custom flavor
|
669 |
$("#cpu:range").change(function(event, value){
|
670 |
$("#custom").click();
|
671 |
// update cpu indicator
|
672 |
$("#cpu-indicator")[0].value = cpus[Number(value)];
|
673 |
});
|
674 |
|
675 |
// get ram value for custom flavor
|
676 |
$("#ram:range").change(function(event, value){
|
677 |
$("#custom").click();
|
678 |
// update ram indicator
|
679 |
$("#ram-indicator")[0].value = ram[Number(value)];
|
680 |
});
|
681 |
|
682 |
// get storage value for custom flavor
|
683 |
$("#storage:range").change(function(event, value){
|
684 |
$("#custom").click();
|
685 |
// update disk indicator
|
686 |
$("#storage-indicator")[0].value = disks[Number(value)];
|
687 |
return false;
|
688 |
});
|
689 |
|
690 |
// exit the wizard
|
691 |
$("#cancel").click(function(){
|
692 |
$("a#create").overlay().close();
|
693 |
});
|
694 |
|
695 |
// starting a new VM through the wizard
|
696 |
$("#start").click(function(){
|
697 |
//TODO: get the real data
|
698 |
var flavorId = identify_flavor($("#cpu-indicator")[0].value, $("#storage-indicator")[0].value, $("#ram-indicator")[0].value);
|
699 |
var payload = {
|
700 |
"server": {
|
701 |
"name": "image-name",
|
702 |
"imageId": 1,
|
703 |
"flavorId" : flavorId,
|
704 |
"metadata" : {
|
705 |
"My Server Name" : $("input[name=machine_name]")[0].value
|
706 |
},
|
707 |
}
|
708 |
};
|
709 |
|
710 |
$.ajax({
|
711 |
url: "/api/v1.0/servers",
|
712 |
type: "POST",
|
713 |
dataType: "json",
|
714 |
data: JSON.stringify(payload),
|
715 |
timeout: TIMEOUT,
|
716 |
error: function(jqXHR, textStatus, errorThrown) {
|
717 |
ajax_error(jqXHR);
|
718 |
},
|
719 |
success: function(data, textStatus, jqXHR) {
|
720 |
if ( jqXHR.status == '202') {
|
721 |
ajax_success(jqXHR);
|
722 |
} else {
|
723 |
ajax_error(jqXHR);
|
724 |
}
|
725 |
}
|
726 |
});
|
727 |
console.warn('creating ' + $("input[name=machine_name]")[0].value)
|
728 |
|
729 |
$("#wizard").hide();
|
730 |
});
|
731 |
|
732 |
// reboot action
|
733 |
function reboot(serverID){
|
734 |
// ajax post reboot call
|
735 |
var payload = {
|
736 |
"reboot": {"type" : "HARD"}
|
737 |
};
|
738 |
|
739 |
$.ajax({
|
740 |
url: '/api/v1.0/servers/' + serverID + '/action',
|
741 |
type: "POST",
|
742 |
dataType: "json",
|
743 |
data: JSON.stringify(payload),
|
744 |
timeout: TIMEOUT,
|
745 |
error: function(jqXHR, textStatus, errorThrown) {
|
746 |
ajax_error(jqXHR);
|
747 |
},
|
748 |
success: function(data, textStatus, jqXHR) {
|
749 |
if ( jqXHR.status == '202') {
|
750 |
ajax_success(jqXHR);
|
751 |
} else {
|
752 |
ajax_error(jqXHR);
|
753 |
}}
|
754 |
});
|
755 |
console.warn('rebooting ' + serverID);
|
756 |
return false;
|
757 |
}
|
758 |
|
759 |
// shutdown action
|
760 |
function shutdown(serverID) {
|
761 |
// ajax post shutdown call
|
762 |
var payload = {
|
763 |
"shutdown": {"timeout" : "5"}
|
764 |
};
|
765 |
|
766 |
$.ajax({
|
767 |
url: '/api/v1.0/servers/' + serverID + '/action',
|
768 |
type: "POST",
|
769 |
dataType: "json",
|
770 |
data: JSON.stringify(payload),
|
771 |
timeout: TIMEOUT,
|
772 |
error: function(jqXHR, textStatus, errorThrown) {
|
773 |
ajax_error(jqXHR);
|
774 |
},
|
775 |
success: function(data, textStatus, jqXHR) {
|
776 |
if ( jqXHR.status == '202') {
|
777 |
ajax_success(jqXHR);
|
778 |
} else {
|
779 |
ajax_error(jqXHR);
|
780 |
}}
|
781 |
});
|
782 |
console.warn('shutting down ' + serverID);
|
783 |
return false;
|
784 |
}
|
785 |
|
786 |
|
787 |
// start action
|
788 |
function start(serverID){
|
789 |
// ajax post start call
|
790 |
var payload = {
|
791 |
"start": {"type" : "NORMAL"}
|
792 |
};
|
793 |
|
794 |
$.ajax({
|
795 |
url: '/api/v1.0/servers/' + serverID + '/action',
|
796 |
type: "POST",
|
797 |
dataType: "json",
|
798 |
data: JSON.stringify(payload),
|
799 |
timeout: TIMEOUT,
|
800 |
error: function(jqXHR, textStatus, errorThrown) {
|
801 |
ajax_error(jqXHR);
|
802 |
},
|
803 |
success: function(data, textStatus, jqXHR) {
|
804 |
if ( jqXHR.status == '202') {
|
805 |
ajax_success(jqXHR);
|
806 |
} else {
|
807 |
ajax_error(jqXHR);
|
808 |
}}
|
809 |
});
|
810 |
console.warn('starting ' + serverID);
|
811 |
return false;
|
812 |
}
|
813 |
|
814 |
|
815 |
// basic functions executed on page load
|
816 |
|
817 |
// create tabs for main menu
|
818 |
$("ul.tabs").tabs("div.panes ul");
|
819 |
|
820 |
// intercept reboot click
|
821 |
$("div.actions a.action-reboot").live('click', function(){
|
822 |
var serverID = $(this).parent().parent().attr("id");
|
823 |
var serverName = $(this).parent().prevAll("a.name").find("span.name").text();
|
824 |
confirm_action('reboot', reboot, serverID, serverName);
|
825 |
return false;
|
826 |
});
|
827 |
|
828 |
// intercept shutdown click
|
829 |
$("div.actions a.action-shutdown").live('click', function(){
|
830 |
var serverID = $(this).parent().parent().attr("id");
|
831 |
var serverName = $(this).parent().prevAll("a.name").find("span.name").text();
|
832 |
confirm_action('shutdown', shutdown, serverID, serverName);
|
833 |
return false;
|
834 |
});
|
835 |
// intercept start click
|
836 |
$("div.actions a.action-start").live('click', function(){
|
837 |
var serverID = $(this).parent().parent().attr("id");
|
838 |
var serverName = $(this).parent().prevAll("a.name").find("span.name").text();
|
839 |
confirm_action('start', start, serverID, serverName);
|
840 |
return false;
|
841 |
});
|
842 |
</script>
|