Statistics
| Branch: | Tag: | Revision:

root / ui / templates / machines.html @ afa2ebd2

History | View | Annotate | Download (19.7 kB)

1
{% load i18n %}
2

    
3
<div id="machines" class="separator"></div>
4

    
5
<!-- the create button -->
6
<div id="createcontainer">
7
    <span id="createbody">{% trans "Start by creating a new Virtual Machine:" %}</span><br />
8
    <a id="create" rel="#wizard" href="#">{% trans "Create New +" %}</a>
9
</div>
10

    
11
<!-- changing between standard/list view -->
12
<div id="view-select">
13
    <a id="standard" href="/machines/standard">#</a>
14
    <span class="view-separator">|</span>
15
    <a id="list" href="/machines/list">=</a>
16
</div>
17

    
18
<div id="emptymachineslist"><h1 id="welcomeheader">{% trans "Welcome to the ocean!" %}</h1><br />
19
    <span class="welcomebody">{% trans "From this panel you will be able to manage your Virtual Machines (VMs). If you don't know what a VM is: take the " %}<a href="#">{% trans "tour" %}</a>.</span><br /><br />
20
    <span class="welcomebody">{% trans "The panel is currently empty, because you don't have any VMs yet. You can start by creating your new VM by clicking the blue button on the right. The wizard will guide you through the hole process." %}</span><br /><br />
21
    <span class="welcomefooter">{% trans "For more information or help, click " %}<a href="#">{% trans "here" %}</a>.</span>
22
</div>
23

    
24
<!-- the form -->
25
<form action="#">
26
        <!-- scrollable root element -->
27
        <div class="modal" id="wizard">
28
                <!-- status bar -->
29
                <ul id="status">
30
                        <li class="active"><span class="headernumber" class="first">1</span><div class="headerbody first">{% trans "Image" %}</div></li>
31
                        <li><span class="headernumber">2</span><div class="headerbody">{% trans "Flavor" %}</div></li>
32
                        <li><span class="headernumber">3</span><div class="headerbody">{% trans "Name" %}</div></li>
33
                </ul>
34
                <!-- scrollable items -->
35
                <div class="items">
36
                        <!-- pages -->
37
                        <div class="page">
38
                <h2>{% trans "Select an OS" %}</h2>
39
                <hr class="topruler" />
40
                <ul class="tabs">
41
                    <li><a href="#">{% trans "system images" %}</a></li>
42
                    <li><a href="#">{% trans "your images" %}</a></li>
43
                </ul>
44
                <div class="panes">
45
                            <li id="image-template" style="display:none">
46
                                    <label for="image.id"> 
47
                            <a>
48
                                <div class="image-container">
49
                                    <div class="image">
50
                                        <input class="radio" type="radio" name="imageGroup" id="image-id" />
51
                                        <img src="" class="image-logo"/>
52
                                        <strong class="image-title">image.title</strong>
53
                                        <br />
54
                                        <span class="description">image.description</span> 
55
                                        <span id="size" class="size">?? MB</span><span class="size">MB</span>                         
56
                                    </div>
57
                                </div>  
58
                            </a>
59
                                    </label>
60
                            </li>
61
                    <ul class="pane" id="standard-images">
62
                                            <!-- standard images -->
63
                                    </ul>
64
                    <ul class="pane" id="custom-images">
65
                                            <!-- custom images -->
66
                    </ul>
67
                </div>
68
                <hr class="bottomruler" />
69
                                <button type="button" class="prev" id="cancel">{% trans "Cancel" %}</button>
70
                                <button type="button" class="next right">{% trans "Next" %}</button>
71
            </div>
72
                        <div class="page">
73
                                <h2>{% trans "Select CPUs, RAM and Disk Size" %}</h2>
74
                <hr class="topruler" />
75
                <ul>
76
                    <li id="machinetype">
77
                        <div class="machine-type">
78
                            <label for="small" id="small">
79
                                <input type="radio" id="small" name="machine-type" value="small" checked="true" />
80
                                <span class="typebody" id="small-body">{% trans "small" %}</span>
81
                            </label>
82
                        </div>
83
                        <div class="machine-type">      
84
                            <label for="medium" id="medium">
85
                                <input type="radio" id="medium" name="machine-type" value="medium" />                  
