11 var callPackagelist = rpc.declare({
13 method: 'packagelist',
16 var callSystemBoard = rpc.declare({
21 var callUpgradeStart = rpc.declare({
23 method: 'upgrade_start',
27 function install_sysupgrade(url, keep, sha256) {
28 displayStatus("notice spinning", E('p', _('Downloading firmware from server to browser')));
31 'Content-Type': 'application/x-www-form-urlencoded'
36 var form_data = new FormData();
37 form_data.append("sessionid", rpc.getSessionID());
38 form_data.append("filename", "/tmp/firmware.bin");
39 form_data.append("filemode", 600);
40 form_data.append("filedata", response.blob());
42 displayStatus("notice spinning", E('p', _('Uploading firmware from browser to device')));
43 request.get(L.env.cgi_base + "/cgi-upload", {
47 .then(response => response.json())
49 if (response.sha256sum != sha256) {
50 displayStatus("warning", [
51 E('b', _('Wrong checksum')),
52 E('p', _('Error during download of firmware. Please try again')),
59 displayStatus('warning spinning', E('p', _('Installing the sysupgrade. Do not unpower device!')));
60 L.resolveDefault(callUpgradeStart(keep), {}).then(response => {
62 ui.awaitReconnect(window.location.host);
64 ui.awaitReconnect('192.168.1.1', 'openwrt.lan');
72 function request_sysupgrade(server_url, data) {
75 if (data.request_hash) {
76 req = request.get(server_url + "/api/build/" + data.request_hash)
78 req = request.post(server_url + "/api/build", {
79 profile: data.board_name,
81 version: data.version,
82 packages: data.packages,
87 req.then(response => {
88 switch (response.status) {
90 var res = response.json()
93 for (image of res.images) {
94 if (image.type == "sysupgrade") {
98 if (image.name != undefined) {
99 var sysupgrade_url = server_url + "/store/" + res.bin_dir + "/" + image.name;
101 var keep = E('input', {
107 _('Version'), res.version_number + ' ' + res.version_code,
109 'href': sysupgrade_url
111 _('SHA256'), image.sha256,
112 _('Build Date'), res.build_at,
113 _('Target'), res.target,
116 var table = E('div', {
120 for (var i = 0; i < fields.length; i += 2) {
121 table.appendChild(E('div', {
130 }, [(fields[i + 1] != null) ? fields[i + 1] : '?'])
136 E('p', {}, E('label', {
139 keep, ' ', _('Keep settings and retain the current configuration')
146 'click': ui.hideModal
150 'class': 'btn cbi-button-action',
151 'click': function() {
152 install_sysupgrade(sysupgrade_url, keep.checked, image.sha256)
154 }, _('Install Sysupgrade'))
158 ui.showModal(_('Successfully created sysupgrade image'), modal_body);
163 res = response.json()
164 data.request_hash = res.request_hash;
165 switch (res.status) {
167 displayStatus("notice spinning", E('p', _('Request in build queue')));
170 displayStatus("notice spinning", E('p', _('Building the sysupgrade image')));
173 setTimeout(function() {
174 request_sysupgrade(server_url, data);
177 case 400: // bad request
178 case 422: // bad package
179 case 500: // build failed
180 res = response.json()
182 E('p', {}, _(res.message)),
183 E('p', {}, _("Please report the error message and request")),
184 E('b', {}, _("Request to server:")),
185 E('pre', {}, JSON.stringify(data, null, 4)),
190 body.push(E('b', {}, "STDOUT:"))
191 body.push(E('pre', {}, res.stdout))
196 body.push(E('b', {}, "STDERR:"))
197 body.push(E('pre', {}, res.stderr))
207 'click': ui.hideModal
211 ui.showModal(_('Error building the sysupgrade'), body);
217 function check_sysupgrade(server_url, current_version, target, board_name, packages) {
218 displayStatus("notice spinning", E('p', _('Searching for an available sysupgrade')));
219 var current_branch = current_version.split(".").slice(0, 2).join(".");
220 var advanced_mode = uci.get_first('attendedsysupgrade', 'client', 'advanced_mode') || 0;
222 fetch(server_url + "/api/latest")
223 .then(response => response.json())
225 if (current_version == "SNAPSHOT") {
226 candidates.push("SNAPSHOT");
228 for (let version of response["latest"]) {
229 var branch = version.split(".").slice(0, 2).join(".");
231 // already latest version installed
232 if (current_version == version) {
236 // skip branch upgrades outside the advanced mode
237 if (current_branch != branch && advanced_mode == 0) {
241 candidates.unshift(version);
243 // don't offer branches older than the current
244 if (current_branch == branch) {
252 console.log(candidates);
256 board_name: board_name,
258 version: candidates[0],
259 packages: Object.keys(packages).sort(),
263 m = new form.JSONMap(mapdata, '');
265 s = m.section(form.NamedSection, 'request', 'example', '',
266 'Use defaults for the safest update');
267 o = s.option(form.ListValue, 'version', 'Select firmware version');
268 for (let candidate of candidates) {
269 o.value(candidate, candidate);
272 if (advanced_mode == 1) {
273 o = s.option(form.Value, 'board_name', 'Board Name / Profile');
274 o = s.option(form.DynamicList, 'packages', 'Packages');
279 .then(function(form_rendered) {
280 ui.showModal(_('New upgrade available'), [
287 'click': ui.hideModal
291 'class': 'btn cbi-button-action',
292 'click': function() {
293 m.save().then(foo => {
295 server_url, mapdata.request
299 }, _('Request Sysupgrade'))
304 ui.showModal(_('No upgrade available'), [
305 E('p', {}, _("The device runs the latest firmware version")),
311 'click': ui.hideModal
319 function displayStatus(type, content) {
321 var message = ui.showModal('', '');
323 message.classList.add('alert-message');
324 DOMTokenList.prototype.add.apply(message.classList, type.split(/\s+/));
327 dom.content(message, content);
336 L.resolveDefault(callPackagelist(), {}),
337 L.resolveDefault(callSystemBoard(), {}),
338 uci.load('attendedsysupgrade')
341 render: function(res) {
342 var packages = res[0].packages;
343 var current_version = res[1].release.version;
344 var target = res[1].release.target;
345 var board_name = res[1].board_name;
346 var auto_search = uci.get_first('attendedsysupgrade', 'client', 'auto_search') || 1;
347 var server_url = uci.get_first('attendedsysupgrade', 'server', 'url');
350 E('h2', _("Attended Sysupgrade")),
351 E('p', _('The attended sysupgrade service allows to easily upgrade vanilla and custom firmware images.')),
352 E('p', _('This is done by building a new firmware on demand via an online service.'))
355 if (auto_search == 1) {
356 check_sysupgrade(server_url, current_version, target, board_name, packages)
360 'class': 'btn cbi-button-positive',
361 'click': function() {
362 check_sysupgrade(server_url, current_version, target, board_name, packages)
364 }, _('Search for sysupgrade')));