Statistics
| Branch: | Tag: | Revision:

root / ui / templates / machines.html @ 2cd96cc7

History | View | Annotate | Download (16.1 kB)

1
{% load i18n %}
2

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

    
5
<!-- the create button -->
6
<a id="create" rel="#wizard" href="#">{% trans "Create New +" %}</a>
7

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

    
15
<!-- the form -->
16
<form action="#">
17
        <!-- scrollable root element -->
18
        <div class="modal" id="wizard">
19
                <!-- status bar -->
20
                <ul id="status">
21
                        <li class="active"><strong>1.</strong> {% trans "Image" %}</li>
22
                        <li><strong>2.</strong> {% trans "Machine" %}</li>
23
                        <li><strong>3.</strong> {% trans "Review" %}</li>
24
                </ul>
25
                <!-- scrollable items -->
26
                <div class="items">
27
                        <!-- pages -->
28
                        <div class="page">
29
                <h2>{% trans "Select an OS" %}</h2>
30
                <ul class="tabs">
31
                    <li><a href="#">{% trans "standard" %}</a></li>
32
                    <li><a href="#">{% trans "custom" %}</a></li>
33
                </ul>
34
                <div class="panes">
35
                            <li id="image-template" style="display:none">
36
                                    <label for="image.id"> 
37
                            <a>
38
                                <div class="image">
39
                                    <img src="" class="image-logo"/>
40
                                    <strong class="image-title">image.title</strong>
41
                                    <input class="radio" type="radio" name="image-id" id="image-id" />
42
                                    <br />
43
                                    <span class="description">image.description</span> 
44
                                    <span class="size">?? MB</span>                              
45
                                </div>
46
                            </a>
47
                                    </label>
48
                            </li>
49
                    <ul class="pane" id="standard-images">
50
                                            <!-- standard images -->
51
                                    </ul>
52
                    <ul class="pane" id="custom-images">
53
                                            <!-- custom images -->
54
                    </ul>
55
                </div>
56
                                <button type="button" class="prev" id="cancel">{% trans "Cancel" %}</button>
57
                                <button type="button" class="next right">{% trans "Next" %} &raquo;</button>
58
            </div>
59
                        <div class="page">
60
                                <h2>{% trans "Select CPU, RAM and storage" %}</h2>
61
                <ul>
62
                    <li>
63
                        <div class="machine-type">
64
                            <label for="small">
65
                                <input type="radio" id="small" name="machine-type" value="small" checked="true" />
66
                                <strong>{% trans "small" %}</strong>
67
                            </label>
68
                        </div>
69
                        <div class="machine-type">      
70
                            <label for="medium">
71
                                <input type="radio" id="medium" name="machine-type" value="medium" />                  
72
                                <strong>{% trans "medium" %}</strong>
73
                            </label>
74
                        </div>
75
                        <div class="machine-type">
76
                            <label for="large">
77
                                <input type="radio" id="large" name="machine-type" value="large" />
78
                                <strong>{% trans "large" %}</strong>
79
                            </label>
80
                        </div>
81
                        <div class="machine-type">
82
                            <label for="custom">
83
                                <input type="radio" name="machine-type" id="custom" value="large" />
84
                                <strong>{% trans "custom" %}</strong>
85
                            </label>
86
                        </div>
87
                    </li>
88
                    <li>
89
                                    <label><strong class="sliders">CPU (cores)</strong></label>
90
                        <input type="range" id="cpu" style="display:none" />
91
                        <input type="text" class="range" id="cpu-indicator" />
92
                    </li>
93
                    <li>
94
                                    <label><strong class="sliders">RAM (MB)</strong></label>
95
                        <input type="range" id="ram" style="display:none" />
96
                        <input type="text" class="range" id="ram-indicator" />
97

    
98
                    </li>
99
                    <li>
100
                                <label><strong class="sliders">Storage (GB)</strong></label>
101
                        <input type="range" id="storage" style="display:none" />
102
                        <input type="text" class="range" id="storage-indicator" />
103

    
104
                    </li>
105
                    <li>
106
                        <div class="cost">
107
                            {% trans "Cost per hour:" %} 20 {% trans "credits" %} | {% trans "Credits currently in account:" %} 10.000
108
                        </div>
109
                    </li>
110
                </ul>
111
                                <button type="button" class="prev">&laquo; {% trans "Back" %}</button>
112
                                <button type="button" class="next right">{% trans "Next" %} &raquo;</button>
113
            </div>
114
                        <div class="page">
115
                                <h2>{% trans "Confirm your settings" %}</h2>
116
                <ul>
117
                    <li class="required">
118
                        <label>
119
                            <strong>Machine name</strong>
120
                            <input type="text" class="text" name="machine_name" value="My Ubuntu 10.04 x86_64 server"/>
121
                        </label>
122
                    </li>
123
                    <li>
124
                        <strong>{% trans "Image:" %}</strong> <span id="machine_image-label">Ubuntu 10.04 x86_64 server</span>
125
                    </li>
