Revision 038383b1

b/README.develop
10 10
- simplejson
11 11
- selenium
12 12
- pyzmq-static
13
- iso8601
13 14

  
14 15
also, depending on the database engine of choice, on one of the following:
15 16
- MySQL-python
b/api/handlers.py
14 14
import string
15 15
import logging
16 16
from datetime import datetime, timedelta
17

  
17
import iso8601
18 18
from logic import backend, utils
19 19

  
20 20
log = logging.getLogger('synnefo.api.handlers')
......
144 144
        try:
145 145
            changes_since = request.GET.get("changes-since", 0)
146 146
            if changes_since:
147
                last_update = datetime.strptime(changes_since,
148
                                                "%Y-%m-%dT%H:%M:%S")
147
                last_update = iso8601.parse_date(changes_since)
149 148
                #return a badRequest if the changes_since is older than a limit
150
                if (datetime.now() - last_update >
149
                if (datetime.now(last_update.tzinfo) - last_update >
151 150
                    timedelta(seconds=settings.POLL_LIMIT)):
152 151
                    raise fault.badRequest
153 152
                virtual_servers = VirtualMachine.objects.filter(
b/ui/static/main.css
531 531
    margin-top: 18px;
532 532
}
533 533

  
534
div.actions a:hover{
534
div.actions a.enabled:hover{
535 535
    color: black !important;
536 536
    text-decoration: underline;
537 537
    display: block;
......
850 850
    color: #F49C1A;
851 851
}
852 852

  
853
#error-success div {
854
    height: 142px;
855
    overflow-y: auto;
856
    overflow-x: hidden;
857
}
858

  
853 859
#error-success .close {
854 860
	background-image: url(/static/close.png);
855 861
	position: absolute;
......
1163 1169
    color: orange !important;
1164 1170
}
1165 1171

  
1166
.message {
1172
.action_error .message, .action_error .code {
1167 1173
    display: none;
1168 1174
}
1169 1175

  
b/ui/static/synnefo.js
11 11
			pad(d.getUTCMonth()+1) + '-' +
12 12
			pad(d.getUTCDate()) + 'T' +
13 13
			pad(d.getUTCHours()) + ':' +
14
			pad(d.getUTCMinutes())+ ':' +
15
			pad(d.getUTCSeconds())
14
			pad(d.getUTCMinutes()) + ':' +
15
			pad(d.getUTCSeconds()) +'Z'
16
}
17

  
18
function parse_error(responseText){
19
	var errors = [];
20
	responseObj = JSON.parse(responseText);
21
	//console.info(inp);
22
	for (var err in responseObj){
23
		errors[errors.length] = responseObj[err];
24
	}
25
	return errors;
16 26
}
17 27

  
18 28
// indexOf prototype for IE
......
221 231
			}
222 232
			// as for now, just show an error message
223 233
			try { console.info('update_vms errback:' + jqXHR.status ) } catch(err) {}
224
			ajax_error(jqXHR.status);						
234
			ajax_error(jqXHR.status, undefined, 'Update VMs', jqXHR.responseText);						
225 235
			return false;
226 236
			},
227 237
        success: function(data, textStatus, jqXHR) {
......
239 249
			if (jqXHR.status == 200 || jqXHR.status == 203) {
240 250
				try {
241 251
					servers = data.servers;
242
				} catch(err) { ajax_error('400');}
252
				} catch(err) { ajax_error('400', undefined, 'Update VMs', jqXHR.responseText);}
243 253
				update_machines_view(data);
244 254
			} else if (jqXHR.status != 304){
245 255
				try { console.info('update_vms callback:' + jqXHR.status ) } catch(err) {}
246
				//ajax_error();						
256
				//ajax_error(jqXHR.status, undefined, 'Update VMs', jqXHR.responseText);					
247 257
			}
248 258
			return false;
249 259
        }
......
260 270
        dataType: "json",
261 271
        timeout: TIMEOUT,
262 272
        error: function(jqXHR, textStatus, errorThrown) { 
263
                    ajax_error(jqXHR.status);
273
                    ajax_error(jqXHR.status, undefined, 'Update Images', jqXHR.responseText);
264 274
                    },
265 275
        success: function(data, textStatus, jqXHR) {
266 276
            try {
......
365 375
        timeout: TIMEOUT,
366 376
        error: function(jqXHR, textStatus, errorThrown) { 
367 377
            try {
368
				ajax_error(jqXHR.status);
378
				ajax_error(jqXHR.status, undefined, 'Update Flavors', jqXHR.responseText);
369 379
			} catch (err) {
370 380
				ajax_error(err);
371 381
			}
......
447 457
            "flavorRef" : flavorRef,
448 458
            "metadata" : {
449 459
                "My Server Name" : machineName
450
            },
460
            }
451 461
        }
452 462
    };
