Statistics
| Branch: | Tag: | Revision:

root / ui / templates / machines.html @ aa1e0cab

History | View | Annotate | Download (21.6 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
    <a id="list" href="/machines/list"></a>
15
    <a id="single" href="#"></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 class="third"><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 "custom 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="image-id" 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
<!-- base notification for error/success reporting -->
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

    
178
<a id="meta-editor-1" rel="#editor-1" href="#"></a>
179

    
180
<div class="modal" id="editor-1">
181
    <h3>
182
        <label>{% trans "Metadata for machine:" %}<label>
183
        <span></span>
184
    </h3>
185
    <hr class="topruler" />
186
    <div class="meta-list">
187
        <ul>
188
            <li class="meta-template">
189
                <label>{% trans "Metadata key" %}</label>
190
                <button type="button" class="remove">{% trans "remove x" %}</button>
191
                <hr class="meta-separator">
192
                <p>{% trans "Metadata value" %}</p>
193
                <button type="button" class="edit">{% trans "edit" %}</button>
194
            </li>
195
        </ul>
196
    </div>
197
    <button type="button" class="create">{% trans "Create New+" %}</button>
198
    <hr class="bottomruler" /> 
199
</div>
200

    
201
<a id="meta-editor-2" rel="#editor-2" href="#"></a>
202

    
203
<div class="modal" id="editor-2">
204
    <h3>
205
        <label>{% trans "Metadata for machine:" %}<label>
206
        <span></span>
207
    </h3>
208
    <hr class="topruler" />
209
    <hr class="fatruler" />
210
    <label class="meta-key">{% trans "Key:" %}</label>
211
    <input type="text" maxlength="15" class="key" value="max 15 characters"/>
212
    <hr class="meta-separator">
213
    <label class="meta-value">{% trans "Value:" %}</label>
214
    <input type="text" maxlength="150" class="value" value="max 150 characters"/>
215
    <button type="button" class="cancel">{% trans "Cancel" %}</button>
216
    <button type="button" class="save">{% trans "Save" %}</button>
217
    <hr class="bottomruler" /> 
218
</div>
219

    
220
<div id="machinesview"></div>
221

    
222
<div class="confirm_multiple">
223
    <p>{% trans "Your actions will affect" %} <span class="actionLen">XX</span> {% trans "machines" %}</p>
224
    <button class="yes">{% trans "Confirm All" %}</button>
225
        <button class="no">{% trans "Cancel All" %}</button>
226
</div>
227

    
228
<div id="machines" class="separator"></div>
229

    
230
<script>
231
//add hover to labels
232
$('span.typebody').mouseover(function() {
233
    $(this).addClass('typehover');
234
});
235
$('span.typebody').mouseout(function() {
236
    $(this).removeClass('typehover');
237
});
238

239
// return value from metadata key "OS", if it exists
240
function os_icon(metadata) {
241
    if (!metadata) {
242
        return 'unknown';
243
    }
244

245
    if (metadata.values.OS == undefined || metadata.values.OS == '') {
246
        return 'unknown';
247
    } else {
248
        return metadata.values.OS;
249
    }
250
} 
251

252
// switch to list view
253
$("a#list").click(function(){
254
    list_view(); 
255
    return false;
256
});
257

258
// switch to standard view
259
$("a#standard").click(function(){
260
    standard_view();
261
    return false;
262
});
263

264
// launch VM creation wizard
265
$("a#create").click(function(){
266
    // launch wizard only if images and flavors are found
267
    if (images.length > 0  && flavors.length > 0) {
268
        $("#wizard").scrollable().begin();
269
        $("#wizard").show();
270
        $('a#create').data('overlay').load()   
271
    } else if (images.length == 0 ) {
272
        ajax_error('NO_IMAGES');
273
        return false;   
274
    } else if (flavors.length == 0) {
275
        ajax_error('NO_FLAVORS');
276
        return false;
277
    }
278
});
279

280
// create wizard overlay
281
$(function() { 
282
    $("a#create").overlay({
283
        mask: '#000', 
284
        effect: 'default', 
285
        top: '5%', 
286
        oneInstance: false,
287
        closeOnClick: false
288
    });
289
});
290

291
// wizard
292
$(function() {
293
    var root = $("#wizard").scrollable();
294
    var api = root.scrollable();
295
    // rangeinput with default configuration
296
    // validation logic is done inside the onBeforeSeek callback
297
    api.onBeforeSeek(function(event, i) {
298
            // we are going 1 step backwards so no need for validation
299
            if (api.getIndex() < i) {
300
             // 1. get current page
301
                     var page = root.find(".page").eq(api.getIndex()),
302
                         // 2. .. and all required fields inside the page
303
                         inputs = page.find(".required :input").removeClass("error"),
304
                         // 3. .. which are empty
305
                         empty = inputs.filter(function() {
306
                                return $(this).val().replace(/\s*/g, '') == '';
307
                         });
308
                     // if there are empty fields, then
309
                    if (empty.length) {
310
                            // add a CSS class name "error" for empty & required fields
311
                            empty.addClass("error");
312
                            // cancel seeking of the scrollable by returning false
313
                            return false;
314
                    // everything is good
315
                    } 
316
            }
317
            // update status bar
318
            $("#status li").removeClass("active").eq(i).addClass("active");
319
        // update confirm step
320
        if (api.getIndex()==0) {
321
            var image = $("input[type=radio][name=image-id]:checked");
322
            var imageRef = image.length ? image[0].id : false
323
            if (imageRef) {
324
                var imageName = $("label[for=" + imageRef + "] .image-title").text();
325
                $("#machine_image-label")[0].textContent = imageName;
326
                $("input[type=text][name=machine_name]")[0].value = "My " + imageName + " server";
327
            }
328
        } else if (api.getIndex()==1) {
329
            $("#machine_cpu-label")[0].textContent = $("#cpu-indicator")[0].value;
330
            $("#machine_ram-label")[0].textContent = $("#ram-indicator")[0].value;
331
            $("#machine_storage-label")[0].textContent = $("#storage-indicator")[0].value;
332
        }    
333
    });
334
    // if tab is pressed on the next button seek to next page
335
    $(root).live('keydown', function (e) {
336
       if ( e.keyCode == 9 ){
337
           if(e.preventDefault) {
338
               e.preventDefault();
339
           }
340
           api.next();
341
        }
342
    });
343
    $("#name").keypress(function (e) {
344
                if ((e.which && e.which == 13) || (e.keyCode && e.keyCode == 13)) {
345
                        $('#start').click();
346
                        return false;
347
                } else {
348
                        return true;
349
                }
350
    });
351
});
352

353
// disable sliders in flavor selection
354
function disableSliders() {
355
    $("#cpu").attr('disabled',true);
356
    $("#ram").attr('disabled',true);
357
    $("#storage").attr('disabled',true);
358
}
359

360
//update radio button when clicking on text
361
$("#small-body").live('click' ,function() { 
362
    $(this).parent().find("#small").click();
363
});
364
$("#medium-body").live('click' ,function() { 
365
    $(this).parent().find("#medium").click();
366
});
367
$("#large-body").live('click' ,function() { 
368
    $(this).parent().find("#large").click();
369
});
370
$("#custom-body").live('click' ,function() { 
371
    $(this).parent().find("#custom").click();
372
});
373

374
//select image div on radio button select
375
$('.radio').live('click' ,function() {           
376
    $(this).parents("div").find(".image").removeClass('selecteddiv');
377
    if($(this).is(':checked'))  {
378
        $(this).parent().addClass('selecteddiv');
379
    }
380
});
381

382
// confirm all actions
383
$("div.confirm_multiple .yes").live('click', function(){
384
    while(pending_actions.length > 0){ // if there is a pending action for this server execute it
385
        action = pending_actions.pop(); // extract action
386
        var serverID = action[1];
387
        if ($.cookie("list") != '1') { // standard view
388
            $('#' + serverID + ' .selected').removeClass('selected');
389
            $('#' + serverID + ' .display').removeClass('display');
390
            if (action[0] == shutdown) {
391
                $('#' + serverID + ' .status').text('Shutting down');
392
            } else if (action[0] == start) {
393
                $('#' + serverID + ' .status').text('Starting');
394
            } else if (action[0] == reboot) {
395
                $('#' + serverID + ' .status').text('Rebooting');
396
            } else if (action[0] == destroy) {
397
                $('#' + serverID + ' .status').text('Destroying');
398
            }
399
            $('#' + serverID + ' .spinner').show();
400
        } else { // list view
401
            osIcon = $('#'+serverID).parent().parent().find('.list-logo');
402
            osIcon.attr('os',osIcon.attr('src'));
403
            osIcon.attr('src','static/progress.gif');
404
            if (action[0] == shutdown) {
405
                $('#' + serverID).parent().parent().find('span.status').text('Shutting down');
406
            } else if (action[0] == start) {
407
                $('#' + serverID).parent().parent().find('span.status').text('Starting');
408
            } else if (action[0] == reboot) {
409
                $('#' + serverID).parent().parent().find('span.status').text('Rebooting');
410
            } else if (action[0] == destroy) {
411
                $('#' + serverID).parent().parent().find('span.status').text('Destroying');
412
            }
413
        }
414
        action[0]([serverID]); // execute action
415
    }
416
    update_confirmations();    
417
});
418

419
// cancel all actions
420
$("div.confirm_multiple .no").live('click', function(){
421
    pending_actions = [];
422
    $('.machine .selected').removeClass('selected');
423
    $('.machine .display').removeClass('display');
424
    update_confirmations();
425
});
426

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

445
// validate ram input box
446
$("#ram-indicator").live('change',function(){
447
    var v = Number(this.value);
448
    var i = ram.indexOf(v);
449
    if (isNaN(v)) {
450
        $(this).value = cpus[0];
451
        $("#ram").data('rangeinput').setValue(0);
452
    } else if (i == -1) {
453
        for (var j=0; j < ram.length; j++)
454
            if (v<ram[j])
455
                break;
456
        $("#ram").data('rangeinput').setValue(j);
457
    } else {
458
        $("#ram").data('rangeinput').setValue(i);
459
    }   
460
    return false;
461
});
462

463

464
// validate storage input box
465
$("#storage-indicator").live('change',function(){
466
    var v = Number(this.value);
467
    var i = disks.indexOf(v);
468
    if (isNaN(v)) {
469
        $(this).value = disks[0];
470
        $("#storage").data('rangeinput').setValue(0);
471
    } else if (i == -1) {
472
        for (var j=0; j < disks.length; j++)
473
            if (v<disks[j])
474
                break;
475
        $("#storage").data('rangeinput').setValue(j);
476
    } else {
477
        $("#storage").data('rangeinput').setValue(i);
478
    }   
479
    return false;
480
});
481

482
// selecting the small size
483
$("#small").click(function(){
484
    $("#cpu").data('rangeinput').setValue(0);
485
    $("#ram").data('rangeinput').setValue(0);
486
    $("#storage").data('rangeinput').setValue(0);
487
    $("#cpu-indicator")[0].value = cpus[0];
488
    $("#ram-indicator")[0].value = ram[0];
489
    $("#storage-indicator")[0].value = disks[0];
490
    $("#small").addClass("active");
491
    $("#medium").removeClass("active");    
492
    $("#large").removeClass("active");    
493
    $("#custom").removeClass("active");    
494
});
495

496
// selecting the medium size
497
$("#medium").click(function(){
498
    $("#cpu").data('rangeinput').setValue(1);
499
    $("#ram").data('rangeinput').setValue(1);
500
    $("#storage").data('rangeinput').setValue(1);
501
    $("#cpu-indicator")[0].value = cpus[1];
502
    $("#ram-indicator")[0].value = ram[1];
503
    $("#storage-indicator")[0].value = disks[1];  
504
    $("#medium").addClass("active");  
505
    $("#small").removeClass("active");    
506
    $("#large").removeClass("active");    
507
    $("#custom").removeClass("active");  
508
});
509

510
// selecting the large size
511
$("#large").click(function(){
512
    $("#cpu").data('rangeinput').setValue(2);
513
    $("#ram").data('rangeinput').setValue(2);
514
    $("#storage").data('rangeinput').setValue(2);
515
    $("#cpu-indicator")[0].value = cpus[2];
516
    $("#ram-indicator")[0].value = ram[2];
517
    $("#storage-indicator")[0].value = disks[2];   
518
    $("#large").addClass("active"); 
519
    $("#medium").removeClass("active");    
520
    $("#small").removeClass("active");    
521
    $("#custom").removeClass("active");  
522
});
523

524
// selecting the custom flavor enables the sliders
525
$("#custom").click(function(){
526
    $("#cpu").attr('disabled',false);
527
    $("#ram").attr('disabled',false);
528
    $("#storage").attr('disabled',false);
529
    $("strong.sliders").style = 'color: #778899;';
530
    $("#custom").addClass("active"); 
531
    $("#medium").removeClass("active");    
532
    $("#large").removeClass("active");    
533
    $("#small").removeClass("active");  
534
});
535

536
// exit the wizard
537
$("#cancel").click(function(){
538
    $("a#create").overlay().close();
539
});
540

541
// starting a new VM through the wizard
542
$("#start").click(function(){
543
    var imageRef = $('input[type=radio][name=image-id]:checked')[0].id.replace('img-radio-','');   
544
    var flavorRef = identify_flavor($("#cpu-indicator")[0].value, $("#storage-indicator")[0].value, $("#ram-indicator")[0].value);
545
    var machineName = $('input[name=machine_name]')[0].value;
546

547
    create_vm(machineName, imageRef, flavorRef);
548

549
    $('a#create').data('overlay').close();
550
    $("#emptymachineslist").hide();
551

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

554
    $("#wizard").hide();
555
});
556

557
// basic functions executed on page load
558
if (images.length > 0) {
559
    // populate image list
560
    update_wizard_images();
561
}
562
if (flavors.length > 0) {
563
    // configure flavors
564
    update_wizard_flavors(); 
565
}
566
// create tabs for main menu
567
$("ul.tabs").tabs("div.panes ul");
568

    
569
</script>