86
                                <span class="typebody" id="medium-body">{% trans "medium" %}</span>
87
                            </label>
88
                        </div>
89
                        <div class="machine-type">
90
                            <label for="large" id="large">
91
                                <input type="radio" id="large" name="machine-type" value="large" />
92
                                <span class="typebody" id="large-body">{% trans "large" %}</span>
93
                            </label>
94
                        </div>
95
                        <div class="machine-type">
96
                            <label for="custom" id="custom">
97
                                <input type="radio" name="machine-type" id="custom" value="large" />
98
                                <span class="typebody" id="custom-body">{% trans "custom" %}</span>
99
                            </label>
100
                        </div>
101
                    </li>
102
                    <div id="page2-container">
103
                        <li class="slider-container">
104
                                        <label><strong class="sliders">CPUs</strong></label>
105
                            <input type="range" id="cpu" style="display:none" />
106
                            <input type="text" class="range" id="cpu-indicator" />
107
                                        <span class="units">cores</span>
108
                        </li>
109
                        <li class="slider-container">
110
                                        <label><strong class="sliders">RAM</strong></label>
111
                            <input type="range" id="ram" style="display:none" />
112
                            <input type="text" class="range" id="ram-indicator" />
113
                                        <span class="units">MB</span>
114
                        </li>
115
                        <li class="slider-container">
116
                                    <label><strong class="sliders">Size</strong></label>
117
                            <input type="range" id="storage" style="display:none" />
118
                            <input type="text" class="range" id="storage-indicator" />
119
                                        <span class="units">GB</span>
120
                        </li>
121
                        <li>
122
                            <div class="cost">
123
                                <span> {% trans "Your wallet:" %} 10,000 Credits </span> | <span>{% trans "This setup will cost you:" %}<input type="text" id="credits-indicator" value="20" class="range" />{% trans "C/hour" %}</span>
124
                            </div>
125
                        </li>
126
                    </div>
127
                </ul>
128
                <hr class="bottomruler" />
129
                                <button type="button" class="prev">{% trans "Back" %}</button>
130
                                <button type="button" class="next right">{% trans "Next" %}</button>
131
            </div>
132
                        <div class="page">
133
                                <h2>{% trans "Confirm your settings" %}</h2>
134
                <hr class="topruler" />
135
                <ul id="page3-container">
136
                    <li class="required" id="label-name">
137
                        <label>
138
                            <strong>Name:</strong>
139
                            <input type="text" class="text" name="machine_name" id="name" value="My Ubuntu 10.04 x86_64 server"/>
140
                        </label>
141
                    </li>
142
                    <li>
143
                        <span>{% trans "Image:" %}</span> <span id="machine_image-label">Ubuntu 10.04 x86_64 server</span>
144
                    </li>
145
                    <li>
146
                        <span>{% trans "CPUs:" %}</span> <span id="machine_cpu-label">2</span> <span>{% trans "cores" %}</span>
147
                    </li>
148
                    <li>
149
                        <span>{% trans "RAM:" %}</span> <span id="machine_ram-label">1024</span><span>MB</span>
150
                    </li>
151
                    <li>
152
                        <span>{% trans "System Disk:" %}</span> <span id="machine_storage-label">10</span><span>GB</span>
153
                    </li>
154
                    <li>
155
                        <span>{% trans "Cost per Hour:" %}</span> <span>40 {% trans "credits" %}</span>
156
                    </li>
157
                    <li>
158
                        <span>{% trans "Credits in Wallet:" %}</span> <span>10.000</span>
159
                    </li>
160
                </ul>
161
                <hr class="bottomruler" />
162
                                <button type="button" class="prev">{% trans "Back" %}</button>
163
                                <button type="button" class="next right" id="start">{% trans "Create VM" %}</button>        
164
            </div>
165
                </div>
166
        </div>
167
</form>
168

    
169
<!-- notification after wizard completion -->
170
<a id="notification" rel="#error-success" href="#"></a>
171

    
172
<div class="modal" id="error-success">
173
    <h3>{% trans "Error!/Success!" %}</h3>
174
    <div><p>{% trans "More details about the result"%}</p></div>