453 463

  
......
459 469
    data: JSON.stringify(payload),
460 470
    timeout: TIMEOUT,
461 471
    error: function(jqXHR, textStatus, errorThrown) { 
462
                ajax_error(jqXHR.status);
472
                ajax_error(jqXHR.status, undefined, 'Create VM', jqXHR.responseText);
463 473
           },
464 474
    success: function(data, textStatus, jqXHR) {
465 475
                if ( jqXHR.status == '202') {
466 476
                    ajax_success("CREATE_VM_SUCCESS", data.server.adminPass);                   
467 477
                } else {
468
                    ajax_error(jqXHR.status);
478
                    ajax_error(jqXHR.status, undefined, 'Create VM', jqXHR.responseText);
469 479
                }
470 480
            }
471 481
    });
......
490 500
		data: JSON.stringify(payload),
491 501
		timeout: TIMEOUT,
492 502
		error: function(jqXHR, textStatus, errorThrown) {
493
                    display_failure(serverID, jqXHR.status, 'Reboot')
503
                    display_failure(jqXHR.status, serverID, 'Reboot', jqXHR.responseText)
494 504
				},
495 505
		success: function(data, textStatus, jqXHR) {
496 506
					if ( jqXHR.status == '202') {
......
502 512
						// continue with the rest of the servers
503 513
						reboot(serverIDs);
504 514
					} else {
505
						ajax_error(jqXHR.status, serverID);
515
						ajax_error(jqXHR.status, serverID, 'Reboot', jqXHR.responseText);
506 516
					}
507 517
				}
508 518
    });
......
529 539
        data: JSON.stringify(payload),
530 540
        timeout: TIMEOUT,
531 541
        error: function(jqXHR, textStatus, errorThrown) { 
532
                    display_failure(serverID, jqXHR.status, 'Shutdown')
542
                    display_failure(jqXHR.status, serverID, 'Shutdown', jqXHR.responseText)
533 543
                    },
534 544
        success: function(data, textStatus, jqXHR) {
535 545
                    if ( jqXHR.status == '202') {
......
541 551
						// continue with the rest of the servers			
542 552
                        shutdown(serverIDs);
543 553
                    } else {
544
                        ajax_error(jqXHR.status, serverID);
554
                        ajax_error(jqXHR.status, serverID, 'Shutdown', jqXHR.responseText);
545 555
                    }
546 556
                }             
547 557
    });
......
566 576
        data: JSON.stringify(payload),
567 577
        timeout: TIMEOUT,
568 578
        error: function(jqXHR, textStatus, errorThrown) { 
569
                    display_failure(serverID, jqXHR.status, 'Destroy')
579
                    display_failure(jqXHR.status, serverID, 'Destroy', jqXHR.responseText)
570 580
                    },
571 581
        success: function(data, textStatus, jqXHR) {
572 582
                    if ( jqXHR.status == '204') {
......
578 588
						// continue with the rest of the servers
579 589
                        destroy(serverIDs);
580 590
                    } else {
581
                        ajax_error(jqXHR.status, serverID);
591
                        ajax_error(jqXHR.status, serverID, 'Destroy', jqXHR.responseText);
582 592
                    }
583 593
                }             
584 594
    });
......
605 615
        data: JSON.stringify(payload),
606 616
        timeout: TIMEOUT,
607 617
        error: function(jqXHR, textStatus, errorThrown) { 
608
                    display_failure(serverID, jqXHR.status, 'Start')
618
                    display_failure(jqXHR.status, serverID, 'Start', jqXHR.responseText)
609 619
                    },
610 620
        success: function(data, textStatus, jqXHR) {
611 621
                    if ( jqXHR.status == '202') {
......
617 627
						// continue with the rest of the servers						
618 628
                        start(serverIDs);
619 629
                    } else {
620
                        ajax_error(jqXHR.status, serverID);
630
                        ajax_error(jqXHR.status, serverID, 'Start', jqXHR.responseText);
621 631
                    }
622 632
                }
623 633
    });
b/ui/templates/home.html
64 64
        };
65 65
        
66 66
        // ajax error checking  