126
                    <li>
127
                        <strong>{% trans "CPU:" %}</strong> <span id="machine_cpu-label">2</span> <span>{% trans "cores" %}</span>
128
                    </li>
129
                    <li>
130
                        <strong>{% trans "RAM:" %}</strong> <span id="machine_ram-label">1024</span><span>MB</span>
131
                    </li>
132
                    <li>
133
                        <strong>{% trans "Storage:" %}</strong> <span id="machine_storage-label">10</span><span>GB</span>
134
                    </li>
135
                    <li>
136
                        <strong>{% trans "Cost per hour:" %}</strong> <span>20 {% trans "credits" %}</span>
137
                    </li>
138
                    <li>
139
                        <strong>{% trans "Remaining credits:" %}</strong> <span>10.000</span>
140
                    </li>
141
                </ul>
142
                                <button type="button" class="prev">&laquo; {% trans "Back" %}</button>
143
                                <button type="button" class="next right" id="start">{% trans "Create VM" %}</button>        
144
            </div>
145
                </div>
146
        </div>
147
</form>
148

    
149
<!-- notification after wizard completion -->
150
<a id="notification" rel="#error-success" href="#"></a>
151

    
152
<div class="modal" id="error-success">
153
    <h3>{% trans "Error!/Success!" %}</h3>
154
    <p>{% trans "More details about the result"%}</p>
155
</div>
156

    
157
<!-- confirmation before executing an action -->
158
<a id="confirmation" rel="#yes-no" href="#"></a>
159

    
160
<div class="modal" id="yes-no">
161
    <h3>{% trans "You are about to xxx machine yyy" %}</h3>
162
    <p>{% trans "Are you sure you want to proceed?" %}</p>
163
    <button>{% trans "Yes" %}</button>
164
        <button>{% trans "No" %}</button>
165
</div>
166

    
167
<div id="machinesview"></div>
168

    
169
<div class="confirm_multiple">
170
    <p>{% trans "Your actions will affect" %} <span class="actionLen">XX</span> {% trans "machines" %}</p>
171
    <button class="yes">{% trans "Confirm All" %}</button>
172
        <button class="no">{% trans "Cancel All" %}</button>
173
</div>
174

    
175
<div id="machines" class="separator"></div>
176

    
177
<script>
178
// hardcoded image types
179
// TODO: get this from the metadata
180
var image_tags = {
181
                1: 'archlinux',
182
                2: 'centos',
183
                3: 'debian',
184
                4: 'freebsd',
185
                5: 'gentoo',
186
                6: 'netbsd',
187
                7: 'openbsd',
188
                8: 'redhat',
189
                9: 'slackware',
190
                10: 'suse',
191
                11: 'ubuntu',
192
                12: 'windows',
193
                20: 'ubuntu',
194
               };
195

196
// switch to list view
197
$("a#list").click(function(){
198
    list_view(); 
199
    return false;
200
});
201

202
// switch to standard view
203
$("a#standard").click(function(){
204
    standard_view();
205
    return false;
206
});
207

208
// launch VM creation wizard
209
$("a#create").click(function(){
210
    // launch wizard only if images and flavors are found
211
    if (images.length > 0  && flavors.length > 0) {
212
        $("#wizard").scrollable().begin();
213
        $("#wizard").show();
214
        $('a#create').data('overlay').load()   
215
    } else if (images.length == 0 ) {
216
        ajax_error('NO_IMAGES');
217
        return false;   
218
    } else if (flavors.length == 0) {
219
        ajax_error('NO_FLAVORS');
220
        return false;
221
    }
222
});
223

224
// create wizard overlay
225
$(function() { 
226
    $("a#create").overlay({
227
        mask: '#000', 
228
        effect: 'default', 
229
        top: '5%', 
230
        oneInstance: false,
231
        closeOnClick: false
232
    });
233
});
234

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

288
// disable sliders in flavor selection
289
function disableSliders() {
290
    $("#cpu").attr('disabled',true);
291
    $("#ram").attr('disabled',true);
292
    $("#storage").attr('disabled',true);
293
}
294

295
// confirm all actions
296
$("div.confirm_multiple .yes").live('click', function(){
297
    while(pending_actions.length > 0){ // if there is a pending action for this server execute it
298
        action = pending_actions.pop(); // extract action
299
        var serverID = action[1];
300
        
301
        if ($.cookie("list") != '1') { // standard view
302
            $('#'+serverID+' .spinner').show();
303
            $('#'+serverID+' .selected').removeClass('selected');
304
            $('#'+serverID+' .display').removeClass('display');
305
        } else { // list view
306
            osIcon = $('#'+serverID).parent().parent().find('.list-logo');
307
            osIcon.attr('os',osIcon.attr('src'));
308
            osIcon.attr('src','static/progress.gif');
309
        }
310
        action[0]([serverID]); // execute action
311
    }
312
    update_confirmations();    
313
});
314