175
</div>
176

    
177
<!-- confirmation before executing an action -->
178
<a id="confirmation" rel="#yes-no" href="#"></a>
179

    
180
<div class="modal" id="yes-no">
181
    <h3>{% trans "You are about to xxx machine yyy" %}</h3>
182
    <p>{% trans "Are you sure you want to proceed?" %}</p>
183
    <button>{% trans "Yes" %}</button>
184
        <button>{% trans "No" %}</button>
185
</div>
186

    
187
<div id="machinesview"></div>
188

    
189
<div class="confirm_multiple">
190
    <p>{% trans "Your actions will affect" %} <span class="actionLen">XX</span> {% trans "machines" %}</p>
191
    <button class="yes">{% trans "Confirm All" %}</button>
192
        <button class="no">{% trans "Cancel All" %}</button>
193
</div>
194

    
195
<div id="machines" class="separator"></div>
196

    
197
<script>
198
//add hover to labels
199
$('span.typebody').mouseover(function() {
200
    $(this).addClass('typehover')
201
});
202
$('span.typebody').mouseout(function() {
203
    $(this).removeClass('typehover')
204
});
205

206
// return value from metadata key "OS", if it exists
207
function os_icon(metadata) {
208
    if (!metadata) {
209
        return 'unknown';
210
    }
211

212
    if (metadata.values.OS == undefined || metadata.values.OS == '') {
213
        return 'unknown';
214
    } else {
215
        return metadata.values.OS;
216
    }
217
} 
218

219
// switch to list view
220
$("a#list").click(function(){
221
    list_view(); 
222
    return false;
223
});
224

225

226
// switch to standard view
227
$("a#standard").click(function(){
228
    standard_view();
229
    return false;
230
});
231

232
// launch VM creation wizard
233
$("a#create").click(function(){
234
    // launch wizard only if images and flavors are found
235
    if (images.length > 0  && flavors.length > 0) {
236
        $("#wizard").scrollable().begin();
237
        $("#wizard").show();
238
        $('a#create').data('overlay').load()   
239
    } else if (images.length == 0 ) {
240
        ajax_error('NO_IMAGES');
241
        return false;   
242
    } else if (flavors.length == 0) {
243
        ajax_error('NO_FLAVORS');
244
        return false;
245
    }
246
});
247

248
// create wizard overlay
249
$(function() { 
250
    $("a#create").overlay({
251
        mask: '#000', 
252
        effect: 'default', 
253
        top: '5%', 
254
        oneInstance: false,
255
        closeOnClick: false
256
    });
257
});
258

259
// wizard
260
$(function() {
261
    var root = $("#wizard").scrollable();
262
    var api = root.scrollable();
263
    // rangeinput with default configuration
264
    // validation logic is done inside the onBeforeSeek callback
265
    api.onBeforeSeek(function(event, i) {
266
            // we are going 1 step backwards so no need for validation
267
            if (api.getIndex() < i) {
268
             // 1. get current page
269
                     var page = root.find(".page").eq(api.getIndex()),
270
                         // 2. .. and all required fields inside the page
271
                         inputs = page.find(".required :input").removeClass("error"),
272
                         // 3. .. which are empty
273
                         empty = inputs.filter(function() {
274
                                return $(this).val().replace(/\s*/g, '') == '';
275
                         });
276
                     // if there are empty fields, then
277
                    if (empty.length) {
278
                            // add a CSS class name "error" for empty & required fields
279
                            empty.addClass("error");
280
                            // cancel seeking of the scrollable by returning false
281
                            return false;
282
                    // everything is good
283
                    } 
284
            }
285
            // update status bar
286
            $("#status li").removeClass("active").eq(i).addClass("active");
287
        // update confirm step
288
        if (api.getIndex()==0) {
289
            var image = $("input[type=radio][name=image-id]:checked");
290
            var imageRef = image.length ? image[0].id : false
291
            if (imageRef) {
292
                var imageName = $("label[for=" + imageRef + "] .image-title").text();
293
                $("#machine_image-label")[0].textContent = imageName;
294
                $("input[type=text][name=machine_name]")[0].value = "My " + imageName + " server";
295
            }
296
        } else if (api.getIndex()==1) {
297
            $("#machine_cpu-label")[0].textContent = $("#cpu-indicator")[0].value;
298
            $("#machine_ram-label")[0].textContent = $("#ram-indicator")[0].value;
299
            $("#machine_storage-label")[0].textContent = $("#storage-indicator")[0].value;
300
        }    
301
    });
302
    // if tab is pressed on the next button seek to next page
303
    root.find("button.next").keydown(function(e) {
304
            if (e.keyCode == 9) {
305
                    // seeks to next tab by executing our validation routine
306
                    api.next();
307
                    e.preventDefault();
308
            }
309
    });
310
    $("#name").keypress(function (e) {
311
                if ((e.which && e.which == 13) || (e.keyCode && e.keyCode == 13)) {
312
                        $('#start').click();
313
                        return false;
314
                } else {
315
                        return true;
316
                }
317
    });
318
});
319

