mirror of
https://github.com/unraid/webgui.git
synced 2026-01-07 01:59:52 -06:00
refactor: downgrade & update os web components
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
<?PHP
|
||||
<?php
|
||||
$docroot ??= ($_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp');
|
||||
$var = (array)parse_ini_file('state/var.ini');
|
||||
|
||||
|
||||
@@ -16,6 +16,15 @@
|
||||
margin-left: auto;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tools page, rotate the Downgrade icon to prevent needing to add a new icon to the icon font.
|
||||
* The pseudo element is targeted here otherwise the rotation of the span would mess up spacing with the text.
|
||||
*/
|
||||
a[href="/Tools/Downgrade"] .icon-update:before {
|
||||
display: inline-block; /* required otherwise the rotation won't work */
|
||||
rotate: 180deg;
|
||||
}
|
||||
</style>
|
||||
<?php
|
||||
// Set the path for the local manifest file
|
||||
|
||||
@@ -1,29 +1,7 @@
|
||||
<?PHP
|
||||
<?php
|
||||
$docroot ??= ($_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp');
|
||||
require_once("$docroot/plugins/dynamix.my.servers/include/state.php");
|
||||
require_once("$docroot/plugins/dynamix.my.servers/include/translations.php");
|
||||
|
||||
/**
|
||||
* Reboot detection was moved from Update.page to here as to seed the web components on every page rather than just on /Tools/Update
|
||||
*/
|
||||
$readme = @file_get_contents("$docroot/plugins/unRAIDServer/README.md", false, null, 0, 20) ?? ''; // read first 20 bytes of README.md
|
||||
$reboot = preg_match("/^\*\*(REBOOT REQUIRED|DOWNGRADE)/", $readme);
|
||||
|
||||
$rebootForDowngrade = $reboot && strpos($readme, 'DOWNGRADE') !== false;
|
||||
$rebootForUpgrade = $reboot && strpos($readme, 'REBOOT REQUIRED') !== false;
|
||||
|
||||
$rebootType = $rebootForDowngrade ? 'downgrade' : ($rebootForUpgrade ? 'upgrade' : '');
|
||||
|
||||
/**
|
||||
* Detect if third-party drivers were part of the upgrade process
|
||||
*/
|
||||
$processWaitingThirdParthDrivers = "inotifywait -q /boot/changes.txt -e move_self,delete_self";
|
||||
// Run the ps command to list processes and check if the process is running
|
||||
$ps_command = "ps aux | grep -E \"$processWaitingThirdParthDrivers\" | grep -v \"grep -E\"";
|
||||
$output = shell_exec($ps_command) ?? '';
|
||||
if (strpos($output, $processWaitingThirdParthDrivers) !== false) {
|
||||
$rebootType = 'thirdPartyDriversDownloading';
|
||||
}
|
||||
?>
|
||||
<script>
|
||||
window.LOCALE_DATA = '<?= rawurlencode(json_encode($webComponentTranslations, JSON_UNESCAPED_SLASHES, JSON_UNESCAPED_UNICODE)) ?>';
|
||||
@@ -43,7 +21,5 @@ if (!document.getElementsByTagName(modalsWebComponent).length) {
|
||||
<?
|
||||
echo "
|
||||
<unraid-i18n-host>
|
||||
<unraid-user-profile
|
||||
reboot-type='" . $rebootType . "'
|
||||
server='" . json_encode($serverState) . "'></unraid-user-profile>
|
||||
<unraid-user-profile server='" . json_encode($serverState) . "'></unraid-user-profile>
|
||||
</unraid-i18n-host>";
|
||||
|
||||
96
emhttp/plugins/dynamix.my.servers/include/reboot-details.php
Normal file
96
emhttp/plugins/dynamix.my.servers/include/reboot-details.php
Normal file
@@ -0,0 +1,96 @@
|
||||
<?php
|
||||
/**
|
||||
* RebootDetails class is responsible for detecting the type and version of a system reboot required in the context of an unRAID server.
|
||||
*
|
||||
* Usage:
|
||||
* ```
|
||||
* $rebootDetails = new RebootDetails();
|
||||
* $rebootType = $rebootDetails->getRebootType();
|
||||
* ```
|
||||
*/
|
||||
class RebootDetails
|
||||
{
|
||||
/**
|
||||
* @var string $rebootType Stores the type of reboot required, which can be 'update', 'downgrade', or 'thirdPartyDriversDownloading'.
|
||||
*/
|
||||
private $rebootType = '';
|
||||
|
||||
/**
|
||||
* Constructs a new RebootDetails object and automatically detects the reboot type during initialization.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->detectRebootType();
|
||||
}
|
||||
|
||||
/**
|
||||
* Detects the type of reboot required based on the contents of the unRAID server's README.md file.
|
||||
* Sets the $rebootType property accordingly.
|
||||
*/
|
||||
private function detectRebootType()
|
||||
{
|
||||
$docroot ??= ($_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp');
|
||||
|
||||
$rebootReadme = @file_get_contents("$docroot/plugins/unRAIDServer/README.md", false, null, 0, 20) ?: '';
|
||||
$rebootDetected = preg_match("/^\*\*(REBOOT REQUIRED|DOWNGRADE)/", $rebootReadme);
|
||||
|
||||
$rebootForDowngrade = $rebootDetected && strpos($rebootReadme, 'DOWNGRADE') !== false;
|
||||
$rebootForUpdate = $rebootDetected && strpos($rebootReadme, 'REBOOT REQUIRED') !== false;
|
||||
|
||||
$this->rebootType = $rebootForDowngrade ? 'downgrade' : ($rebootForUpdate ? 'update' : '');
|
||||
|
||||
// Detect if third-party drivers were part of the update process
|
||||
$processWaitingThirdParthDrivers = "inotifywait -q /boot/changes.txt -e move_self,delete_self";
|
||||
// Run the ps command to list processes and check if the process is running
|
||||
$ps_command = "ps aux | grep -E \"$processWaitingThirdParthDrivers\" | grep -v \"grep -E\"";
|
||||
$output = shell_exec($ps_command) ?? '';
|
||||
if (strpos($output, $processWaitingThirdParthDrivers) !== false) {
|
||||
$this->rebootType = 'thirdPartyDriversDownloading';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the type of reboot required, which can be 'update', 'downgrade', or 'thirdPartyDriversDownloading'.
|
||||
*
|
||||
* @return string The type of reboot required.
|
||||
*/
|
||||
public function getRebootType()
|
||||
{
|
||||
return $this->rebootType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Detects and retrieves the version information related to the system reboot based on the contents of the '/boot/changes.txt' file.
|
||||
*
|
||||
* @return string The system version information or 'Not found' if not found, or 'File not found' if the file is not present.
|
||||
*/
|
||||
public function getRebootVersion()
|
||||
{
|
||||
$file_path = '/boot/changes.txt';
|
||||
|
||||
// Check if the file exists
|
||||
if (file_exists($file_path)) {
|
||||
// Open the file for reading
|
||||
$file = fopen($file_path, 'r');
|
||||
|
||||
// Read the file line by line until we find a line that starts with '# Version'
|
||||
while (($line = fgets($file)) !== false) {
|
||||
if (strpos($line, '# Version') === 0) {
|
||||
// Use a regular expression to extract the full version string
|
||||
if (preg_match('/# Version\s+(\S+)/', $line, $matches)) {
|
||||
$fullVersion = $matches[1];
|
||||
return $fullVersion;
|
||||
} else {
|
||||
return 'Not found';
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Close the file
|
||||
fclose($file);
|
||||
} else {
|
||||
return 'File not found';
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,7 @@
|
||||
<?php
|
||||
$docroot ??= ($_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp');
|
||||
require_once "$docroot/plugins/dynamix.my.servers/include/reboot-details.php";
|
||||
|
||||
// read flashbackup ini file
|
||||
$flashbackup_ini = '/var/local/emhttp/flashbackup.ini';
|
||||
$flashbackup_status = (file_exists($flashbackup_ini)) ? @parse_ini_file($flashbackup_ini) : [];
|
||||
@@ -31,12 +34,21 @@ $configErrorEnum = [
|
||||
$osVersionBranch = trim(@exec('plugin category /var/log/plugins/unRAIDServer.plg') ?? 'stable');
|
||||
$registered = !empty($myservers['remote']['apikey']) && $connectPluginInstalled;
|
||||
|
||||
/**
|
||||
* Reboot detection
|
||||
*/
|
||||
// Create an instance of the RebootDetails class
|
||||
$rebootDetails = new RebootDetails();
|
||||
// Access the detected reboot type
|
||||
$rebootType = $rebootDetails->getRebootType();
|
||||
|
||||
$serverState = [
|
||||
"apiKey" => $myservers['upc']['apikey'] ?? '',
|
||||
"apiVersion" => $myservers['api']['version'] ?? '',
|
||||
"avatar" => (!empty($myservers['remote']['avatar']) && $connectPluginInstalled) ? $myservers['remote']['avatar'] : '',
|
||||
"config" => [
|
||||
'valid' => ($var['configValid'] === 'yes'),
|
||||
/** @todo remove error key value when config is valid */
|
||||
'error' => isset($configErrorEnum[$var['configValid']]) ? $configErrorEnum[$var['configValid']] : 'UNKNOWN_ERROR',
|
||||
],
|
||||
"connectPluginInstalled" => $connectPluginInstalled,
|
||||
@@ -65,6 +77,7 @@ $serverState = [
|
||||
"osVersion" => $var['version'],
|
||||
"osVersionBranch" => $osVersionBranch,
|
||||
"protocol" => $_SERVER['REQUEST_SCHEME'],
|
||||
"rebootType" => $rebootType,
|
||||
"regDev" => @(int)$var['regDev'] ?? 0,
|
||||
"regGen" => @(int)$var['regGen'],
|
||||
"regGuid" => @$var['regGUID'] ?? '',
|
||||
|
||||
@@ -155,7 +155,6 @@ $webComponentTranslations = [
|
||||
'<p>Your license key file is corrupted or missing. The key file should be located in the /config directory on your USB Flash boot device.</p><p>If you do not have a backup copy of your license key file you may attempt to recover your key.</p><p>If this was an expired Trial installation, you may purchase a license key.</p>' => '<p>' . _('Your license key file is corrupted or missing.') . ' ' . _('The key file should be located in the /config directory on your USB Flash boot device') . '</p><p>' . _('If you do not have a backup copy of your license key file you may attempt to recover your key with your Unraid.net account') . '</p><p>' . _('If this was an expired Trial installation, you may purchase a license key.') . '</p>',
|
||||
'Invalid installation' => _('Invalid installation'),
|
||||
'<p>It is not possible to use a Trial key with an existing Unraid OS installation.</p><p>You may purchase a license key corresponding to this USB Flash device to continue using this installation.</p>' => '<p>' . _('It is not possible to use a Trial key with an existing Unraid OS installation') . '</p><p>' . _('You may purchase a license key corresponding to this USB Flash device to continue using this installation.') . '</p>',
|
||||
|
||||
'No USB flash configuration data' => _('No USB flash configuration data'),
|
||||
'<p>There is a problem with your USB Flash device</p>' => '<p>' . _('There is a problem with your USB Flash device') . '</p>',
|
||||
'No Flash' => _('No Flash'),
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
span.thanks{padding-left:12px;color:#6FA239;font-weight:bold;}
|
||||
span.thanks.red{color:#F0000C;}
|
||||
div.device{padding:0 12px;font-weight:normal;font-style:italic;}
|
||||
div.remark{padding:0 12px;text-align:justify;}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,13 +1,13 @@
|
||||
{
|
||||
".nuxt/nuxt-custom-elements/entries/unraid-components.client.css": {
|
||||
"file": "_nuxt/unraid-components.client-896c373f.css",
|
||||
"file": "_nuxt/unraid-components.client-060d5fb6.css",
|
||||
"src": ".nuxt/nuxt-custom-elements/entries/unraid-components.client.css"
|
||||
},
|
||||
".nuxt/nuxt-custom-elements/entries/unraid-components.client.mjs": {
|
||||
"css": [
|
||||
"_nuxt/unraid-components.client-896c373f.css"
|
||||
"_nuxt/unraid-components.client-060d5fb6.css"
|
||||
],
|
||||
"file": "_nuxt/unraid-components.client-41af9187.js",
|
||||
"file": "_nuxt/unraid-components.client-f56a40ff.js",
|
||||
"isEntry": true,
|
||||
"src": ".nuxt/nuxt-custom-elements/entries/unraid-components.client.mjs"
|
||||
}
|
||||
|
||||
@@ -4,20 +4,24 @@ Icon="icon-update"
|
||||
Tag="upload"
|
||||
---
|
||||
<?php
|
||||
require_once "$docroot/plugins/dynamix.my.servers/include/reboot-details.php";
|
||||
// Create an instance of the RebootDetails class
|
||||
$rebootDetails = new RebootDetails();
|
||||
// Access the detected reboot type
|
||||
$rebootVersion = $rebootDetails->getRebootVersion();
|
||||
/**
|
||||
* @todo - need a downgrade icon
|
||||
* @note icon-update is rotated via CSS in myservers1.php
|
||||
*
|
||||
* If /boot/previous/bzroot exists, then the user has the option to downgrade to the previous version.
|
||||
* Parse the text file /boot/previous/changes.txt to get the version number of the previous version.
|
||||
* Then we move some files around and reboot.
|
||||
*/
|
||||
$check = $notify['unraidos'] ? 0 : 1;
|
||||
|
||||
$restoreVersion = $restoreBranch = $restoreVersionReleaseDate = 'unknown';
|
||||
$restoreExists = file_exists('/boot/previous/bzroot');
|
||||
$restoreChangelogPath = '/boot/previous/changes.txt';
|
||||
$restoreChangelogContent = file_get_contents($restoreChangelogPath);
|
||||
|
||||
$diagnosticsZip = htmlspecialchars(str_replace(' ', '_', strtolower($var['NAME'])));
|
||||
$serverNameEscaped = htmlspecialchars(str_replace(' ', '_', strtolower($var['NAME'])));
|
||||
|
||||
if (file_exists($restoreChangelogPath)) {
|
||||
exec("head -n4 $restoreChangelogPath", $rows);
|
||||
@@ -37,57 +41,29 @@ if (file_exists($restoreChangelogPath)) {
|
||||
?>
|
||||
|
||||
<script>
|
||||
var diagnosticsFile = "";
|
||||
var nchan_diagnostics = new NchanSubscriber('/sub/diagnostics', { subscriber: 'websocket' });
|
||||
const args = {};
|
||||
const nchan_diagnostics = new NchanSubscriber('/sub/diagnostics', { subscriber: 'websocket' });
|
||||
const reportUrl = new URL('https://forums.unraid.net/bug-reports/');
|
||||
let diagnosticsFile = '';
|
||||
|
||||
nchan_diagnostics.on('message', function(data) {
|
||||
if (data == '_DONE_') {
|
||||
nchan_diagnostics.stop();
|
||||
$('.sweet-alert').hide('fast').removeClass('nchan');
|
||||
swal.close();
|
||||
$('div.spinner').show('slow');
|
||||
location = diagnosticsFile;
|
||||
setTimeout(cleanUp,4000);
|
||||
|
||||
setTimeout(() => {
|
||||
cleanupDiagnostics();
|
||||
reportAfterDiagnosticsDownload();
|
||||
}, 2000);
|
||||
} else if (data) {
|
||||
let box = $('pre#swaltext');
|
||||
box.html(box.html() + '<br>' + data).scrollTop(box[0].scrollHeight);
|
||||
}
|
||||
});
|
||||
|
||||
function downgradeAction() {
|
||||
$.get('/plugins/dynamix.plugin.manager/include/Downgrade.php', { version: '<?=$restoreVersion?>' }, function() { refresh(); });
|
||||
}
|
||||
|
||||
function downgrade() {
|
||||
swal({
|
||||
title: "_(Diagnostics)_",
|
||||
text: "_(Please provide diagnostics when experiencing problems)_<br>_(Post these in the forums)_",
|
||||
html: true,
|
||||
type: 'warning',
|
||||
showCancelButton: true,
|
||||
confirmButtonText: "<?= _('Diagnostics') ?>",
|
||||
cancelButtonText: "<?= _('Restore') ?>",
|
||||
}, function(diag) {
|
||||
if (diag) {
|
||||
// get diagnostics and then downgrade
|
||||
setTimeout(function() {
|
||||
diagnostics(zipfile());
|
||||
}, 250);
|
||||
} else {
|
||||
// downgrade immediately
|
||||
downgradeAction();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function cleanUp() {
|
||||
if (document.hasFocus()) {
|
||||
$.post('/webGui/include/Download.php', { cmd: 'delete', file: diagnosticsFile }, downgradeAction());
|
||||
} else {
|
||||
setTimeout(cleanUp,2000);
|
||||
}
|
||||
}
|
||||
function zipfile() {
|
||||
function downloadDiagnostics() {
|
||||
const tzoffset = (new Date()).getTimezoneOffset() * 60000; // offset in milliseconds
|
||||
const localISOTime = (new Date(Date.now() - tzoffset));
|
||||
const year = localISOTime.getFullYear();
|
||||
@@ -96,12 +72,22 @@ function zipfile() {
|
||||
const hours = String(localISOTime.getHours()).padStart(2, '0');
|
||||
const minutes = String(localISOTime.getMinutes()).padStart(2, '0');
|
||||
const dateOutput = `${year}${month}${day}_${hours}${minutes}`;
|
||||
return '<?=$diagnosticsZip?>-diagnostics-' + dateOutput + '.zip';
|
||||
}
|
||||
function diagnostics(file) {
|
||||
const zipName = '<?=$serverNameEscaped?>-diagnostics-' + dateOutput + '.zip';
|
||||
|
||||
nchan_diagnostics.start();
|
||||
$.post('/webGui/include/Download.php', { cmd:'diag', file: file, anonymize: '' }, function(zip) {
|
||||
if (zip) {
|
||||
|
||||
$.post(
|
||||
'/webGui/include/Download.php',
|
||||
{
|
||||
cmd: 'diag',
|
||||
file: zipName,
|
||||
anonymize: '',
|
||||
},
|
||||
function(zip) {
|
||||
if (!zip) {
|
||||
return nchan_diagnostics.stop();
|
||||
}
|
||||
|
||||
diagnosticsFile = zip;
|
||||
swal({
|
||||
title: "_(Downloading)_...",
|
||||
@@ -112,15 +98,70 @@ function diagnostics(file) {
|
||||
});
|
||||
$('.sweet-alert').addClass('nchan');
|
||||
$('button.confirm').prop('disabled', true);
|
||||
} else {
|
||||
nchan_diagnostics.stop();
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
function reportAfterDiagnosticsDownload() {
|
||||
$('div.spinner').hide('fast');
|
||||
swal({
|
||||
title: "_(Open a bug report)_",
|
||||
text: "_(Create a bug report on our forums with a description of the issue along with your diagsnotics)_",
|
||||
html: true,
|
||||
type: 'warning',
|
||||
showCancelButton: true,
|
||||
confirmButtonText: "<?= _('Create Bug Report') ?>",
|
||||
cancelButtonText: "<?= _('Close') ?>",
|
||||
}, function(confirm) {
|
||||
if (!confirm) {
|
||||
return false;
|
||||
}
|
||||
window.open(reportUrl, '_blank');
|
||||
});
|
||||
}
|
||||
|
||||
function cleanupDiagnostics() {
|
||||
if (document.hasFocus()) {
|
||||
return $.post('/webGui/include/Download.php', { cmd: 'delete', file: diagnosticsFile });
|
||||
}
|
||||
setTimeout(cleanupDiagnostics, 2000);
|
||||
}
|
||||
|
||||
function startDowngrade() {
|
||||
$('div.spinner').show('slow');
|
||||
|
||||
$.get(
|
||||
'/plugins/dynamix.plugin.manager/include/Downgrade.php',
|
||||
{
|
||||
version: '<?=$restoreVersion?>',
|
||||
},
|
||||
function() {
|
||||
refresh();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function confirmDowngrade() {
|
||||
swal({
|
||||
title: "_(Confirm Downgrade)_",
|
||||
text: "<?= $restoreVersion ?><br>_(A reboot will be required)_",
|
||||
html: true,
|
||||
type: 'warning',
|
||||
showCancelButton: true,
|
||||
confirmButtonText: "<?= _('Confirm') ?>",
|
||||
cancelButtonText: "<?= _('Cancel') ?>",
|
||||
}, function(confirm) {
|
||||
if (!confirm) {
|
||||
return false;
|
||||
}
|
||||
startDowngrade();
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<unraid-i18n-host>
|
||||
<unraid-downgrade-os
|
||||
reboot-version="<?= $rebootVersion ?>"
|
||||
restore-version="<?= $restoreExists && $restoreVersion != 'unknown' ? $restoreVersion : '' ?>"
|
||||
restore-release-date="<?= $restoreExists && $restoreVersionReleaseDate != 'unknown' ? $restoreVersionReleaseDate : '' ?>"></unraid-downgrade-os>
|
||||
</unraid-i18n-host>
|
||||
</unraid-i18n-host>
|
||||
|
||||
@@ -3,6 +3,13 @@ Title="Update OS"
|
||||
Icon="icon-update"
|
||||
Tag="upload"
|
||||
---
|
||||
<?php
|
||||
require_once "$docroot/plugins/dynamix.my.servers/include/reboot-details.php";
|
||||
// Create an instance of the RebootDetails class
|
||||
$rebootDetails = new RebootDetails();
|
||||
// Access the detected reboot type
|
||||
$rebootVersion = $rebootDetails->getRebootVersion();
|
||||
?>
|
||||
<script>
|
||||
function cleanUpFlashBackup(zip) {
|
||||
if (document.hasFocus()) {
|
||||
@@ -33,5 +40,5 @@ function flashBackup() {
|
||||
</script>
|
||||
|
||||
<unraid-i18n-host>
|
||||
<unraid-update-os></unraid-update-os>
|
||||
<unraid-update-os reboot-version="<?= $rebootVersion ?>"></unraid-update-os>
|
||||
</unraid-i18n-host>
|
||||
Reference in New Issue
Block a user