67
        function ajax_error(status, serverID) {
67
        function ajax_error(status, serverID, action, responseText) {
68
            var serverName = '';
69
            
70
            if (serverID != undefined) {
71
                serverName = $("#"+serverID).parent().parent().find("span.name").text();
72
            }
73
            
68 74
            // prepare the error message
69 75
            $("#error-success h3").text(ERRORS['HEADER']);
70
            
71
            if (ERRORS[status] != undefined) {
76
            if (responseText != undefined){
77
                var errors = parse_error(responseText);
78
                if (serverName){
79
                    serverName="<p><strong>Server:</strong> " + serverName + "</p>";
80
                }
81
                $("#error-success div").html("<p>"+(errors[0].message || ERRORS[errors[0].code]) +"</p>"+serverName +"<p><strong>Action:</strong> " + action + "</p><p><strong>Code</strong>: " + errors[0].code + "</p><p><strong>Details:</strong> " + errors[0].details +"</p>");
82
            } else if (ERRORS[status] != undefined) {
72 83
                if (serverID == undefined){
73 84
                    $("#error-success p").text(ERRORS[status]);
74 85
                } else {
75
                    var serverName = $("#"+serverID).parent().parent().find("a.name").text();
76 86
                    $("#error-success p").html("<b>" + serverName + "</b>" + ": " + ERRORS[status]);
77 87
                }
78 88
            } else {
......
110 120
                    var CREATE_VM_SUCCESS_MSG = SUCCESS["CREATE_VM_SUCCESS_ONE"] + '<br />'
111 121
                        + SUCCESS["CREATE_VM_SUCCESS_TWO"] + '<br /><br />' + '<b>' + password + '</b>'
112 122
                        + '<br /><br />' + SUCCESS["CREATE_VM_SUCCESS_THREE"] ;
113
                    $("#error-success p").html(CREATE_VM_SUCCESS_MSG);             
123
                    $("#error-success div").html("<p>" + CREATE_VM_SUCCESS_MSG + "</p>");             
114 124
                } else {
115 125
                    $("#error-success h3").text(SUCCESS['HEADER']);
116
                    $("#error-success p").text(SUCCESS[status]);             
126
                    $("#error-success div").text("<p>" + SUCCESS[status] + "</p>");             
117 127
                }
118 128
            } else {
119 129
                $("#error-success h3").text(SUCCESS['HEADER']);
120
                $("#error-success p").text(SUCCESS['DEFAULT']);             
130
                $("#error-success div").html("<p>" + SUCCESS['DEFAULT'] + "</p>");             
121 131

  
122 132
            }
123 133

  
b/ui/templates/list.html
260 260
}
261 261

  
262 262
// indicate that the requested action was not completed
263
function display_failure(serverID, status, action) {
263
function display_failure(status, serverID, action, responseText) {
264 264
	osIcon = $('#'+serverID).parent().parent().find('.list-logo');
265 265
	osIcon.attr('src',osIcon.attr('os'));
266
    ajax_error(status, serverID);
266
    ajax_error(status, serverID, action, responseText);
267 267
}
268 268

  
269 269
var vmTable = $("div.list table.list-machines").dataTable({
b/ui/templates/machines.html
151 151

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

  
157 157
<!-- confirmation before executing an action -->
b/ui/templates/standard.html
37 37
        </div>
38 38
        <div class="action_error" align="center">
39 39
            {% trans "<span class='orange'>Error</span> on" %} <span class="action">error action</span>
40
            <span class="code"></span>            
40 41
            <span class="message"></span>
41 42
            <button class="details">Details</button>
42 43
        </div>
......
150 151

  
151 152
$("div.action_error .details").live('click', function(){
152 153
    // remove the action from the pending list
153
    ajax_error($(this).parent().children('.message').text());
154
    ajax_error($(this).parent().children('.code').text(), undefined, $(this).parent().children('.action').text(), $(this).parent().children('.message').text());
154 155
    $(this).parent().hide();
155 156
});
156 157

  
......
258 259
}
259 260

  
260 261
// indicate that the requested action was not completed
261
function display_failure(serverID, status, action) {
262
function display_failure(status, serverID, action, responseText) {
262 263
    $('#'+serverID+ ' .spinner').hide();
263 264
    $('#'+serverID+ ' .action_error .action').text(action);
264
    $('#'+serverID+ ' .action_error .message').text(status);
265
    $('#'+serverID+ ' .action_error .code').text(status);
266
    $('#'+serverID+ ' .action_error .message').text(responseText);
265 267
    $('#'+serverID+ ' .action_error').show();
266 268
    
267 269
}

Also available in: Unified diff