320
// disable sliders in flavor selection
321
function disableSliders() {
322
    $("#cpu").attr('disabled',true);
323
    $("#ram").attr('disabled',true);
324
    $("#storage").attr('disabled',true);
325
}
326

327
if($('.radio:checked').val() == 'true')  {
328
    $(this).parent().addClass('selecteddiv');
329
}
330

331
//update radio button when clicking on text
332
$("#small-body").live('click' ,function() { 
333
    $(this).parent().find("#small").click();
334
});
335
$("#medium-body").live('click' ,function() { 
336
    $(this).parent().find("#medium").click();
337
});
338
$("#large-body").live('click' ,function() { 
339
    $(this).parent().find("#large").click();
340
});
341
$("#custom-body").live('click' ,function() { 
342
    $(this).parent().find("#custom").click();
343
});
344

345
//select image div on radio button select
346
$('.radio').live('click' ,function() {           
347
    $(this).parents("div").find(".image").removeClass('selecteddiv');
348
    if($(this).is(':checked'))  {
349
        $(this).parent().addClass('selecteddiv');
350
    }
351
});
352

353
// confirm all actions
354
$("div.confirm_multiple .yes").live('click', function(){
355
    while(pending_actions.length > 0){ // if there is a pending action for this server execute it
356
        action = pending_actions.pop(); // extract action
357
        var serverID = action[1];
358
        if ($.cookie("list") != '1') { // standard view
359
            $('#' + serverID + ' .selected').removeClass('selected');
360
            $('#' + serverID + ' .display').removeClass('display');
361
            if (action[0] == shutdown) {
362
                $('#' + serverID + ' .status').text('Shutting down');
363
            } else if (action[0] == start) {
364
                $('#' + serverID + ' .status').text('Starting');
365
            }
366
            $('#' + serverID + ' .spinner').show();
367
        } else { // list view
368
            osIcon = $('#'+serverID).parent().parent().find('.list-logo');
369
            osIcon.attr('os',osIcon.attr('src'));
370
            osIcon.attr('src','static/progress.gif');
371
        }
372
        action[0]([serverID]); // execute action
373
    }
374
    update_confirmations();    
375
});
376

377
// cancel all actions
378
$("div.confirm_multiple .no").live('click', function(){
379
    pending_actions = [];
380
    $('.machine .selected').removeClass('selected');
381
    $('.machine .display').removeClass('display');
382
    update_confirmations();
383
});
384

385
// validate cpu input box
386
$("#cpu-indicator").live('change',function(){
387
    var v = Number(this.value);
388
    var i = cpus.indexOf(v);
389
    if (isNaN(v)) {
390
        $(this).value = cpus[0];
391
        $("#cpu").data('rangeinput').setValue(0);
392
    } else if (i == -1) {
393
        for (var j=0; j < cpus.length; j++)
394
            if (v<cpus[j])
395
                break;
396
        $("#cpu").data('rangeinput').setValue(j);
397
    } else {
398
        $("#cpu").data('rangeinput').setValue(i);
399
    }   
400
    return false;
401
});
402

403
// validate ram input box
404
$("#ram-indicator").live('change',function(){
405
    var v = Number(this.value);
406
    var i = ram.indexOf(v);
407
    if (isNaN(v)) {
408
        $(this).value = cpus[0];
409
        $("#ram").data('rangeinput').setValue(0);
410
    } else if (i == -1) {
411
        for (var j=0; j < ram.length; j++)
412
            if (v<ram[j])
413
                break;
414
        $("#ram").data('rangeinput').setValue(j);
415
    } else {
416
        $("#ram").data('rangeinput').setValue(i);
417
    }   
418
    return false;
419
});
420