315
// cancel all actions
316
$("div.confirm_multiple .no").live('click', function(){
317
    pending_actions = [];
318
    $('.machine .selected').removeClass('selected');
319
    $('.machine .display').removeClass('display');
320
    update_confirmations();
321
});
322

323
// validate cpu input box
324
$("#cpu-indicator").live('change',function(){
325
    var v = Number(this.value);
326
    var i = cpus.indexOf(v);
327
    if (isNaN(v)) {
328
        $(this).value = cpus[0];
329
        $("#cpu").data('rangeinput').setValue(0);
330
    } else if (i == -1) {
331
        for (var j=0; j < cpus.length; j++)
332
            if (v<cpus[j])
333
                break;
334
        $("#cpu").data('rangeinput').setValue(j);
335
    } else {
336
        $("#cpu").data('rangeinput').setValue(i);
337
    }   
338
    return false;
339
});
340

341
// validate ram input box
342
$("#ram-indicator").live('change',function(){
343
    var v = Number(this.value);
344
    var i = ram.indexOf(v);
345
    if (isNaN(v)) {
346
        $(this).value = cpus[0];
347
        $("#ram").data('rangeinput').setValue(0);
348
    } else if (i == -1) {
349
        for (var j=0; j < ram.length; j++)
350
            if (v<ram[j])
351
                break;
352
        $("#ram").data('rangeinput').setValue(j);
353
    } else {
354
        $("#ram").data('rangeinput').setValue(i);
355
    }   
356
    return false;
357
});
358

359

360
// validate storage input box
361
$("#storage-indicator").live('change',function(){
362
    var v = Number(this.value);
363
    var i = disks.indexOf(v);
364
    if (isNaN(v)) {
365
        $(this).value = disks[0];
366
        $("#storage").data('rangeinput').setValue(0);
367
    } else if (i == -1) {
368
        for (var j=0; j < disks.length; j++)
369
            if (v<disks[j])
370
                break;
371
        $("#storage").data('rangeinput').setValue(j);
372
    } else {
373
        $("#storage").data('rangeinput').setValue(i);
374
    }   
375
    return false;
376
});
377

378
// selecting the small size
379
$("#small").click(function(){
380
    $("#cpu").data('rangeinput').setValue(0);
381
    $("#ram").data('rangeinput').setValue(0);
382
    $("#storage").data('rangeinput').setValue(0);
383
    $("#cpu-indicator")[0].value = cpus[0];
384
    $("#ram-indicator")[0].value = ram[0];
385
    $("#storage-indicator")[0].value = disks[0];
386
});
387

388
// selecting the medium size
389
$("#medium").click(function(){
390
    $("#cpu").data('rangeinput').setValue(1);
391
    $("#ram").data('rangeinput').setValue(1);
392
    $("#storage").data('rangeinput').setValue(1);
393
    $("#cpu-indicator")[0].value = cpus[1];
394
    $("#ram-indicator")[0].value = ram[1];
395
    $("#storage-indicator")[0].value = disks[1];    
396
});
397

398
// selecting the large size
399
$("#large").click(function(){
400
    $("#cpu").data('rangeinput').setValue(2);
401
    $("#ram").data('rangeinput').setValue(2);
402
    $("#storage").data('rangeinput').setValue(2);
403
    $("#cpu-indicator")[0].value = cpus[2];
404
    $("#ram-indicator")[0].value = ram[2];
405
    $("#storage-indicator")[0].value = disks[2];    
406
});
407

408
// selecting the custom flavor enables the sliders
409
$("#custom").click(function(){
410
    $("#cpu").attr('disabled',false);
411
    $("#ram").attr('disabled',false);
412
    $("#storage").attr('disabled',false);
413
    $("strong.sliders").style = 'color: #778899;';
414
});
415

416
// exit the wizard
417
$("#cancel").click(function(){
418
    $("a#create").overlay().close();
419
});
420

421
// starting a new VM through the wizard
422
$("#start").click(function(){
423
    var imageRef = $('input[type=radio][name=image-id]:checked')[0].id.replace('img-radio-','');   
424
    var flavorRef = identify_flavor($("#cpu-indicator")[0].value, $("#storage-indicator")[0].value, $("#ram-indicator")[0].value);
425
    var machineName = $('input[name=machine_name]')[0].value;
426

427
    create_vm(machineName, imageRef, flavorRef);
428

429
    $('a#create').data('overlay').close();
430
    $("#emptymachineslist").hide();
431

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

434
    $("#wizard").hide();
435
});
436

437
// basic functions executed on page load
438
if (images.length > 0) {
439
    // populate image list
440
    update_wizard_images();
441
}
442
if (flavors.length > 0) {
443
    // configure flavors
444
    update_wizard_flavors(); 
445
}
446
// create tabs for main menu
447
$("ul.tabs").tabs("div.panes ul");
448

449
$(window).resize(function(){
450
    if (this.innerHeight - 240 < $('#machinesview').height())
451
        $('.confirm_multiple').addClass('fixed');
452
    else
453
        $('.confirm_multiple').removeClass('fixed');
454
});
455

    
456
</script>