diff options
Diffstat (limited to 'applications/luci-app-attendedsysupgrade/htdocs/luci-static/resources/view/attendedsysupgrade/overview.js')
-rw-r--r-- | applications/luci-app-attendedsysupgrade/htdocs/luci-static/resources/view/attendedsysupgrade/overview.js | 734 |
1 files changed, 382 insertions, 352 deletions
diff --git a/applications/luci-app-attendedsysupgrade/htdocs/luci-static/resources/view/attendedsysupgrade/overview.js b/applications/luci-app-attendedsysupgrade/htdocs/luci-static/resources/view/attendedsysupgrade/overview.js index fc179212b1..b148e793b2 100644 --- a/applications/luci-app-attendedsysupgrade/htdocs/luci-static/resources/view/attendedsysupgrade/overview.js +++ b/applications/luci-app-attendedsysupgrade/htdocs/luci-static/resources/view/attendedsysupgrade/overview.js @@ -9,382 +9,412 @@ 'require dom'; var callPackagelist = rpc.declare({ - object: 'rpc-sys', - method: 'packagelist', + object: 'rpc-sys', + method: 'packagelist', }); var callSystemBoard = rpc.declare({ - object: 'system', - method: 'board' + object: 'system', + method: 'board' }); var callUpgradeStart = rpc.declare({ - object: 'rpc-sys', - method: 'upgrade_start', - params: ["keep"] + object: 'rpc-sys', + method: 'upgrade_start', + params: ["keep"] }); function get_branch(version) { - // determine branch of a version - // SNAPSHOT -> SNAPSHOT - // 21.02-SNAPSHOT -> 21.02 - // 21.02.0-rc1 -> 21.02 - // 19.07.8 -> 19.07 - return version.replace("-SNAPSHOT", "").split(".").slice(0, 2).join("."); + // determine branch of a version + // SNAPSHOT -> SNAPSHOT + // 21.02-SNAPSHOT -> 21.02 + // 21.02.0-rc1 -> 21.02 + // 19.07.8 -> 19.07 + return version.replace("-SNAPSHOT", "").split(".").slice(0, 2).join("."); +} + +function get_revision_count(revision) { + return parseInt(revision.substring(1).split("-")[0]) +} + +function error_api_connect(response) { + console.log(response) + ui.showModal(_('Error connecting to upgrade server'), [ + E('p', {}, _(`Could not reach API at "${response.url}. Please try again later.`)), + E('pre', {}, response.responseText), + E('div', { + 'class': 'right' + }, [ + E('div', { + 'class': 'btn', + 'click': ui.hideModal + }, _('Close')) + ]) + ]); } function install_sysupgrade(url, keep, sha256) { - displayStatus("notice spinning", E('p', _('Downloading firmware from server to browser'))); - request.get(url, { - headers: { - 'Content-Type': 'application/x-www-form-urlencoded' - }, - responseType: 'blob' - }) - .then(response => { - var form_data = new FormData(); - form_data.append("sessionid", rpc.getSessionID()); - form_data.append("filename", "/tmp/firmware.bin"); - form_data.append("filemode", 600); - form_data.append("filedata", response.blob()); - - displayStatus("notice spinning", E('p', _('Uploading firmware from browser to device'))); - request.get(L.env.cgi_base + "/cgi-upload", { - method: 'PUT', - content: form_data - }) - .then(response => response.json()) - .then(response => { - if (response.sha256sum != sha256) { - displayStatus("warning", [ - E('b', _('Wrong checksum')), - E('p', _('Error during download of firmware. Please try again')), - E('div', { - 'class': 'btn', - 'click': ui.hideModal - }, _('Close')) - ]); - } else { - displayStatus('warning spinning', E('p', _('Installing the sysupgrade. Do not unpower device!'))); - L.resolveDefault(callUpgradeStart(keep), {}).then(response => { - if (keep) { - ui.awaitReconnect(window.location.host); - } else { - ui.awaitReconnect('192.168.1.1', 'openwrt.lan'); - } - }); - } - }); - }); + displayStatus("notice spinning", E('p', _('Downloading firmware from server to browser'))); + request.get(url, { + headers: { + 'Content-Type': 'application/x-www-form-urlencoded' + }, + responseType: 'blob' + }) + .then(response => { + var form_data = new FormData(); + form_data.append("sessionid", rpc.getSessionID()); + form_data.append("filename", "/tmp/firmware.bin"); + form_data.append("filemode", 600); + form_data.append("filedata", response.blob()); + + displayStatus("notice spinning", E('p', _('Uploading firmware from browser to device'))); + request.get(`${L.env.cgi_base}/cgi-upload`, { + method: 'PUT', + content: form_data + }) + .then(response => response.json()) + .then(response => { + if (response.sha256sum != sha256) { + displayStatus("warning", [ + E('b', _('Wrong checksum')), + E('p', _('Error during download of firmware. Please try again')), + E('div', { + 'class': 'btn', + 'click': ui.hideModal + }, _('Close')) + ]); + } else { + displayStatus('warning spinning', E('p', _('Installing the sysupgrade. Do not unpower device!'))); + L.resolveDefault(callUpgradeStart(keep), {}).then(response => { + if (keep) { + ui.awaitReconnect(window.location.host); + } else { + ui.awaitReconnect('192.168.1.1', 'openwrt.lan'); + } + }); + } + }); + }); } function request_sysupgrade(server_url, data) { - var res, req; - - if (data.request_hash) { - req = request.get(server_url + "/api/build/" + data.request_hash) - } else { - req = request.post(server_url + "/api/build", { - profile: data.board_name, - target: data.target, - version: data.version, - packages: data.packages, - diff_packages: true, - }) - } - - req.then(response => { - switch (response.status) { - case 200: - var res = response.json() - var image; - for (image of res.images) { - if (image.type == "sysupgrade") { - break; - } - } - if (image.name != undefined) { - var sysupgrade_url = server_url + "/store/" + res.bin_dir + "/" + image.name; - - var keep = E('input', { - type: 'checkbox' - }) - keep.checked = true; - - var fields = [ - _('Version'), res.version_number + ' ' + res.version_code, - _('File'), E('a', { - 'href': sysupgrade_url - }, image.name), - _('SHA256'), image.sha256, - _('Build Date'), res.build_at, - _('Target'), res.target, - ]; - - var table = E('div', { - 'class': 'table' - }); - - for (var i = 0; i < fields.length; i += 2) { - table.appendChild(E('div', { - 'class': 'tr' - }, [ - E('div', { - 'class': 'td left', - 'width': '33%' - }, [fields[i]]), - E('div', { - 'class': 'td left' - }, [(fields[i + 1] != null) ? fields[i + 1] : '?']) - ])); - } - - var modal_body = [ - table, - E('p', {}, E('label', { - 'class': 'btn' - }, [ - keep, ' ', _('Keep settings and retain the current configuration') - ])), - E('div', { - 'class': 'right' - }, [ - E('div', { - 'class': 'btn', - 'click': ui.hideModal - }, _('Cancel')), - ' ', - E('div', { - 'class': 'btn cbi-button-action', - 'click': function() { - install_sysupgrade(sysupgrade_url, keep.checked, image.sha256) - } - }, _('Install Sysupgrade')) - ]) - ] - - ui.showModal(_('Successfully created sysupgrade image'), modal_body); - } - - break; - case 202: - res = response.json() - data.request_hash = res.request_hash; - - if ("queue_position" in res) - displayStatus("notice spinning", E('p', _('Request in build queue position %d'.format(res.queue_position)))); - else - displayStatus("notice spinning", E('p', _('Building firmware sysupgrade image'))); - - setTimeout(function() { - request_sysupgrade(server_url, data); - }, 5000); - break; - case 400: // bad request - case 422: // bad package - case 500: // build failed - res = response.json() - var body = [ - E('p', {}, res.detail), - E('p', {}, _("Please report the error message and request")), - E('b', {}, _("Request to server:")), - E('pre', {}, JSON.stringify(data, null, 4)), - - ] - - if (res.stdout) { - body.push(E('b', {}, "STDOUT:")) - body.push(E('pre', {}, res.stdout)) - - } - - if (res.stderr) { - body.push(E('b', {}, "STDERR:")) - body.push(E('pre', {}, res.stderr)) - - } - - body = body.concat([ - E('div', { - 'class': 'right' - }, [ - E('div', { - 'class': 'btn', - 'click': ui.hideModal - }, _('Close')) - ]) - ]); - ui.showModal(_('Error building the sysupgrade'), body); - break; - } - }); + var res, req; + + if (data.request_hash) { + req = request.get(`${server_url}/api/v1/build/${data.request_hash}`) + } else { + req = request.post(`${server_url}/api/v1/build`, { + profile: data.board_name, + target: data.target, + version: data.version, + packages: data.packages, + diff_packages: true, + }) + } + + req.then(response => { + switch (response.status) { + case 200: + res = response.json() + var image; + for (image of res.images) { + if (image.type == "sysupgrade") { + break; + } + } + if (image.name != undefined) { + var sysupgrade_url = `${server_url}/store/${res.bin_dir}/${image.name}`; + + var keep = E('input', { + type: 'checkbox' + }) + keep.checked = true; + + var fields = [ + _('Version'), `${res.version_number} ${res.version_code}`, + _('File'), E('a', { + 'href': sysupgrade_url + }, image.name), + _('SHA256'), image.sha256, + _('Build Date'), res.build_at, + _('Target'), res.target, + ]; + + var table = E('div', { + 'class': 'table' + }); + + for (var i = 0; i < fields.length; i += 2) { + table.appendChild(E('div', { + 'class': 'tr' + }, [ + E('div', { + 'class': 'td left', + 'width': '33%' + }, [fields[i]]), + E('div', { + 'class': 'td left' + }, [(fields[i + 1] != null) ? fields[i + 1] : '?']) + ])); + } + + var modal_body = [ + table, + E('p', {}, E('label', { + 'class': 'btn' + }, [ + keep, ' ', _('Keep settings and retain the current configuration') + ])), + E('div', { + 'class': 'right' + }, [ + E('div', { + 'class': 'btn', + 'click': ui.hideModal + }, _('Cancel')), + ' ', + E('div', { + 'class': 'btn cbi-button-action', + 'click': function() { + install_sysupgrade(sysupgrade_url, keep.checked, image.sha256) + } + }, _('Install Sysupgrade')) + ]) + ] + + ui.showModal(_('Successfully created sysupgrade image'), modal_body); + } + + break; + case 202: + res = response.json() + data.request_hash = res.request_hash; + + if ("queue_position" in res) + displayStatus("notice spinning", E('p', _('Request in build queue position %d'.format(res.queue_position)))); + else + displayStatus("notice spinning", E('p', _('Building firmware sysupgrade image'))); + + setTimeout(function() { + request_sysupgrade(server_url, data); + }, 5000); + break; + case 400: // bad request + case 422: // bad package + case 500: // build failed + res = response.json() + var body = [ + E('p', {}, res.detail), + E('p', {}, _("Please report the error message and request")), + E('b', {}, _("Request to server:")), + E('pre', {}, JSON.stringify(data, null, 4)), + + ] + + if (res.stdout) { + body.push(E('b', {}, "STDOUT:")) + body.push(E('pre', {}, res.stdout)) + + } + + if (res.stderr) { + body.push(E('b', {}, "STDERR:")) + body.push(E('pre', {}, res.stderr)) + + } + + body = body.concat([ + E('div', { + 'class': 'right' + }, [ + E('div', { + 'class': 'btn', + 'click': ui.hideModal + }, _('Close')) + ]) + ]); + ui.showModal(_('Error building the sysupgrade'), body); + break; + } + }); } -function check_sysupgrade(server_url, current_version, target, board_name, packages) { - displayStatus("notice spinning", E('p', _('Searching for an available sysupgrade'))); - var current_branch = get_branch(current_version); - var advanced_mode = uci.get_first('attendedsysupgrade', 'client', 'advanced_mode') || 0; - var candidates = []; - - request.get(server_url + "/json/latest.json", { - timeout: 8000 - }) - .then(response => response.json()) - .then(response => { - if (current_version == "SNAPSHOT") { - candidates.push("SNAPSHOT"); - } else { - for (let version of response["latest"]) { - var branch = get_branch(version); - - // already latest version installed - if (current_version == version) { - break; - } - - // skip branch upgrades outside the advanced mode - if (current_branch != branch && advanced_mode == 0) { - continue; - } - - candidates.unshift(version); - - // don't offer branches older than the current - if (current_branch == branch) { - break; - } - } - } - if (candidates.length) { - var m, s, o; - - var mapdata = { - request: { - board_name: board_name, - target: target, - version: candidates[0], - packages: Object.keys(packages).sort(), - } - } - - m = new form.JSONMap(mapdata, ''); - - s = m.section(form.NamedSection, 'request', 'example', '', - 'Use defaults for the safest update'); - o = s.option(form.ListValue, 'version', 'Select firmware version'); - for (let candidate of candidates) { - o.value(candidate, candidate); - } - - if (advanced_mode == 1) { - o = s.option(form.Value, 'board_name', 'Board Name / Profile'); - o = s.option(form.DynamicList, 'packages', 'Packages'); - } - - - m.render() - .then(function(form_rendered) { - ui.showModal(_('New upgrade available'), [ - form_rendered, - E('div', { - 'class': 'right' - }, [ - E('div', { - 'class': 'btn', - 'click': ui.hideModal - }, _('Cancel')), - ' ', - E('div', { - 'class': 'btn cbi-button-action', - 'click': function() { - m.save().then(foo => { - request_sysupgrade( - server_url, mapdata.request - ) - }); - } - }, _('Request Sysupgrade')) - ]) - ]); - }); - } else { - ui.showModal(_('No upgrade available'), [ - E('p', {}, _("The device runs the latest firmware version")), - E('div', { - 'class': 'right' - }, [ - E('div', { - 'class': 'btn', - 'click': ui.hideModal - }, _('Close')) - ]) - ]); - } - }) - .catch(error => { - ui.showModal(_('Error connecting to upgrade server'), [ - E('p', {}, _('Could not reach API at "%s". Please try again later.'.format(server_url))), - E('pre', {}, error), - E('div', { - 'class': 'right' - }, [ - E('div', { - 'class': 'btn', - 'click': ui.hideModal - }, _('Close')) - ]) - ]); - }); +async function check_sysupgrade(server_url, system_board, packages) { + var { + board_name + } = system_board; + var { + target, + version, + revision + } = system_board.release; + var current_branch = get_branch(version); + var advanced_mode = uci.get_first('attendedsysupgrade', 'client', 'advanced_mode') || 0; + var candidates = []; + var response; + + displayStatus("notice spinning", E('p', _(`Searching for an available sysupgrade of ${version} - ${revision}`))); + + if (version.endsWith("SNAPSHOT")) { + response = await request.get(`${server_url}/api/v1/revision/${version}/${target}`) + if (!response.ok) { + error_api_connect(response); + return; + } + + const remote_revision = response.json().revision; + + if (get_revision_count(revision) < get_revision_count(remote_revision)) { + candidates.push(version); + } + } else { + response = await request.get(`${server_url}/api/overview`, { + timeout: 8000 + }); + + if (!response.ok) { + error_api_connect(response); + return; + } + + const latest = response.json().latest + + for (let remote_version of latest) { + var remote_branch = get_branch(remote_version); + + // already latest version installed + if (version == remote_version) { + break; + } + + // skip branch upgrades outside the advanced mode + if (current_branch != remote_branch && advanced_mode == 0) { + continue; + } + + candidates.unshift(remote_version); + + // don't offer branches older than the current + if (current_branch == remote_branch) { + break; + } + } + } + + if (candidates.length) { + var m, s, o; + + var mapdata = { + request: { + board_name: board_name, + target: target, + version: candidates[0], + packages: Object.keys(packages).sort(), + } + } + + m = new form.JSONMap(mapdata, ''); + + s = m.section(form.NamedSection, 'request', 'example', '', + 'Use defaults for the safest update'); + o = s.option(form.ListValue, 'version', 'Select firmware version'); + for (let candidate of candidates) { + o.value(candidate, candidate); + } + + if (advanced_mode == 1) { + o = s.option(form.Value, 'board_name', 'Board Name / Profile'); + o = s.option(form.DynamicList, 'packages', 'Packages'); + } + + + m.render() + .then(function(form_rendered) { + ui.showModal(_('New upgrade available'), [ + form_rendered, + E('div', { + 'class': 'right' + }, [ + E('div', { + 'class': 'btn', + 'click': ui.hideModal + }, _('Cancel')), + ' ', + E('div', { + 'class': 'btn cbi-button-action', + 'click': function() { + m.save().then(foo => { + request_sysupgrade( + server_url, mapdata.request + ) + }); + } + }, _('Request Sysupgrade')) + ]) + ]); + }); + } else { + ui.showModal(_('No upgrade available'), [ + E('p', {}, _(`The device runs the latest firmware version ${version} - ${revision}`)), + E('div', { + 'class': 'right' + }, [ + E('div', { + 'class': 'btn', + 'click': ui.hideModal + }, _('Close')) + ]) + ]); + } } function displayStatus(type, content) { - if (type) { - var message = ui.showModal('', ''); + if (type) { + var message = ui.showModal('', ''); - message.classList.add('alert-message'); - DOMTokenList.prototype.add.apply(message.classList, type.split(/\s+/)); + message.classList.add('alert-message'); + DOMTokenList.prototype.add.apply(message.classList, type.split(/\s+/)); - if (content) - dom.content(message, content); - } else { - ui.hideModal(); - } + if (content) + dom.content(message, content); + } else { + ui.hideModal(); + } } return view.extend({ - load: function() { - return Promise.all([ - L.resolveDefault(callPackagelist(), {}), - L.resolveDefault(callSystemBoard(), {}), - uci.load('attendedsysupgrade') - ]); - }, - render: function(res) { - var packages = res[0].packages; - var current_version = res[1].release.version; - var target = res[1].release.target; - var board_name = res[1].board_name; - var auto_search = uci.get_first('attendedsysupgrade', 'client', 'auto_search') || 1; - var server_url = uci.get_first('attendedsysupgrade', 'server', 'url'); - - var view = [ - E('h2', _("Attended Sysupgrade")), - E('p', _('The attended sysupgrade service allows to easily upgrade vanilla and custom firmware images.')), - E('p', _('This is done by building a new firmware on demand via an online service.')) - ]; - - if (auto_search == 1) { - check_sysupgrade(server_url, current_version, target, board_name, packages) - } - - view.push(E('p', { - 'class': 'btn cbi-button-positive', - 'click': function() { - check_sysupgrade(server_url, current_version, target, board_name, packages) - } - }, _('Search for sysupgrade'))); - - return view; - }, + load: function() { + return Promise.all([ + L.resolveDefault(callPackagelist(), {}), + L.resolveDefault(callSystemBoard(), {}), + uci.load('attendedsysupgrade') + ]); + }, + render: function(res) { + var packages = res[0].packages; + var system_board = res[1]; + var auto_search = uci.get_first('attendedsysupgrade', 'client', 'auto_search') || 1; + var server_url = uci.get_first('attendedsysupgrade', 'server', 'url'); + + var view = [ + E('h2', _("Attended Sysupgrade")), + E('p', _('The attended sysupgrade service allows to easily upgrade vanilla and custom firmware images.')), + E('p', _('This is done by building a new firmware on demand via an online service.')) + ]; + + if (auto_search == 1) { + check_sysupgrade(server_url, system_board, packages) + } + + view.push(E('p', { + 'class': 'btn cbi-button-positive', + 'click': function() { + check_sysupgrade(server_url, system_board, packages) + } + }, _('Search for sysupgrade'))); + + return view; + }, }); |