11 var callPackagelist
= rpc
.declare({
13 method
: 'packagelist',
16 var callSystemBoard
= rpc
.declare({
21 var callUpgradeStart
= rpc
.declare({
23 method
: 'upgrade_start',
27 function get_branch(version
) {
28 // determine branch of a version
29 // SNAPSHOT -> SNAPSHOT
30 // 21.02-SNAPSHOT -> 21.02
31 // 21.02.0-rc1 -> 21.02
33 return version
.replace("-SNAPSHOT", "").split(".").slice(0, 2).join(".");
36 function install_sysupgrade(url
, keep
, sha256
) {
37 displayStatus("notice spinning", E('p', _('Downloading firmware from server to browser')));
40 'Content-Type': 'application/x-www-form-urlencoded'
45 var form_data
= new FormData();
46 form_data
.append("sessionid", rpc
.getSessionID());
47 form_data
.append("filename", "/tmp/firmware.bin");
48 form_data
.append("filemode", 600);
49 form_data
.append("filedata", response
.blob());
51 displayStatus("notice spinning", E('p', _('Uploading firmware from browser to device')));
52 request
.get(L
.env
.cgi_base
+ "/cgi-upload", {
56 .then(response
=> response
.json())
58 if (response
.sha256sum
!= sha256
) {
59 displayStatus("warning", [
60 E('b', _('Wrong checksum')),
61 E('p', _('Error during download of firmware. Please try again')),
68 displayStatus('warning spinning', E('p', _('Installing the sysupgrade. Do not unpower device!')));
69 L
.resolveDefault(callUpgradeStart(keep
), {}).then(response
=> {
71 ui
.awaitReconnect(window
.location
.host
);
73 ui
.awaitReconnect('192.168.1.1', 'openwrt.lan');
81 function request_sysupgrade(server_url
, data
) {
84 if (data
.request_hash
) {
85 req
= request
.get(server_url
+ "/api/build/" + data
.request_hash
)
87 req
= request
.post(server_url
+ "/api/build", {
88 profile
: data
.board_name
,
90 version
: data
.version
,
91 packages
: data
.packages
,
96 req
.then(response
=> {
97 switch (response
.status
) {
99 var res
= response
.json()
101 for (image
of res
.images
) {
102 if (image
.type
== "sysupgrade") {
106 if (image
.name
!= undefined) {
107 var sysupgrade_url
= server_url
+ "/store/" + res
.bin_dir
+ "/" + image
.name
;
109 var keep
= E('input', {
115 _('Version'), res
.version_number
+ ' ' + res
.version_code
,
117 'href': sysupgrade_url
119 _('SHA256'), image
.sha256
,
120 _('Build Date'), res
.build_at
,
121 _('Target'), res
.target
,
124 var table
= E('div', {
128 for (var i
= 0; i
< fields
.length
; i
+= 2) {
129 table
.appendChild(E('div', {
138 }, [(fields
[i
+ 1] != null) ? fields
[i
+ 1] : '?'])
144 E('p', {}, E('label', {
147 keep
, ' ', _('Keep settings and retain the current configuration')
154 'click': ui
.hideModal
158 'class': 'btn cbi-button-action',
159 'click': function() {
160 install_sysupgrade(sysupgrade_url
, keep
.checked
, image
.sha256
)
162 }, _('Install Sysupgrade'))
166 ui
.showModal(_('Successfully created sysupgrade image'), modal_body
);
171 res
= response
.json()
172 data
.request_hash
= res
.request_hash
;
173 switch (res
.status
) {
175 displayStatus("notice spinning", E('p', _('Request in build queue')));
178 displayStatus("notice spinning", E('p', _('Building the sysupgrade image')));
181 setTimeout(function() {
182 request_sysupgrade(server_url
, data
);
185 case 400: // bad request
186 case 422: // bad package
187 case 500: // build failed
188 res
= response
.json()
190 E('p', {}, _(res
.message
)),
191 E('p', {}, _("Please report the error message and request")),
192 E('b', {}, _("Request to server:")),
193 E('pre', {}, JSON
.stringify(data
, null, 4)),
198 body
.push(E('b', {}, "STDOUT:"))
199 body
.push(E('pre', {}, res
.stdout
))
204 body
.push(E('b', {}, "STDERR:"))
205 body
.push(E('pre', {}, res
.stderr
))
215 'click': ui
.hideModal
219 ui
.showModal(_('Error building the sysupgrade'), body
);
225 function check_sysupgrade(server_url
, current_version
, target
, board_name
, packages
) {
226 displayStatus("notice spinning", E('p', _('Searching for an available sysupgrade')));
227 var current_branch
= get_branch(current_version
);
228 var advanced_mode
= uci
.get_first('attendedsysupgrade', 'client', 'advanced_mode') || 0;
231 request
.get(server_url
+ "/api/latest", {
234 .then(response
=> response
.json())
236 if (current_version
== "SNAPSHOT") {
237 candidates
.push("SNAPSHOT");
239 for (let version
of response
["latest"]) {
240 var branch
= get_branch(version
);
242 // already latest version installed
243 if (current_version
== version
) {
247 // skip branch upgrades outside the advanced mode
248 if (current_branch
!= branch
&& advanced_mode
== 0) {
252 candidates
.unshift(version
);
254 // don't offer branches older than the current
255 if (current_branch
== branch
) {
260 if (candidates
.length
) {
265 board_name
: board_name
,
267 version
: candidates
[0],
268 packages
: Object
.keys(packages
).sort(),
272 m
= new form
.JSONMap(mapdata
, '');
274 s
= m
.section(form
.NamedSection
, 'request', 'example', '',
275 'Use defaults for the safest update');
276 o
= s
.option(form
.ListValue
, 'version', 'Select firmware version');
277 for (let candidate
of candidates
) {
278 o
.value(candidate
, candidate
);
281 if (advanced_mode
== 1) {
282 o
= s
.option(form
.Value
, 'board_name', 'Board Name / Profile');
283 o
= s
.option(form
.DynamicList
, 'packages', 'Packages');
288 .then(function(form_rendered
) {
289 ui
.showModal(_('New upgrade available'), [
296 'click': ui
.hideModal
300 'class': 'btn cbi-button-action',
301 'click': function() {
302 m
.save().then(foo
=> {
304 server_url
, mapdata
.request
308 }, _('Request Sysupgrade'))
313 ui
.showModal(_('No upgrade available'), [
314 E('p', {}, _("The device runs the latest firmware version")),
320 'click': ui
.hideModal
327 ui
.showModal(_('Error connecting to upgrade server'), [
328 E('p', {}, _('Could not reach API at "%s". Please try again later.'.format(server_url
))),
335 'click': ui
.hideModal
342 function displayStatus(type
, content
) {
344 var message
= ui
.showModal('', '');
346 message
.classList
.add('alert-message');
347 DOMTokenList
.prototype.add
.apply(message
.classList
, type
.split(/\s+/));
350 dom
.content(message
, content
);
359 L
.resolveDefault(callPackagelist(), {}),
360 L
.resolveDefault(callSystemBoard(), {}),
361 uci
.load('attendedsysupgrade')
364 render: function(res
) {
365 var packages
= res
[0].packages
;
366 var current_version
= res
[1].release
.version
;
367 var target
= res
[1].release
.target
;
368 var board_name
= res
[1].board_name
;
369 var auto_search
= uci
.get_first('attendedsysupgrade', 'client', 'auto_search') || 1;
370 var server_url
= uci
.get_first('attendedsysupgrade', 'server', 'url');
373 E('h2', _("Attended Sysupgrade")),
374 E('p', _('The attended sysupgrade service allows to easily upgrade vanilla and custom firmware images.')),
375 E('p', _('This is done by building a new firmware on demand via an online service.'))
378 if (auto_search
== 1) {
379 check_sysupgrade(server_url
, current_version
, target
, board_name
, packages
)
383 'class': 'btn cbi-button-positive',
384 'click': function() {
385 check_sysupgrade(server_url
, current_version
, target
, board_name
, packages
)
387 }, _('Search for sysupgrade')));