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
;
174 if ("queue_position" in res
)
175 displayStatus("notice spinning", E('p', _('Request in build queue position %d'.format(res
.queue_position
))));
177 displayStatus("notice spinning", E('p', _('Building firmware sysupgrade image')));
179 setTimeout(function() {
180 request_sysupgrade(server_url
, data
);
183 case 400: // bad request
184 case 422: // bad package
185 case 500: // build failed
186 res
= response
.json()
188 E('p', {}, _(res
.message
)),
189 E('p', {}, _("Please report the error message and request")),
190 E('b', {}, _("Request to server:")),
191 E('pre', {}, JSON
.stringify(data
, null, 4)),
196 body
.push(E('b', {}, "STDOUT:"))
197 body
.push(E('pre', {}, res
.stdout
))
202 body
.push(E('b', {}, "STDERR:"))
203 body
.push(E('pre', {}, res
.stderr
))
213 'click': ui
.hideModal
217 ui
.showModal(_('Error building the sysupgrade'), body
);
223 function check_sysupgrade(server_url
, current_version
, target
, board_name
, packages
) {
224 displayStatus("notice spinning", E('p', _('Searching for an available sysupgrade')));
225 var current_branch
= get_branch(current_version
);
226 var advanced_mode
= uci
.get_first('attendedsysupgrade', 'client', 'advanced_mode') || 0;
229 request
.get(server_url
+ "/json/latest.json", {
232 .then(response
=> response
.json())
234 if (current_version
== "SNAPSHOT") {
235 candidates
.push("SNAPSHOT");
237 for (let version
of response
["latest"]) {
238 var branch
= get_branch(version
);
240 // already latest version installed
241 if (current_version
== version
) {
245 // skip branch upgrades outside the advanced mode
246 if (current_branch
!= branch
&& advanced_mode
== 0) {
250 candidates
.unshift(version
);
252 // don't offer branches older than the current
253 if (current_branch
== branch
) {
258 if (candidates
.length
) {
263 board_name
: board_name
,
265 version
: candidates
[0],
266 packages
: Object
.keys(packages
).sort(),
270 m
= new form
.JSONMap(mapdata
, '');
272 s
= m
.section(form
.NamedSection
, 'request', 'example', '',
273 'Use defaults for the safest update');
274 o
= s
.option(form
.ListValue
, 'version', 'Select firmware version');
275 for (let candidate
of candidates
) {
276 o
.value(candidate
, candidate
);
279 if (advanced_mode
== 1) {
280 o
= s
.option(form
.Value
, 'board_name', 'Board Name / Profile');
281 o
= s
.option(form
.DynamicList
, 'packages', 'Packages');
286 .then(function(form_rendered
) {
287 ui
.showModal(_('New upgrade available'), [
294 'click': ui
.hideModal
298 'class': 'btn cbi-button-action',
299 'click': function() {
300 m
.save().then(foo
=> {
302 server_url
, mapdata
.request
306 }, _('Request Sysupgrade'))
311 ui
.showModal(_('No upgrade available'), [
312 E('p', {}, _("The device runs the latest firmware version")),
318 'click': ui
.hideModal
325 ui
.showModal(_('Error connecting to upgrade server'), [
326 E('p', {}, _('Could not reach API at "%s". Please try again later.'.format(server_url
))),
333 'click': ui
.hideModal
340 function displayStatus(type
, content
) {
342 var message
= ui
.showModal('', '');
344 message
.classList
.add('alert-message');
345 DOMTokenList
.prototype.add
.apply(message
.classList
, type
.split(/\s+/));
348 dom
.content(message
, content
);
357 L
.resolveDefault(callPackagelist(), {}),
358 L
.resolveDefault(callSystemBoard(), {}),
359 uci
.load('attendedsysupgrade')
362 render: function(res
) {
363 var packages
= res
[0].packages
;
364 var current_version
= res
[1].release
.version
;
365 var target
= res
[1].release
.target
;
366 var board_name
= res
[1].board_name
;
367 var auto_search
= uci
.get_first('attendedsysupgrade', 'client', 'auto_search') || 1;
368 var server_url
= uci
.get_first('attendedsysupgrade', 'server', 'url');
371 E('h2', _("Attended Sysupgrade")),
372 E('p', _('The attended sysupgrade service allows to easily upgrade vanilla and custom firmware images.')),
373 E('p', _('This is done by building a new firmware on demand via an online service.'))
376 if (auto_search
== 1) {
377 check_sysupgrade(server_url
, current_version
, target
, board_name
, packages
)
381 'class': 'btn cbi-button-positive',
382 'click': function() {
383 check_sysupgrade(server_url
, current_version
, target
, board_name
, packages
)
385 }, _('Search for sysupgrade')));