Statistics
| Branch: | Tag: | Revision:

root / ui / templates / machines.html @ 198e13aa

History | View | Annotate | Download (18.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">1</span><div class="headerbody">{% 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="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 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
                                <strong>{% trans "small" %}</strong>
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
                                <strong>{% trans "medium" %}</strong>
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
                                <strong>{% trans "large" %}</strong>
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
                                <strong>{% trans "custom" %}</strong>
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">
137
                        <label>
138
                            <strong>Name:</strong>
139
                            <input type="text" class="text" name="machine_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
// hardcoded image types
199
// TODO: get this from the metadata
200
var image_tags = {
201
                1: 'archlinux',
202
                2: 'centos',
203
                3: 'debian',
204
                4: 'freebsd',
205
                5: 'gentoo',
206
                6: 'netbsd',
207
                7: 'openbsd',
208
                8: 'redhat',
209
                9: 'slackware',
210
                10: 'suse',
211
                11: 'ubuntu',
212
                12: 'windows',
213
                20: 'ubuntu',
214
               };
215

216
// switch to list view
217
$("a#list").click(function(){
218
    list_view(); 
219
    return false;
220
});
221

222
// switch to standard view
223
$("a#standard").click(function(){
224
    standard_view();
225
    return false;
226
});
227

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

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

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

308
// disable sliders in flavor selection
309
function disableSliders() {
310
    $("#cpu").attr('disabled',true);
311
    $("#ram").attr('disabled',true);
312
    $("#storage").attr('disabled',true);
313
}
314

315
// confirm all actions
316
$("div.confirm_multiple .yes").live('click', function(){
317
    while(pending_actions.length > 0){ // if there is a pending action for this server execute it
318
        action = pending_actions.pop(); // extract action
319
        var serverID = action[1];
320
        if ($.cookie("list") != '1') { // standard view
321
            $('#' + serverID + ' .selected').removeClass('selected');
322
            $('#' + serverID + ' .display').removeClass('display');
323
            if (action[0] == shutdown) {
324
                $('#' + serverID + ' .status').text('Shutting down');
325
                alert('shutting');
326
            } else if (action[0] == start) {
327
                $('#' + serverID + ' .status').text('Starting');
328
                alert('starting');
329
            }
330
            $('#' + serverID + ' .spinner').show();
331
        } else { // list view
332
            osIcon = $('#'+serverID).parent().parent().find('.list-logo');
333
            osIcon.attr('os',osIcon.attr('src'));
334
            osIcon.attr('src','static/progress.gif');
335
        }
336
        action[0]([serverID]); // execute action
337
    }
338
    update_confirmations();    
339
});
340

341
// cancel all actions
342
$("div.confirm_multiple .no").live('click', function(){
343
    pending_actions = [];
344
    $('.machine .selected').removeClass('selected');
345
    $('.machine .display').removeClass('display');
346
    update_confirmations();
347
});
348

349
// validate cpu input box
350
$("#cpu-indicator").live('change',function(){
351
    var v = Number(this.value);
352
    var i = cpus.indexOf(v);
353
    if (isNaN(v)) {
354
        $(this).value = cpus[0];
355
        $("#cpu").data('rangeinput').setValue(0);
356
    } else if (i == -1) {
357
        for (var j=0; j < cpus.length; j++)
358
            if (v<cpus[j])
359
                break;
360
        $("#cpu").data('rangeinput').setValue(j);
361
    } else {
362
        $("#cpu").data('rangeinput').setValue(i);
363
    }   
364
    return false;
365
});
366

367
// validate ram input box
368
$("#ram-indicator").live('change',function(){
369
    var v = Number(this.value);
370
    var i = ram.indexOf(v);
371
    if (isNaN(v)) {
372
        $(this).value = cpus[0];
373
        $("#ram").data('rangeinput').setValue(0);
374
    } else if (i == -1) {
375
        for (var j=0; j < ram.length; j++)
376
            if (v<ram[j])
377
                break;
378
        $("#ram").data('rangeinput').setValue(j);
379
    } else {
380
        $("#ram").data('rangeinput').setValue(i);
381
    }   
382
    return false;
383
});
384

385

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

404
// selecting the small size
405
$("#small").click(function(){
406
    $("#cpu").data('rangeinput').setValue(0);
407
    $("#ram").data('rangeinput').setValue(0);
408
    $("#storage").data('rangeinput').setValue(0);
409
    $("#cpu-indicator")[0].value = cpus[0];
410
    $("#ram-indicator")[0].value = ram[0];
411
    $("#storage-indicator")[0].value = disks[0];
412
    $("#small").addClass("active");
413
    $("#medium").removeClass("active");    
414
    $("#large").removeClass("active");    
415
    $("#custom").removeClass("active");    
416
});
417

418
// selecting the medium size
419
$("#medium").click(function(){
420
    $("#cpu").data('rangeinput').setValue(1);
421
    $("#ram").data('rangeinput').setValue(1);
422
    $("#storage").data('rangeinput').setValue(1);
423
    $("#cpu-indicator")[0].value = cpus[1];
424
    $("#ram-indicator")[0].value = ram[1];
425
    $("#storage-indicator")[0].value = disks[1];  
426
    $("#medium").addClass("active");  
427
    $("#small").removeClass("active");    
428
    $("#large").removeClass("active");    
429
    $("#custom").removeClass("active");  
430
});
431

432
// selecting the large size
433
$("#large").click(function(){
434
    $("#cpu").data('rangeinput').setValue(2);
435
    $("#ram").data('rangeinput').setValue(2);
436
    $("#storage").data('rangeinput').setValue(2);
437
    $("#cpu-indicator")[0].value = cpus[2];
438
    $("#ram-indicator")[0].value = ram[2];
439
    $("#storage-indicator")[0].value = disks[2];   
440
    $("#large").addClass("active"); 
441
    $("#medium").removeClass("active");    
442
    $("#small").removeClass("active");    
443
    $("#custom").removeClass("active");  
444
});
445

446
// selecting the custom flavor enables the sliders
447
$("#custom").click(function(){
448
    $("#cpu").attr('disabled',false);
449
    $("#ram").attr('disabled',false);
450
    $("#storage").attr('disabled',false);
451
    $("strong.sliders").style = 'color: #778899;';
452
    $("#custom").addClass("active"); 
453
    $("#medium").removeClass("active");    
454
    $("#large").removeClass("active");    
455
    $("#small").removeClass("active");  
456
});
457

458
// exit the wizard
459
$("#cancel").click(function(){
460
    $("a#create").overlay().close();
461
});
462

463
// starting a new VM through the wizard
464
$("#start").click(function(){
465
    var imageRef = $('input[type=radio][name=image-id]:checked')[0].id.replace('img-radio-','');   
466
    var flavorRef = identify_flavor($("#cpu-indicator")[0].value, $("#storage-indicator")[0].value, $("#ram-indicator")[0].value);
467
    var machineName = $('input[name=machine_name]')[0].value;
468

469
    create_vm(machineName, imageRef, flavorRef);
470

471
    $('a#create').data('overlay').close();
472
    $("#emptymachineslist").hide();
473

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

476
    $("#wizard").hide();
477
});
478

479
// basic functions executed on page load
480
if (images.length > 0) {
481
    // populate image list
482
    update_wizard_images();
483
}
484
if (flavors.length > 0) {
485
    // configure flavors
486
    update_wizard_flavors(); 
487
}
488
// create tabs for main menu
489
$("ul.tabs").tabs("div.panes ul");
490

    
491
</script>