421

422
// validate storage input box
423
$("#storage-indicator").live('change',function(){
424
    var v = Number(this.value);
425
    var i = disks.indexOf(v);
426
    if (isNaN(v)) {
427
        $(this).value = disks[0];
428
        $("#storage").data('rangeinput').setValue(0);
429
    } else if (i == -1) {
430
        for (var j=0; j < disks.length; j++)
431
            if (v<disks[j])
432
                break;
433
        $("#storage").data('rangeinput').setValue(j);
434
    } else {
435
        $("#storage").data('rangeinput').setValue(i);
436
    }   
437
    return false;
438
});
439

440
// selecting the small size
441
$("#small").click(function(){
442
    $("#cpu").data('rangeinput').setValue(0);
443
    $("#ram").data('rangeinput').setValue(0);
444
    $("#storage").data('rangeinput').setValue(0);
445
    $("#cpu-indicator")[0].value = cpus[0];
446
    $("#ram-indicator")[0].value = ram[0];
447
    $("#storage-indicator")[0].value = disks[0];
448
    $("#small").addClass("active");
449
    $("#medium").removeClass("active");    
450
    $("#large").removeClass("active");    
451
    $("#custom").removeClass("active");    
452
});
453

454
// selecting the medium size
455
$("#medium").click(function(){
456
    $("#cpu").data('rangeinput').setValue(1);
457
    $("#ram").data('rangeinput').setValue(1);
458
    $("#storage").data('rangeinput').setValue(1);
459
    $("#cpu-indicator")[0].value = cpus[1];
460
    $("#ram-indicator")[0].value = ram[1];
461
    $("#storage-indicator")[0].value = disks[1];  
462
    $("#medium").addClass("active");  
463
    $("#small").removeClass("active");    
464
    $("#large").removeClass("active");    
465
    $("#custom").removeClass("active");  
466
});
467

468
// selecting the large size
469
$("#large").click(function(){
470
    $("#cpu").data('rangeinput').setValue(2);
471
    $("#ram").data('rangeinput').setValue(2);
472
    $("#storage").data('rangeinput').setValue(2);
473
    $("#cpu-indicator")[0].value = cpus[2];
474
    $("#ram-indicator")[0].value = ram[2];
475
    $("#storage-indicator")[0].value = disks[2];   
476
    $("#large").addClass("active"); 
477
    $("#medium").removeClass("active");    
478
    $("#small").removeClass("active");    
479
    $("#custom").removeClass("active");  
480
});
481

482
// selecting the custom flavor enables the sliders
483
$("#custom").click(function(){
484
    $("#cpu").attr('disabled',false);
485
    $("#ram").attr('disabled',false);
486
    $("#storage").attr('disabled',false);
487
    $("strong.sliders").style = 'color: #778899;';
488
    $("#custom").addClass("active"); 
489
    $("#medium").removeClass("active");    
490
    $("#large").removeClass("active");    
491
    $("#small").removeClass("active");  
492
});
493

494
// exit the wizard
495
$("#cancel").click(function(){
496
    $("a#create").overlay().close();
497
});
498

499
// starting a new VM through the wizard
500
$("#start").click(function(){
501
    var imageRef = $('input[type=radio][name=image-id]:checked')[0].id.replace('img-radio-','');   
502
    var flavorRef = identify_flavor($("#cpu-indicator")[0].value, $("#storage-indicator")[0].value, $("#ram-indicator")[0].value);
503
    var machineName = $('input[name=machine_name]')[0].value;
504

505
    create_vm(machineName, imageRef, flavorRef);
506

507
    $('a#create').data('overlay').close();
508
    $("#emptymachineslist").hide();
509

510
    try{console.warn('creating ' + $("input[name=machine_name]")[0].value)} catch(err){}
511

512
    $("#wizard").hide();
513
});
514

515
// basic functions executed on page load
516
if (images.length > 0) {
517
    // populate image list
518
    update_wizard_images();
519
}
520
if (flavors.length > 0) {
521
    // configure flavors
522
    update_wizard_flavors(); 
523
}
524
// create tabs for main menu
525
$("ul.tabs").tabs("div.panes ul");
526

    
527
</script>