Statistics
| Branch: | Tag: | Revision:

root / ui / templates / machines.html @ 1508a5ab

History | View | Annotate | Download (21.8 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="meta-modal" id="editor-1">
181
    <h3>
182
        <label>{% trans "Metadata for machine:" %}<label>
183
        <span></span>
184
    </h3>
185
    <hr class="topruler" />
186
    <hr class="fatruler" />
187
    <div class="content">
188
        <ul>
189
            <li class="meta-template">
190
                <label>{% trans "Metadata key" %}</label>
191
                <button type="button" class="remove">{% trans "remove x" %}</button>
192
                <hr class="meta-separator">
193
                <p>{% trans "Metadata value" %}</p>
194
                <button type="button" class="edit">{% trans "edit" %}</button>
195
            </li>
196
        </ul>
197
    </div>
198
    <button type="button" class="create">{% trans "Create New+" %}</button>
199
    <hr class="bottomruler" /> 
200
</div>
201

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

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

    
223
<div id="machinesview"></div>
224

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

    
231
<div id="machines" class="separator"></div>
232

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

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

248
    if (metadata.values.OS == undefined || metadata.values.OS == '') {
249
        return 'unknown';
250
    } else {
251
        return metadata.values.OS;
252
    }
253
} 
254

255
// switch to list view
256
$("a#list").click(function(){
257
    list_view(); 
258
    return false;
259
});
260

261
// switch to standard view
262
$("a#standard").click(function(){
263
    standard_view();
264
    return false;
265
});
266

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

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

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

361
// disable sliders in flavor selection
362
function disableSliders() {
363
    $("#cpu").attr('disabled',true);
364
    $("#ram").attr('disabled',true);
365
    $("#storage").attr('disabled',true);
366
}
367

368
//update radio button when clicking on text
369
$("#small-body").live('click' ,function() { 
370
    $(this).parent().find("#small").click();
371
});
372
$("#medium-body").live('click' ,function() { 
373
    $(this).parent().find("#medium").click();
374
});
375
$("#large-body").live('click' ,function() { 
376
    $(this).parent().find("#large").click();
377
});
378
$("#custom-body").live('click' ,function() { 
379
    $(this).parent().find("#custom").click();
380
});
381

382
//select image div on radio button select
383
$('.radio').live('click' ,function() {           
384
    $(this).parents("div").find(".image").removeClass('selecteddiv');
385
    if($(this).is(':checked'))  {
386
        $(this).parent().addClass('selecteddiv');
387
    }
388
});
389

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

427
// cancel all actions
428
$("div.confirm_multiple .no").live('click', function(){
429
    pending_actions = [];
430
    $('.machine .selected').removeClass('selected');
431
    $('.machine .display').removeClass('display');
432
    update_confirmations();
433
});
434

435
// validate cpu input box
436
$("#cpu-indicator").live('change',function(){
437
    var v = Number(this.value);
438
    var i = cpus.indexOf(v);
439
    if (isNaN(v)) {
440
        $(this).value = cpus[0];
441
        $("#cpu").data('rangeinput').setValue(0);
442
    } else if (i == -1) {
443
        for (var j=0; j < cpus.length; j++)
444
            if (v<cpus[j])
445
                break;
446
        $("#cpu").data('rangeinput').setValue(j);
447
    } else {
448
        $("#cpu").data('rangeinput').setValue(i);
449
    }   
450
    return false;
451
});
452

453
// validate ram input box
454
$("#ram-indicator").live('change',function(){
455
    var v = Number(this.value);
456
    var i = ram.indexOf(v);
457
    if (isNaN(v)) {
458
        $(this).value = cpus[0];
459
        $("#ram").data('rangeinput').setValue(0);
460
    } else if (i == -1) {
461
        for (var j=0; j < ram.length; j++)
462
            if (v<ram[j])
463
                break;
464
        $("#ram").data('rangeinput').setValue(j);
465
    } else {
466
        $("#ram").data('rangeinput').setValue(i);
467
    }   
468
    return false;
469
});
470

471

