Revision 9ce969a7
b/ui/static/snf/js/models.js | ||
---|---|---|
114 | 114 |
}, |
115 | 115 |
|
116 | 116 |
get_fetcher: function(timeout, fast, limit, initial, params) { |
117 |
var fetch_params = params; |
|
117 |
var fetch_params = params || {}; |
|
118 |
fetch_params.skips_timeouts = true; |
|
119 |
|
|
118 | 120 |
var timeout = parseInt(timeout); |
119 | 121 |
var fast = fast || 1000; |
120 | 122 |
var limit = limit; |
121 | 123 |
var initial_call = initial || true; |
122 | 124 |
|
123 | 125 |
var last_ajax = undefined; |
124 |
var cb = _.bind(function(){ |
|
126 |
var cb = _.bind(function() { |
|
127 |
// clone to avoid referenced objects |
|
128 |
var params = _.clone(fetch_params); |
|
125 | 129 |
updater._ajax = last_ajax; |
126 | 130 |
if (last_ajax) { |
127 | 131 |
last_ajax.abort(); |
128 | 132 |
} |
129 |
last_ajax = this.fetch(fetch_params);
|
|
133 |
last_ajax = this.fetch(params); |
|
130 | 134 |
}, this); |
131 | 135 |
var updater = new snf.api.updateHandler({'callback': cb, timeout:timeout, |
132 | 136 |
fast:fast, limit:limit, |
133 | 137 |
call_on_start:initial_call}); |
134 | 138 |
|
135 |
snf.api.bind("call", _.bind(function(){ updater.faster()}, this));
|
|
139 |
snf.api.bind("call", _.throttle(_.bind(function(){ updater.faster()}, this)), 2000);
|
|
136 | 140 |
return updater; |
137 | 141 |
} |
138 | 142 |
}); |
... | ... | |
391 | 395 |
return net_vm_exists && vm_net_exists; |
392 | 396 |
}, |
393 | 397 |
|
394 |
add_vm: function (vm, callback) { |
|
398 |
add_vm: function (vm, callback, error, options) { |
|
399 |
var payload = {add:{serverRef:"" + vm.id}}; |
|
400 |
payload._options = options || {}; |
|
395 | 401 |
return this.api.call(this.api_path() + "/action", "create", |
396 |
{add:{serverRef:"" + vm.id}},
|
|
402 |
payload,
|
|
397 | 403 |
_.bind(function(){ |
398 | 404 |
this.vms.add_pending(vm.id); |
399 | 405 |
if (callback) {callback()} |
400 |
},this)); |
|
406 |
},this), error);
|
|
401 | 407 |
}, |
402 | 408 |
|
403 |
remove_vm: function (vm, callback) { |
|
409 |
remove_vm: function (vm, callback, error, options) { |
|
410 |
var payload = {remove:{serverRef:"" + vm.id}}; |
|
411 |
payload._options = options || {}; |
|
404 | 412 |
return this.api.call(this.api_path() + "/action", "create", |
405 | 413 |
{remove:{serverRef:"" + vm.id}}, |
406 | 414 |
_.bind(function(){ |
407 | 415 |
this.vms.add_pending_for_remove(vm.id); |
408 | 416 |
if (callback) {callback()} |
409 |
},this)); |
|
417 |
},this), error);
|
|
410 | 418 |
}, |
411 | 419 |
|
412 | 420 |
rename: function(name, callback) { |
... | ... | |
758 | 766 |
var payload = {meta:{}}; |
759 | 767 |
payload.meta[meta.key] = meta.value; |
760 | 768 |
|
769 |
// inject error settings |
|
770 |
payload._options = {critical: false}; |
|
771 |
|
|
761 | 772 |
this.api.call(url, "update", payload, complete, error) |
762 | 773 |
}, |
763 | 774 |
|
764 |
set_firewall: function(net_id, value, callback) { |
|
775 |
set_firewall: function(net_id, value, callback, error, options) {
|
|
765 | 776 |
if (this.get("firewalls") && this.get("firewalls")[net_id] == value) { return } |
766 | 777 |
|
767 | 778 |
this.pending_firewalls[net_id] = value; |
768 | 779 |
this.trigger("change", this, this); |
769 |
this.api.call(this.api_path() + "/action", "create", {"firewallProfile":{"profile":value}}, callback); |
|
780 |
var payload = {"firewallProfile":{"profile":value}}; |
|
781 |
payload._options = _.extend({critical: false}, options); |
|
782 |
|
|
783 |
// reset firewall state on error |
|
784 |
var error_cb = _.bind(function() { |
|
785 |
thi |
|
786 |
}, this); |
|
787 |
|
|
788 |
this.api.call(this.api_path() + "/action", "create", payload, callback, error); |
|
770 | 789 |
storage.networks.get(net_id).update_state(); |
771 | 790 |
}, |
772 | 791 |
|
... | ... | |
1026 | 1045 |
extra_details: { 'Machine ID': this.id, 'URL': url, 'Action': action || "undefined" }, |
1027 | 1046 |
allow_reload: false |
1028 | 1047 |
}, |
1029 |
handles_error: true |
|
1048 |
display: false, |
|
1049 |
critical: false |
|
1030 | 1050 |
} |
1031 | 1051 |
this.sync(method, this, params); |
1032 | 1052 |
}, |
... | ... | |
1274 | 1294 |
|
1275 | 1295 |
get_flavor: function(cpu, mem, disk, filter_list) { |
1276 | 1296 |
if (!filter_list) { filter_list = this.models }; |
1297 |
|
|
1277 | 1298 |
return this.select(function(flv){ |
1278 | 1299 |
if (flv.get("cpu") == cpu + "" && |
1279 | 1300 |
flv.get("ram") == mem + "" && |
1280 | 1301 |
flv.get("disk") == disk + "" && |
1281 | 1302 |
filter_list.indexOf(flv) > -1) { return true; } |
1282 |
})[0] |
|
1303 |
})[0];
|
|
1283 | 1304 |
}, |
1284 | 1305 |
|
1285 | 1306 |
get_data: function(lst) { |
... | ... | |
1334 | 1355 |
}) |
1335 | 1356 |
}, |
1336 | 1357 |
|
1337 |
reset_stats_update: function() {
|
|
1358 |
stop_stats_update: function() {
|
|
1338 | 1359 |
this.each(function(vm) { |
1339 | 1360 |
vm.do_update_stats = false; |
1340 | 1361 |
}) |
... | ... | |
1390 | 1411 |
opts = {name: name, imageRef: image.id, flavorRef: flavor.id, metadata:meta} |
1391 | 1412 |
opts = _.extend(opts, extra); |
1392 | 1413 |
|
1393 |
this.api.call(this.path, "create", {'server': opts}, undefined, undefined, callback); |
|
1414 |
this.api.call(this.path, "create", {'server': opts}, undefined, undefined, callback, {critical: false});
|
|
1394 | 1415 |
} |
1395 | 1416 |
|
1396 | 1417 |
}) |
b/ui/static/snf/js/sync.js | ||
---|---|---|
7 | 7 |
var snf = root.synnefo = root.synnefo || {}; |
8 | 8 |
var sync = snf.sync = snf.sync || {}; |
9 | 9 |
var api = snf.api = snf.api || {}; |
10 |
var storage = snf.storage = snf.storage || {}; |
|
10 | 11 |
|
11 | 12 |
// shortcuts |
12 | 13 |
var bb = Backbone; |
... | ... | |
37 | 38 |
var addApiCallDate = function(url, d, method) { |
38 | 39 |
if (d === undefined) { d = Date() }; |
39 | 40 |
var path = snf.util.parseUri(url).path; |
40 |
api_history[path + "_" + method] = d; |
|
41 |
var key = path + "_" + method; |
|
42 |
|
|
43 |
// TODO: check if d is very old date |
|
44 |
api_history[key] = d; |
|
41 | 45 |
return api_history[path] |
42 | 46 |
} |
43 |
|
|
47 |
|
|
48 |
var clearApiCallDate = function(url, method) { |
|
49 |
var path = snf.util.parseUri(url).path; |
|
50 |
var key = path + "_" + method; |
|
51 |
api_history[key] = false; |
|
52 |
return api_history[path] |
|
53 |
} |
|
54 |
|
|
44 | 55 |
var api_errors = api.errors = api.errors || []; |
45 | 56 |
var add_api_error = function(settings, data) { |
46 | 57 |
api_errors.push({url:settings.url, date:new Date, settings:settings, data:data}) |
... | ... | |
74 | 85 |
} |
75 | 86 |
} |
76 | 87 |
|
77 |
options.handles_error = options.handles_error || false; |
|
78 |
|
|
79 |
if (api.stop_calls) { |
|
88 |
// default error options |
|
89 |
options.critical = options.critical === undefined ? true : options.critical; |
|
90 |
options.display = options.display === undefined ? true : options.display; |
|
91 |
|
|
92 |
if (api.stop_calls && !options.no_skip) { |
|
80 | 93 |
return; |
81 | 94 |
} |
82 | 95 |
|
... | ... | |
103 | 116 |
return bb.sync(method, model, api_options); |
104 | 117 |
} |
105 | 118 |
|
119 |
api.timeouts_occured = 0; |
|
120 |
|
|
106 | 121 |
api.handlerWrapper = function(wrap, method, type) { |
122 |
|
|
107 | 123 |
var cb_type = type; |
124 |
|
|
108 | 125 |
return function() { |
109 | 126 |
|
110 |
if (type == "error") { |
|
127 |
var xhr = undefined; |
|
128 |
var handler_type = type; |
|
129 |
var args = arguments; |
|
130 |
var ajax_options = this; |
|
131 |
|
|
132 |
// save the request date to use it as a changes-since value |
|
133 |
// for opera because we are not able to determine |
|
134 |
// response date header for 304 requests |
|
135 |
if (handler_type == "beforeSend" && $.browser.opera) { |
|
136 |
this.date_send = new Date; |
|
137 |
} |
|
138 |
|
|
139 |
// error with status code 0 in opera |
|
140 |
// act as 304 response |
|
141 |
if (handler_type == "error" && $.browser.opera) { |
|
142 |
if (arguments[0].status === 0 && arguments[1] === "error") { |
|
143 |
arguments[0].status = 304; |
|
144 |
arguments[1] = "notmodified"; |
|
145 |
response_type = "success"; |
|
146 |
xhr = arguments[0]; |
|
147 |
} |
|
148 |
} |
|
149 |
|
|
150 |
// add error in api errors registry |
|
151 |
// api errors registry will be sent |
|
152 |
// if user reports an error using feedback form |
|
153 |
if (handler_type == "error") { |
|
111 | 154 |
add_api_error(this, arguments); |
112 | 155 |
} |
113 | 156 |
|
157 |
// identify response status |
|
114 | 158 |
var status = 304; |
115 | 159 |
if (arguments[0]) { |
116 |
var status = arguments[0].status;
|
|
160 |
status = arguments[0].status; |
|
117 | 161 |
} |
118 |
|
|
119 |
if (type == "error" && this.handles_error && ((status > 499 && status < 600) || status == 400)) { |
|
120 |
arguments.ajax = this; |
|
121 |
return method(arguments) |
|
122 |
} |
|
123 |
|
|
124 |
var args = wrap.apply(this, arguments); |
|
125 |
args = _.toArray(args); |
|
126 |
var ajax_options = this; |
|
127 | 162 |
|
163 |
// identify aborted request |
|
128 | 164 |
try { |
129 | 165 |
if (args[1] === "abort") { |
130 | 166 |
api.trigger("abort"); |
... | ... | |
133 | 169 |
} catch(error) { |
134 | 170 |
console.error("error aborting", error); |
135 | 171 |
} |
136 |
|
|
137 |
// FIXME: is this good practice ??
|
|
138 |
// fetch callbacks wont get called
|
|
172 |
|
|
173 |
// try to set the last request date
|
|
174 |
// only for notmodified or succeed responses
|
|
139 | 175 |
try { |
140 | 176 |
// identify xhr object |
141 |
var xhr = args[2]; |
|
142 |
if (args.length == 2) { |
|
143 |
xhr = args[0]; |
|
144 |
} |
|
145 |
|
|
146 |
// do not call success for 304 responses |
|
147 |
if (args[1] === "notmodified" || xhr.status == 0 && $.browser.opera) { |
|
148 |
if (args[2]) { |
|
149 |
addApiCallDate(this.url, new Date(args[2].getResponseHeader('Date')), ajax_options.type); |
|
177 |
xhr = xhr || args[2]; |
|
178 |
|
|
179 |
// not modified response |
|
180 |
if (args[1] === "notmodified") { |
|
181 |
if (xhr) { |
|
182 |
// use date_send if exists (opera browser) |
|
183 |
var d = this.date_send || xhr.getResponseHeader('Date'); |
|
184 |
if (d) { addApiCallDate(this.url, new Date(d), ajax_options.type); }; |
|
150 | 185 |
} |
151 | 186 |
return; |
152 | 187 |
} |
153 | 188 |
|
189 |
// success response |
|
190 |
if (args[1] == "success" && handler_type == "success") { |
|
191 |
try { |
|
192 |
// use date_send if exists (opera browser) |
|
193 |
var d = this.date_send || args[2].getResponseHeader('Date'); |
|
194 |
if (d) { addApiCallDate(this.url, new Date(d), ajax_options.type); }; |
|
195 |
} catch (err) { |
|
196 |
console.error(err) |
|
197 |
} |
|
198 |
} |
|
154 | 199 |
} catch (err) { |
155 | 200 |
console.error(err); |
156 | 201 |
} |
157 |
method.apply(this, args); |
|
202 |
|
|
203 |
// dont call error callback for non modified responses |
|
204 |
if (arguments[1] === "notmodified") { |
|
205 |
return; |
|
206 |
} |
|
207 |
|
|
208 |
// prepare arguments for error callbacks |
|
209 |
var cb_args = _.toArray(arguments); |
|
210 |
if (handler_type === "error") { |
|
211 |
cb_args.push(_.clone(this)); |
|
212 |
} |
|
213 |
|
|
214 |
// determine if we need to call our callback wrapper |
|
215 |
var call_api_handler = true; |
|
216 |
|
|
217 |
// request handles errors by itself, s |
|
218 |
if (handler_type == "error" && this.skip_api_error) { |
|
219 |
call_api_handler = false |
|
220 |
} |
|
221 |
|
|
222 |
// aborted request, don't call error handler |
|
223 |
if (handler_type === "error" && args[1] === "abort") { |
|
224 |
call_api_handler = false; |
|
225 |
} |
|
226 |
|
|
227 |
// reset api call date, next call will be sent without changes-since |
|
228 |
// parameter set |
|
229 |
if (handler_type === "error") { |
|
230 |
if (args[1] === "error") { |
|
231 |
clearApiCallDate(this.url, this.type); |
|
232 |
} |
|
233 |
} |
|
234 |
|
|
235 |
// call api call back and retrieve params to |
|
236 |
// be passed to the callback method set for |
|
237 |
// this type of response |
|
238 |
if (call_api_handler) { |
|
239 |
cb_args = wrap.apply(this, cb_args); |
|
240 |
} |
|
241 |
|
|
242 |
// call requested callback |
|
243 |
method.apply(this, _.toArray(cb_args)); |
|
158 | 244 |
} |
159 | 245 |
} |
160 | 246 |
|
161 | 247 |
api.successHandler = function(data, status, xhr) { |
162 | 248 |
//debug("ajax success", arguments) |
163 | 249 |
// on success, update the last date we called the api url |
164 |
addApiCallDate(this.url, new Date(xhr.getResponseHeader('Date')), this.type); |
|
165 | 250 |
return [data, status, xhr]; |
166 | 251 |
} |
167 | 252 |
|
168 | 253 |
api.errorHandler = function(event, xhr, settings, error) { |
169 |
//debug("ajax error", arguments, this); |
|
170 |
arguments.ajax = this; |
|
171 | 254 |
|
172 |
// skip aborts |
|
173 |
if (xhr != "abort") { |
|
174 |
arguments.ajax.critical = arguments.ajax.critical == undefined ? true : arguments.ajax.critical; |
|
175 |
if (!settings.handles_error) api.trigger("error", arguments); |
|
255 |
// dont trigger api error untill timeouts occured |
|
256 |
// exceed the skips_timeouts limit |
|
257 |
// |
|
258 |
// check only requests with skips_timeouts option set |
|
259 |
if (xhr === "timeout" && _.last(arguments).skips_timeouts) { |
|
260 |
var skip_timeouts = snf.config.skip_timeouts || 1; |
|
261 |
if (snf.api.timeouts_occured < skip_timeouts) { |
|
262 |
snf.api.timeouts_occured++; |
|
263 |
return; |
|
264 |
} else { |
|
265 |
// reset and continue to error trigger |
|
266 |
snf.api.timeouts_occured = 0; |
|
267 |
} |
|
176 | 268 |
} |
177 |
return arguments; |
|
269 |
|
|
270 |
// skip aborts, notmodified (opera) |
|
271 |
if (xhr === "error" || xhr === "timeout") { |
|
272 |
var args = _.toArray(arguments); |
|
273 |
api.trigger("error", args); |
|
274 |
} |
|
275 |
|
|
276 |
return _.toArray(arguments); |
|
178 | 277 |
} |
179 | 278 |
|
180 | 279 |
api.completeHandler = function(xhr, status) { |
... | ... | |
189 | 288 |
return arguments; |
190 | 289 |
} |
191 | 290 |
|
192 |
|
|
193 |
api.call = function(url, method, data, complete, error, success) { |
|
291 |
// api call helper |
|
292 |
api.call = function(url, method, data, complete, error, success, options) {
|
|
194 | 293 |
var self = this; |
195 | 294 |
error = error || function(){}; |
196 | 295 |
success = success || function(){}; |
197 | 296 |
complete = complete || function(){}; |
198 | 297 |
var extra = data ? data._options || {} : {}; |
199 |
if (data && data._options) { delete data['_options'] }; |
|
200 | 298 |
|
299 |
// really ugly way to pass sync request options. |
|
300 |
// it works though.... |
|
301 |
if (data && data._options) { delete data['_options'] }; |
|
302 |
|
|
303 |
// prepare the params |
|
201 | 304 |
var params = { |
202 | 305 |
url: snf.config.api_url + "/" + url, |
203 | 306 |
data: data, |
... | ... | |
206 | 309 |
error: error |
207 | 310 |
} |
208 | 311 |
|
209 |
params = _.extend(params, extra); |
|
312 |
params = _.extend(params, extra, options);
|
|
210 | 313 |
this.sync(method, this, params); |
211 | 314 |
}, |
212 | 315 |
|
213 | 316 |
_.extend(api, bb.Events); |
214 |
|
|
215 | 317 |
|
318 |
// helper for callbacks that need to get called |
|
319 |
// in fixed intervals |
|
216 | 320 |
api.updateHandler = function(options) { |
217 | 321 |
this.cb = options.callback; |
218 | 322 |
this.limit = options.limit; |
... | ... | |
269 | 373 |
} |
270 | 374 |
} |
271 | 375 |
|
376 |
// api error state |
|
272 | 377 |
api.stop_calls = false; |
378 |
api.STATES = { NORMAL:1, WARN:0, ERROR:-1 }; |
|
379 |
api.error_state = api.STATES.NORMAL; |
|
380 |
|
|
381 |
// on api error update the api error_state |
|
382 |
api.bind("error", function() { |
|
383 |
var args = _.toArray(_.toArray(arguments)[0]); |
|
384 |
var params = _.last(args); |
|
385 |
|
|
386 |
if (params.critical) { |
|
387 |
snf.api.error_state = api.STATES.ERROR; |
|
388 |
snf.api.stop_calls = true; |
|
389 |
} else { |
|
390 |
snf.api.error_state = api.STATES.WARN; |
|
391 |
} |
|
392 |
snf.api.trigger("change:error_state", snf.api.error_state); |
|
393 |
}); |
|
394 |
|
|
395 |
// reset api error state |
|
396 |
api.bind("reset", function() { |
|
397 |
snf.api.error_state = api.STATES.NORMAL; |
|
398 |
snf.api.stop_calls = false; |
|
399 |
snf.api.trigger("change:error_state", snf.api.error_state); |
|
400 |
}) |
|
273 | 401 |
|
274 | 402 |
// make it eventable |
275 | 403 |
_.extend(api.updateHandler.prototype, bb.Events); |
b/ui/static/snf/js/ui/web/ui_error_view.js | ||
---|---|---|
81 | 81 |
}, |
82 | 82 |
|
83 | 83 |
show_error: function(ns, code, message, type, details, error_options) { |
84 |
if (!snf.api.error_state) { this.error_stack = {} };
|
|
84 |
if (snf.api.error_state == snf.api.STATES.NORMAL) { this.error_stack = {} };
|
|
85 | 85 |
|
86 |
if (error_options.fatal_error) { |
|
87 |
snf.api.error_state = true; |
|
88 |
snf.api.trigger("change:error_state", true); |
|
89 |
} else { |
|
90 |
snf.api.error_state = false; |
|
91 |
snf.api.trigger("change:error_state", false); |
|
92 |
} |
|
93 |
|
|
94 | 86 |
var error_entry = [ns, code, message, type, details, error_options]; |
95 | 87 |
this.error_stack[new Date()] = error_entry; |
96 | 88 |
this.display_error.apply(this, error_entry); |
... | ... | |
98 | 90 |
}, |
99 | 91 |
|
100 | 92 |
display_error: function(ns, code, message, type, details, error_options) { |
101 |
this.error_options = {'allow_report': true, 'allow_reload': true, 'extra_details': {}, 'non_critical': false, 'allow_details': false }; |
|
102 |
|
|
93 |
this.error_options = {'allow_report': true, 'allow_reload': true, |
|
94 |
'extra_details': {}, 'non_critical': false, |
|
95 |
'allow_details': false }; |
|
96 |
|
|
103 | 97 |
if (error_options) { |
104 | 98 |
this.error_options = _.extend(this.error_options, error_options); |
105 | 99 |
} |
... | ... | |
109 | 103 |
this.type = type; |
110 | 104 |
this.details = details ? (details.toString ? details.toString() : details) : undefined; |
111 | 105 |
this.message = message; |
106 |
this.title = error_options.title || undefined; |
|
112 | 107 |
|
113 | 108 |
this.update_details(); |
114 | 109 |
|
... | ... | |
120 | 115 |
this.error_options.allow_details = true; |
121 | 116 |
} |
122 | 117 |
|
123 |
//if (APP_DEBUG) {
|
|
124 |
//this.error_options.allow_details = true;
|
|
125 |
//}
|
|
126 |
|
|
118 |
if (APP_DEBUG) { |
|
119 |
this.error_options.allow_details = true; |
|
120 |
} |
|
121 |
|
|
127 | 122 |
this.$(".actions .show-details").click(); |
128 | 123 |
this.$(".key.details").click(); |
129 | 124 |
this.$(".error-more-details").hide(); |
... | ... | |
134 | 129 |
if (this.ns && this.type) { |
135 | 130 |
title = this.title || this.type + " Error"; |
136 | 131 |
} |
132 |
|
|
137 | 133 |
this.$(".header .title").text(title); |
138 | 134 |
this.$(".error-code").text(this.code || ""); |
139 | 135 |
this.$(".error-type").text(this.type || ""); |
... | ... | |
172 | 168 |
} else { |
173 | 169 |
this.$(".reload-app").hide(); |
174 | 170 |
} |
171 |
|
|
172 |
}, |
|
173 |
|
|
174 |
onOpen: function() { |
|
175 |
var self = this; |
|
176 |
|
|
177 |
this.$(".closeme").unbind("click"); |
|
178 |
this.$(".closeme").bind("click", function(){ |
|
179 |
self.hide("reset") |
|
180 |
}) |
|
175 | 181 |
}, |
176 | 182 |
|
177 | 183 |
hide: function(reset_state) { |
178 |
if (reset_state === undefined) { reset_state = true }; |
|
179 |
if (reset_state) { |
|
180 |
snf.api.error_state = false; |
|
181 |
snf.api.trigger("change:error_state", snf.api.error_state); |
|
182 |
} |
|
184 |
if (reset_state === "reset") { snf.api.trigger("reset") }; |
|
183 | 185 |
views.ErrorView.__super__.hide.apply(this); |
184 | 186 |
}, |
185 | 187 |
|
b/ui/static/snf/js/ui/web/ui_feedback_view.js | ||
---|---|---|
83 | 83 |
'data': $.param(data), |
84 | 84 |
'success': this.show_success, |
85 | 85 |
'error': this.show_error, |
86 |
'no_skip': true, |
|
87 |
'display': false, |
|
86 | 88 |
'handles_error': true |
87 | 89 |
} |
88 | 90 |
api.sync('create', undefined, opts); |
... | ... | |
93 | 95 |
}, |
94 | 96 |
|
95 | 97 |
onOpen: function() { |
98 |
var self = this; |
|
96 | 99 |
var point = this.text.val().length; |
97 | 100 |
this.text.show().focus().setCursorPosition(point); |
101 |
|
|
102 |
this.$(".closeme").unbind("click"); |
|
103 |
this.$(".closeme").bind("click", function(){ |
|
104 |
self.hide("reset") |
|
105 |
}); |
|
98 | 106 |
}, |
99 | 107 |
|
100 | 108 |
show_form: function() { |
... | ... | |
127 | 135 |
this.sending.hide(); |
128 | 136 |
}, |
129 | 137 |
|
130 |
hide: function() { |
|
131 |
snf.api.error_state = false; |
|
132 |
snf.api.trigger("change:error_state", snf.api.error_state); |
|
138 |
hide: function(reset_error_state) { |
|
139 |
// trigger api reset |
|
140 |
if (reset_error_state === "reset") { |
|
141 |
// report error feedback form |
|
142 |
if (snf.api.error_state == snf.api.STATES.ERROR) { |
|
143 |
snf.api.trigger("reset"); |
|
144 |
} |
|
145 |
} |
|
133 | 146 |
views.FeedbackView.__super__.hide.apply(this); |
134 | 147 |
}, |
135 | 148 |
|
b/ui/static/snf/js/ui/web/ui_icon_view.js | ||
---|---|---|
40 | 40 |
this.has_error = true; |
41 | 41 |
var action = "undefined"; |
42 | 42 |
try { |
43 |
action = args[0].ajax.error_params.extra_details['Action'];
|
|
43 |
action = _.last(args).error_params.extra_details['Action'];
|
|
44 | 44 |
} catch (err) {console.log(err)}; |
45 | 45 |
|
46 | 46 |
this.error.find(".action").text(action); |
... | ... | |
50 | 50 |
|
51 | 51 |
// show error overlay |
52 | 52 |
this.show_btn.click(_.bind(function() { |
53 |
this.show_error_overlay(this.vm.action_error); |
|
53 |
if (this.vm.action_error) { |
|
54 |
this.show_error_overlay(this.vm.action_error); |
|
55 |
} |
|
54 | 56 |
this.vm.reset_action_error(); |
55 | 57 |
}, this)); |
56 | 58 |
|
... | ... | |
66 | 68 |
}, this)); |
67 | 69 |
}, |
68 | 70 |
|
69 |
show_error_overlay: function(arguments) { |
|
70 |
var xhr = arguments[0]; |
|
71 |
var args = util.parse_api_error(arguments); |
|
71 |
show_error_overlay: function(args) { |
|
72 |
var args = util.parse_api_error.apply(util, args); |
|
72 | 73 |
|
73 | 74 |
// force logout if UNAUTHORIZED request arrives |
74 | 75 |
if (args.code == 401) { snf.ui.logout(); return }; |
75 |
|
|
76 |
|
|
76 | 77 |
var error_entry = [args.ns, args.code, args.message, args.type, args.details, args]; |
77 | 78 |
ui.main.error_view.show_error.apply(ui.main.error_view, error_entry); |
78 | 79 |
}, |
b/ui/static/snf/js/ui/web/ui_list_view.js | ||
---|---|---|
371 | 371 |
if (vm.in_transition()) { |
372 | 372 |
self.sel("vm_spinner", vm.id).fadeIn(200); |
373 | 373 |
} else { |
374 |
if (vm.pending_action || (self.actions.hovered && this.vm(vm).find("input").is(":checked"))) {
|
|
374 |
if (vm.pending_action || (self.actions.hovered && self.vm(vm).find("input").is(":checked"))) {
|
|
375 | 375 |
self.vm(vm).find(".action-indicator").show(); |
376 | 376 |
} else { |
377 | 377 |
self.sel("os_icon", vm.id).fadeIn(200); |
b/ui/static/snf/js/ui/web/ui_main_view.js | ||
---|---|---|
339 | 339 |
}, |
340 | 340 |
|
341 | 341 |
handle_api_error_state: function(state) { |
342 |
if (snf.api.error_state) { |
|
342 |
if (snf.api.error_state === snf.api.STATES.ERROR) {
|
|
343 | 343 |
this.stop_intervals(); |
344 | 344 |
} else { |
345 | 345 |
if (this.intervals_stopped) { |
... | ... | |
348 | 348 |
} |
349 | 349 |
}, |
350 | 350 |
|
351 |
handle_api_error: function(xhr, type, message) { |
|
351 |
handle_api_error: function(args) { |
|
352 |
if (arguments.length == 1) { arguments = _.toArray(arguments[0])}; |
|
353 |
|
|
354 |
if (!_.last(arguments).display) { |
|
355 |
return; |
|
356 |
} |
|
357 |
|
|
352 | 358 |
this.error_state = true; |
353 |
this.log.error("API ERRROR", arguments); |
|
354 | 359 |
|
355 | 360 |
var xhr = arguments[0]; |
356 |
var args = util.parse_api_error(arguments);
|
|
361 |
var args = util.parse_api_error.apply(util, arguments);
|
|
357 | 362 |
|
358 | 363 |
// force logout if UNAUTHORIZED request arrives |
359 | 364 |
if (args.code == 401) { snf.ui.logout(); return }; |
... | ... | |
401 | 406 |
this.update_status("Loading vms..."); |
402 | 407 |
storage.vms.fetch({refresh:true, update:false, success: function(){ |
403 | 408 |
self.update_status("VMS Loaded."); |
404 |
self.check_status() |
|
409 |
self.check_status();
|
|
405 | 410 |
}}); |
411 |
|
|
406 | 412 |
this.update_status("Loading networks..."); |
407 | 413 |
storage.networks.fetch({refresh:true, update:false, success: function(){ |
408 | 414 |
self.update_status("Networks loaded."); |
409 |
self.check_status() |
|
415 |
self.check_status();
|
|
410 | 416 |
}}); |
411 | 417 |
}, |
412 | 418 |
|
413 | 419 |
init_intervals: function() { |
414 |
this._networks = storage.networks.get_fetcher(snf.config.update_interval, snf.config.update_interval/2, 2, true, undefined); |
|
415 |
this._vms = storage.vms.get_fetcher(snf.config.update_interval, snf.config.update_interval/2, 2, true, undefined); |
|
420 |
this._networks = storage.networks.get_fetcher(snf.config.update_interval, |
|
421 |
snf.config.update_interval - 100, |
|
422 |
1, true, undefined); |
|
423 |
this._vms = storage.vms.get_fetcher(snf.config.update_interval, |
|
424 |
snf.config.update_interval - 100, |
|
425 |
1, true, undefined); |
|
416 | 426 |
}, |
417 | 427 |
|
418 | 428 |
stop_intervals: function() { |
... | ... | |
679 | 689 |
$(".large-spinner").remove(); |
680 | 690 |
|
681 | 691 |
storage.vms.reset_pending_actions(); |
682 |
storage.vms.reset_stats_update();
|
|
692 |
storage.vms.stop_stats_update();
|
|
683 | 693 |
|
684 | 694 |
// show current view |
685 | 695 |
this.show_view_pane(); |
b/ui/static/snf/js/ui/web/ui_networks_view.js | ||
---|---|---|
436 | 436 |
|
437 | 437 |
$(window).trigger("resize"); |
438 | 438 |
}, this)) |
439 |
|
|
439 |
|
|
440 | 440 |
this.apply.click(_.bind(function(){ |
441 | 441 |
this.apply.addClass("in-progress"); |
442 |
this.vm.set_firewall(this.network.id, this.value(), _.bind(function() { |
|
442 |
|
|
443 |
// make the api call |
|
444 |
this.vm.set_firewall(this.network.id, this.value(), |
|
445 |
// complete |
|
446 |
_.bind(function() { |
|
447 |
// complete callback |
|
448 |
this.apply.removeClass("in-progress"); |
|
449 |
}, this), |
|
450 |
// error |
|
451 |
_.bind(function(){ |
|
452 |
this.vm.remove_pending_firewall(this.network.id, this.value()); |
|
443 | 453 |
}, this)); |
444 | 454 |
this.hide_firewall(); |
445 | 455 |
}, this)) |
b/ui/static/snf/js/ui/web/ui_single_view.js | ||
---|---|---|
104 | 104 |
}, |
105 | 105 |
|
106 | 106 |
update_current_vm: function() { |
107 |
storage.vms.reset_stats_update();
|
|
107 |
storage.vms.stop_stats_update();
|
|
108 | 108 |
|
109 | 109 |
try { |
110 | 110 |
this.current_vm_instance = storage.vms.at(this.current_vm); |
b/ui/static/snf/js/utils.js | ||
---|---|---|
47 | 47 |
|
48 | 48 |
this.error = function() { |
49 | 49 |
var args = [2]; args.push.call(args, arguments); |
50 |
try { |
|
51 |
console.trace() |
|
52 |
} catch (err) {} |
|
53 | 50 |
this._log.apply(this, args); |
54 | 51 |
} |
55 | 52 |
|
... | ... | |
210 | 207 |
}, |
211 | 208 |
|
212 | 209 |
'abort': {}, |
213 |
'parserror': {} |
|
210 |
'parserror': {}, |
|
211 |
'413': { |
|
212 |
'title': "Account warning" |
|
213 |
} |
|
214 | 214 |
} |
215 | 215 |
|
216 | 216 |
synnefo.util.array_diff = function(arr1, arr2) { |
... | ... | |
285 | 285 |
} |
286 | 286 |
} |
287 | 287 |
|
288 |
synnefo.util.parse_api_error = function(arguments) {
|
|
289 |
arguments = arguments[0];
|
|
288 |
synnefo.util.parse_api_error = function() { |
|
289 |
if (arguments.length == 1) { arguments = arguments[0] };
|
|
290 | 290 |
|
291 | 291 |
var xhr = arguments[0]; |
292 | 292 |
var error_message = arguments[1]; |
293 | 293 |
var error_thrown = arguments[2]; |
294 |
var ajax_settings = arguments.ajax || {}; |
|
295 |
var call_settings = arguments.ajax ? arguments.ajax.error_params || {} : {}; |
|
296 |
|
|
294 |
var ajax_settings = _.last(arguments) || {}; |
|
295 |
var call_settings = ajax_settings.error_params || {}; |
|
297 | 296 |
var json_data = undefined; |
297 |
|
|
298 |
var critical = ajax_settings.critical === undefined ? true : ajax_settings.critical; |
|
299 |
|
|
298 | 300 |
if (xhr.responseText) { |
299 | 301 |
try { |
300 | 302 |
json_data = JSON.parse(xhr.responseText) |
... | ... | |
315 | 317 |
'message': 'Api error', |
316 | 318 |
'type': 'API', |
317 | 319 |
'allow_report': true, |
318 |
'fatal_error': ajax_settings.critical || false |
|
320 |
'fatal_error': ajax_settings.critical || false, |
|
321 |
'non_critical': !critical |
|
319 | 322 |
} |
320 | 323 |
|
321 | 324 |
var code = -1; |
... | ... | |
328 | 331 |
defaults.non_critical = true; |
329 | 332 |
defaults.allow_report = false; |
330 | 333 |
defaults.allow_reload = false; |
334 |
error_message = "limit_error"; |
|
335 |
} |
|
336 |
|
|
337 |
if (critical) { |
|
338 |
defaults.allow_report = true; |
|
331 | 339 |
} |
332 | 340 |
|
333 | 341 |
if (json_data) { |
... | ... | |
337 | 345 |
error_message = obj.message; |
338 | 346 |
}) |
339 | 347 |
} |
340 |
|
|
348 |
|
|
341 | 349 |
extra = {'URL': ajax_settings.url}; |
342 | 350 |
options = {}; |
343 | 351 |
options = _.extend(options, {'details': details, 'message': error_message, 'ns': module, 'extra_details': extra}); |
344 | 352 |
options = _.extend(options, call_settings); |
345 | 353 |
options = _.extend(options, synnefo.i18n.API_ERROR_MESSAGES[error_message] || {}); |
354 |
options = _.extend(options, synnefo.i18n.API_ERROR_MESSAGES[code] || {}); |
|
346 | 355 |
|
347 | 356 |
if (window.ERROR_OVERRIDES && window.ERROR_OVERRIDES[options.message]) { |
348 | 357 |
options.message = window.ERROR_OVERRIDES[options.message]; |
b/ui/static/snf/js/views.js | ||
---|---|---|
82 | 82 |
this.defaults = { |
83 | 83 |
load: false, |
84 | 84 |
closeOnClick: false, |
85 |
closeOnEsc: false, |
|
85 | 86 |
mask: { |
86 | 87 |
color: "#444", |
87 | 88 |
loadSpeed: snf.config.overlay_speed || 0, |
... | ... | |
180 | 181 |
}, |
181 | 182 |
|
182 | 183 |
_onOpen: function() { |
184 |
// clear previously bound click events |
|
185 |
$(this.el).find(".closeme").unbind("click"); |
|
186 |
|
|
183 | 187 |
if ($(this.el).find(".closeme").length) { |
184 | 188 |
$(this.el).find(".closeme").click(_.bind(function(){ |
185 | 189 |
this.hide(); |
... | ... | |
270 | 274 |
_update_vm_details: function() { |
271 | 275 |
if (!this.vm) { console.error("invalid view state"); return } |
272 | 276 |
this.set_subtitle(this.vm.get("name") + snf.ui.helpers.vm_icon_tag(this.vm, "small")); |
273 |
|
|
274 |
var ico_path = snf.ui.helpers.os_icon_path(this.vm.get("OS"), "oslarge"); |
|
275 |
this.$(".content").css({"background-image":"url(" + ico_path +")"}) |
|
276 | 277 |
this.update_vm_details() |
277 | 278 |
}, |
278 | 279 |
|
b/ui/templates/home.html | ||
---|---|---|
447 | 447 |
<span class="show-details">{% trans "Show details" %}</span> |
448 | 448 |
<span class="hide-details">{% trans "Hide details" %}</span> |
449 | 449 |
<span class="report-error">{% trans "Send report" %}</span> |
450 |
<span class="reload-app">{% trans "Reload application" %}</span>
|
|
450 |
<span class="reload-app">{% trans "Reload" %}</span> |
|
451 | 451 |
</div> |
452 | 452 |
</div> |
453 | 453 |
|
Also available in: Unified diff