472
// validate storage input box
473
$("#storage-indicator").live('change',function(){
474
    var v = Number(this.value);
475
    var i = disks.indexOf(v);
476
    if (isNaN(v)) {
477
        $(this).value = disks[0];
478
        $("#storage").data('rangeinput').setValue(0);
479
    } else if (i == -1) {
480
        for (var j=0; j < disks.length; j++)
481
            if (v<disks[j])
482
                break;
483
        $("#storage").data('rangeinput').setValue(j);
484
    } else {
485
        $("#storage").data('rangeinput').setValue(i);
486
    }   
487
    return false;
488
});
489

490
// selecting the small size
491
$("#small").click(function(){
492
    $("#cpu").data('rangeinput').setValue(0);
493
    $("#ram").data('rangeinput').setValue(0);
494
    $("#storage").data('rangeinput').setValue(0);
495
    $("#cpu-indicator")[0].value = cpus[0];
496
    $("#ram-indicator")[0].value = ram[0];
497
    $("#storage-indicator")[0].value = disks[0];
498
    $("#small").addClass("active");
499
    $("#medium").removeClass("active");    
500
    $("#large").removeClass("active");    
501
    $("#custom").removeClass("active");    
502
});
503

504
// selecting the medium size
505
$("#medium").click(function(){
506
    $("#cpu").data('rangeinput').setValue(1);
507
    $("#ram").data('rangeinput').setValue(1);
508
    $("#storage").data('rangeinput').setValue(1);
509
    $("#cpu-indicator")[0].value = cpus[1];
510
    $("#ram-indicator")[0].value = ram[1];
511
    $("#storage-indicator")[0].value = disks[1];  
512
    $("#medium").addClass("active");  
513
    $("#small").removeClass("active");    
514
    $("#large").removeClass("active");    
515
    $("#custom").removeClass("active");  
516
});
517

518
// selecting the large size
519
$("#large").click(function(){
520
    $("#cpu").data('rangeinput').setValue(2);
521
    $("#ram").data('rangeinput').setValue(2);
522
    $("#storage").data('rangeinput').setValue(2);
523
    $("#cpu-indicator")[0].value = cpus[2];
524
    $("#ram-indicator")[0].value = ram[2];
525
    $("#storage-indicator")[0].value = disks[2];   
526
    $("#large").addClass("active"); 
527
    $("#medium").removeClass("active");    
528
    $("#small").removeClass("active");    
529
    $("#custom").removeClass("active");  
530
});
531

532
// selecting the custom flavor enables the sliders
533
$("#custom").click(function(){
534
    $("#cpu").attr('disabled',false);
535
    $("#ram").attr('disabled',false);
536
    $("#storage").attr('disabled',false);
537
    $("strong.sliders").style = 'color: #778899;';
538
    $("#custom").addClass("active"); 
539
    $("#medium").removeClass("active");    
540
    $("#large").removeClass("active");    
541
    $("#small").removeClass("active");  
542
});
543

544
// exit the wizard
545
$("#cancel").click(function(){
546
    $("a#create").overlay().close();
547
});
548

549
// starting a new VM through the wizard
550
$("#start").click(function(){
551
    var imageRef = $('input[type=radio][name=image-id]:checked')[0].id.replace('img-radio-','');   
552
    var flavorRef = identify_flavor($("#cpu-indicator")[0].value, $("#storage-indicator")[0].value, $("#ram-indicator")[0].value);
553
    var machineName = $('input[name=machine_name]')[0].value;
554

555
    create_vm(machineName, imageRef, flavorRef);
556

557
    $('a#create').data('overlay').close();
558
    $("#emptymachineslist").hide();
559

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

562
    $("#wizard").hide();
563
});
564

565
// basic functions executed on page load
566
if (images.length > 0) {
567
    // populate image list
568
    update_wizard_images();
569
}
570
if (flavors.length > 0) {
571
    // configure flavors
572
    update_wizard_flavors(); 
573
}
574
// create tabs for main menu
575
$("ul.tabs").tabs("div.panes ul");
576

    
577
</script>