mirror of
https://github.com/unraid/webgui.git
synced 2026-01-08 10:39:56 -06:00
Merge branch 'master' into master
This commit is contained in:
@@ -1203,7 +1203,7 @@ SSL certificate. Use this URL to access your server:
|
||||
Note that use of a self-signed SSL certificate will generate a browser
|
||||
warning.
|
||||
|
||||
Select **Strict** to enable *exclusive* use of an Unraid.net SSL
|
||||
Select **Strict** to enable *exclusive* use of a myunraid.net SSL
|
||||
certificate for https access (see **Provision** below). Note that a DNS
|
||||
server must be reachable.
|
||||
|
||||
@@ -1267,10 +1267,10 @@ To adjust URLs or redirects, see the help text for "Use SSL/TLS".
|
||||
:end
|
||||
|
||||
:mgmt_certificate_expiration_help:
|
||||
**Provision** may be used to install a *free* Unraid.net SSL Certificate from
|
||||
**Provision** may be used to install a *free* myunraid.net SSL Certificate from
|
||||
[Let's Encrypt](https://letsencrypt.org/).
|
||||
|
||||
The Unraid.net SSL certificate can be used in two ways. First,
|
||||
The myunraid.net SSL certificate can be used in two ways. First,
|
||||
having the certificate present enables your server to respond to an
|
||||
alternate URL of the form:
|
||||
|
||||
@@ -1284,24 +1284,20 @@ set to `*.<hash>.myunraid.net` thus validating the https connection.
|
||||
You may enable this URL exclusively on your LAN by setting **Use
|
||||
SSL/TLS** to **Strict**.
|
||||
|
||||
The second use for an Unraid.net certificate is to enable secure
|
||||
remote access available through the My Servers plugin feature. Note
|
||||
The second use for a myunraid.net certificate is to enable secure
|
||||
remote access available through the Unraid Connect plugin feature. Note
|
||||
that it is possible to use secure remote access in conjunction with
|
||||
insecure local access.
|
||||
|
||||
After an Unraid.net SSL Certificate has been installed, two
|
||||
background services are activated while the server is signed in to unraid.net:
|
||||
|
||||
- *updatedns* - This starts 30 seconds after server reboot has completed and contacts the Lime Technology
|
||||
DNS service to register the servers local IP address. Thereafter it wakes up every 10 minutes in case
|
||||
the local IP address has changed.
|
||||
After a myunraid.net SSL Certificate has been installed, a
|
||||
background service is activated:
|
||||
|
||||
- *renewcert* - This starts 60 seconds after server reboot has completed and contacts the Lime Technology
|
||||
certificate renewal service to determine if your Unraid.net SSL certificate needs to be renewed.
|
||||
certificate renewal service to determine if your myunraid.net SSL certificate needs to be renewed.
|
||||
Thereafter it wakes up every 24 hours. If within 30 days of expiration, a new certificate is automatically
|
||||
provisioned and downloaded to your server.
|
||||
|
||||
**Delete** may be used to delete the Unraid.net certificate file.
|
||||
**Delete** may be used to delete the myunraid.net certificate file.
|
||||
|
||||
**nginx certificate handling details**
|
||||
|
||||
@@ -1309,7 +1305,7 @@ nginx makes use of two certificate files stored on the USB flash boot device:<br
|
||||
|
||||
- a self-signed certificate: `config/ssl/certs/<server-name>_unraid_bundle.pem`
|
||||
|
||||
- an Unraid.net certificate: `config/ssl/certs/certificate_bundle.pem`
|
||||
- a myunraid.net certificate: `config/ssl/certs/certificate_bundle.pem`
|
||||
|
||||
The self-signed SSL certificate file is automatically created when nginx
|
||||
starts; and re-created if the server hostname or local TLD is changed.
|
||||
@@ -1493,7 +1489,7 @@ This will increase write performance but might possibly decrease read performanc
|
||||
Let the server act as a central syslog server and collect syslog messages from other systems.
|
||||
The server can listen on UDP, TCP or both with a selectable port number.
|
||||
|
||||
Syslog information is stored per IP address. That is every system gets its own syslog file.
|
||||
Syslog information is stored either per IP address or per hostname. That is every system gets its own syslog file.
|
||||
:end
|
||||
|
||||
:syslog_local_folder_help:
|
||||
@@ -1501,6 +1497,15 @@ Select the share folder where the syslogs will be stored.
|
||||
It is recommended that you use a share located on the cache drive to prevent array disk spinups.
|
||||
:end
|
||||
|
||||
:syslog_remote_system_identifier_help:
|
||||
Select the identifier for the remote system (used in the logfile name).
|
||||
|
||||
* "IP Address" uses the IP address (IPv4 or IPv6) of the sending system.
|
||||
* "Hostname (from syslog message)" uses the hostname included in each syslog message.
|
||||
* "Hostname (from DNS reverse lookup)" performs a DNS reverse lookup for the sending IP and uses the result.
|
||||
|
||||
:end
|
||||
|
||||
:syslog_local_rotation_help:
|
||||
By default LOG rotation is disabled and will create a single LOG file of unlimited size.
|
||||
|
||||
@@ -2493,7 +2498,7 @@ If set to 'Yes' the bash history will persist reboots, set to 'No' to disable.
|
||||
:WOL_intro_help:
|
||||
This page allows the setup to start/resume and stop VMs, Containters(Docker and LXC) using WOL magic packets
|
||||
|
||||
It does setup wake up of the Unraid server.
|
||||
It does not setup wake up of the Unraid server.
|
||||
|
||||
The process will look for the defined mac address defined within the service(VM or container) with the exception of dockers. Dockers do not have a mac address until they are running so you will need to define a user mac address to allow you to start them
|
||||
|
||||
@@ -2508,7 +2513,7 @@ When the enable and shutdown is set if the service is running when the next WOL
|
||||
If set to yes Unraidwold daemon is set to run.
|
||||
:end
|
||||
|
||||
:WOL_docker_help:
|
||||
:WOL_run_docker_help:
|
||||
If set to yes when wake on lan packets are received checks are carrried out for dockers otherwise dockers will be ignored.
|
||||
:end
|
||||
|
||||
|
||||
@@ -111,6 +111,7 @@ function LockButton() {
|
||||
}
|
||||
function loadlist(init) {
|
||||
timers.docker = setTimeout(function(){$('div.spinner.fixed').show('slow');},500);
|
||||
docker = [];
|
||||
$.get('/plugins/dynamix.docker.manager/include/DockerContainers.php',function(d) {
|
||||
clearTimeout(timers.docker);
|
||||
var data = d.split(/\0/);
|
||||
|
||||
@@ -748,6 +748,7 @@ _(Categories)_:
|
||||
: <input type="hidden" name="contCategory">
|
||||
<select id="catSelect" size="1" multiple="multiple" style="display:none" onchange="prepareCategory();">
|
||||
<optgroup label="_(Categories)_">
|
||||
<option value="AI:">_(AI)_</option>
|
||||
<option value="Backup:">_(Backup)_</option>
|
||||
<option value="Cloud:">_(Cloud)_</option>
|
||||
<option value="Crypto:">_(Crypto Currency)_</option>
|
||||
|
||||
@@ -176,7 +176,7 @@ class DockerTemplates {
|
||||
}
|
||||
// if after above we don't have a valid url, check for GitLab
|
||||
if (empty($github_api['url'])) {
|
||||
$source = file_get_contents($url);
|
||||
$source = $this->download_url($url);
|
||||
// the following should always exist for GitLab Community Edition or GitLab Enterprise Edition
|
||||
if (preg_match("/<meta content='GitLab (Community|Enterprise) Edition' name='description'>/", $source) > 0) {
|
||||
$parse = parse_url($url);
|
||||
@@ -721,7 +721,7 @@ class DockerClient {
|
||||
$fp = stream_socket_client('unix:///var/run/docker.sock', $errno, $errstr);
|
||||
if ($fp === false) {
|
||||
echo "Couldn't create socket: [$errno] $errstr";
|
||||
return null;
|
||||
return [];
|
||||
}
|
||||
$protocol = $unchunk ? 'HTTP/1.0' : 'HTTP/1.1';
|
||||
$out = "$method {$api}{$url} $protocol\r\nHost:127.0.0.1\r\nConnection:Close\r\n";
|
||||
@@ -915,6 +915,7 @@ class DockerClient {
|
||||
$c['Volumes'] = $info['HostConfig']['Binds'];
|
||||
$c['Created'] = $this->humanTiming($ct['Created']);
|
||||
$c['NetworkMode'] = $ct['HostConfig']['NetworkMode'];
|
||||
$c['Manager'] = $info['Config']['Labels']['net.unraid.docker.managed'] ?? false;
|
||||
[$net, $id] = array_pad(explode(':',$c['NetworkMode']),2,'');
|
||||
$c['CPUset'] = $info['HostConfig']['CpusetCpus'];
|
||||
$c['BaseImage'] = $ct['Labels']['BASEIMAGE'] ?? false;
|
||||
|
||||
@@ -120,20 +120,25 @@ foreach ($containers as $ct) {
|
||||
switch ($updateStatus) {
|
||||
case 0:
|
||||
echo "<span class='green-text' style='white-space:nowrap;'><i class='fa fa-check fa-fw'></i> "._('up-to-date')."</span>";
|
||||
echo "<div class='advanced'><a class='exec' onclick=\"updateContainer('".addslashes(htmlspecialchars($name))."');\"><span style='white-space:nowrap;'><i class='fa fa-cloud-download fa-fw'></i> "._('force update')."</span></a></div>";
|
||||
break;
|
||||
case 1:
|
||||
echo "<div class='advanced'><span class='orange-text' style='white-space:nowrap;'><i class='fa fa-flash fa-fw'></i> "._('update ready')."</span></div>";
|
||||
echo "<a class='exec' onclick=\"updateContainer('".addslashes(htmlspecialchars($name))."');\"><span style='white-space:nowrap;'><i class='fa fa-cloud-download fa-fw'></i> "._('apply update')."</span></a>";
|
||||
break;
|
||||
case 2:
|
||||
echo "<div class='advanced'><span class='orange-text' style='white-space:nowrap;'><i class='fa fa-flash fa-fw'></i> "._('rebuild ready')."</span></div>";
|
||||
echo "<a class='exec'><span style='white-space:nowrap;'><i class='fa fa-recycle fa-fw'></i> "._('rebuilding')."</span></a>";
|
||||
break;
|
||||
default:
|
||||
echo "<span class='orange-text' style='white-space:nowrap;'><i class='fa fa-unlink'></i> "._('not available')."</span>";
|
||||
echo "<div class='advanced'><a class='exec' onclick=\"updateContainer('".addslashes(htmlspecialchars($name))."');\"><span style='white-space:nowrap;'><i class='fa fa-cloud-download fa-fw'></i> "._('force update')."</span></a></div>";
|
||||
if ($ct['Manager'] == "dockerman")
|
||||
echo "<div class='advanced'><a class='exec' onclick=\"updateContainer('".addslashes(htmlspecialchars($name))."');\"><span style='white-space:nowrap;'><i class='fa fa-cloud-download fa-fw'></i> "._('force update')."</span></a></div>";
|
||||
break;
|
||||
case 1:
|
||||
echo "<div class='advanced'><span class='orange-text' style='white-space:nowrap;'><i class='fa fa-flash fa-fw'></i> "._('update ready')."</span></div>";
|
||||
if ($ct['Manager'] == "dockerman")
|
||||
echo "<a class='exec' onclick=\"updateContainer('".addslashes(htmlspecialchars($name))."');\"><span style='white-space:nowrap;'><i class='fa fa-cloud-download fa-fw'></i> "._('apply update')."</span></a>";
|
||||
else
|
||||
echo "<span style='white-space:nowrap;'><i class='fa fa-cloud-download fa-fw'></i> "._('update available')."</span>";
|
||||
break;
|
||||
case 2:
|
||||
echo "<div class='advanced'><span class='orange-text' style='white-space:nowrap;'><i class='fa fa-flash fa-fw'></i> "._('rebuild ready')."</span></div>";
|
||||
echo "<a class='exec'><span style='white-space:nowrap;'><i class='fa fa-recycle fa-fw'></i> "._('rebuilding')."</span></a>";
|
||||
break;
|
||||
default:
|
||||
echo "<span class='orange-text' style='white-space:nowrap;'><i class='fa fa-unlink'></i> "._('not available')."</span>";
|
||||
if ($ct['Manager'] == "dockerman")
|
||||
echo "<div class='advanced'><a class='exec' onclick=\"updateContainer('".addslashes(htmlspecialchars($name))."');\"><span style='white-space:nowrap;'><i class='fa fa-cloud-download fa-fw'></i> "._('force update')."</span></a></div>";
|
||||
break;
|
||||
}
|
||||
echo "<div class='advanced'><i class='fa fa-info-circle fa-fw'></i> ".compress(_($version),12,0)."</div></td>";
|
||||
echo "<td>{$ct['NetworkMode']}</td>";
|
||||
|
||||
@@ -14,8 +14,9 @@
|
||||
<?
|
||||
$docroot ??= ($_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp');
|
||||
require_once "$docroot/plugins/dynamix.docker.manager/include/DockerClient.php";
|
||||
require_once "$docroot/webGui/include/Wrappers.php";
|
||||
|
||||
$ncsi = exec("wget --spider --no-check-certificate -nv -T10 -t1 https://www.msftncsi.com/ncsi.txt 2>&1|grep -o 'OK'")=='OK';
|
||||
$ncsi = check_network_connectivity();
|
||||
$DockerTemplates = new DockerTemplates();
|
||||
if ($ncsi) $DockerTemplates->downloadTemplates();
|
||||
$DockerTemplates->getAllInfo($ncsi,$ncsi);
|
||||
|
||||
@@ -270,6 +270,8 @@ function xmlToCommand($xml, $create_paths=false) {
|
||||
$Mode = strval($config['Mode']);
|
||||
if ($confType != "device" && !strlen($containerConfig)) continue;
|
||||
if ($confType == "path") {
|
||||
if ( ! trim($hostConfig) || ! trim($containerConfig) )
|
||||
continue;
|
||||
$Volumes[] = escapeshellarg($hostConfig).':'.escapeshellarg($containerConfig).':'.escapeshellarg($Mode);
|
||||
if (!file_exists($hostConfig) && $create_paths) {
|
||||
@mkdir($hostConfig, 0777, true);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/php -q
|
||||
<?PHP
|
||||
/* Copyright 2005-2023, Lime Technology
|
||||
* Copyright 2012-2023, Bergware International.
|
||||
/* Copyright 2005-2024, Lime Technology
|
||||
* Copyright 2012-2024, Bergware International.
|
||||
* Copyright 2014-2021, Guilherme Jardim, Eric Schultz, Jon Panozzo.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
@@ -16,6 +16,7 @@
|
||||
$docroot ??= ($_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp');
|
||||
require_once "$docroot/webGui/include/Wrappers.php";
|
||||
require_once "$docroot/plugins/dynamix.docker.manager/include/DockerClient.php";
|
||||
// this command will set the $notify array
|
||||
extract(parse_plugin_cfg('dynamix', true));
|
||||
|
||||
// Multi-language support
|
||||
@@ -43,7 +44,7 @@ if (!isset($check)) {
|
||||
$DockerTemplates->getAllInfo(true);
|
||||
echo " Done.";
|
||||
} else {
|
||||
$notify = "$docroot/webGui/scripts/notify";
|
||||
$script = "$docroot/webGui/scripts/notify";
|
||||
$var = (array)@parse_ini_file("/var/local/emhttp/var.ini");
|
||||
$server = strtoupper(_var($var,'NAME','tower'));
|
||||
$output = _var($notify,'docker_notify');
|
||||
@@ -59,7 +60,7 @@ if (!isset($check)) {
|
||||
$event = str_replace("'","'",_("Docker")." - $name [$new]");
|
||||
$subject = str_replace("'","'",sprintf(_("Notice [%s] - Version update %s"),$server,$new));
|
||||
$description = str_replace("'","'",sprintf(_("A new version of %s is available"),$name));
|
||||
exec("$notify -e ".escapeshellarg($event)." -s ".escapeshellarg($subject)." -d ".escapeshellarg($description)." -i ".escapeshellarg("normal $output")." -l '/Docker' -x");
|
||||
exec("$script -e ".escapeshellarg($event)." -s ".escapeshellarg($subject)." -d ".escapeshellarg($description)." -i ".escapeshellarg("normal $output")." -l '/Docker' -x");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,8 +30,7 @@ if (!document.getElementsByTagName(modalsWebComponent).length) {
|
||||
$i18nHost.appendChild($modals);
|
||||
}
|
||||
</script>
|
||||
<?
|
||||
echo "
|
||||
|
||||
<unraid-i18n-host>
|
||||
<unraid-user-profile server='" . $serverState->getServerStateJson() . "'></unraid-user-profile>
|
||||
</unraid-i18n-host>";
|
||||
<unraid-user-profile server="<?= $serverState->getServerStateJsonForHtmlAttr() ?>"></unraid-user-profile>
|
||||
</unraid-i18n-host>
|
||||
|
||||
@@ -34,11 +34,20 @@ class ServerState
|
||||
protected $webguiGlobals;
|
||||
|
||||
private $var;
|
||||
private $flashbackupCfg;
|
||||
private $apiKey = '';
|
||||
private $apiVersion = '';
|
||||
private $avatar = '';
|
||||
private $email = '';
|
||||
private $extraOrigins = [];
|
||||
private $flashBackupActivated = '';
|
||||
private $hasRemoteApikey = false;
|
||||
private $registeredTime = '';
|
||||
private $username = '';
|
||||
private $connectPluginInstalled = '';
|
||||
private $connectPluginVersion;
|
||||
private $configErrorEnum = [
|
||||
"error" => 'UNKNOWN_ERROR',
|
||||
"ineligible" => 'INELIGIBLE',
|
||||
"invalid" => 'INVALID',
|
||||
"nokeyserver" => 'NO_KEY_SERVER',
|
||||
"withdrawn" => 'WITHDRAWN',
|
||||
@@ -58,9 +67,9 @@ class ServerState
|
||||
public $host = 'unknown';
|
||||
public $combinedKnownOrigins = [];
|
||||
|
||||
public $nginxCfg;
|
||||
public $flashbackupStatus;
|
||||
public $registered;
|
||||
public $nginxCfg = [];
|
||||
public $flashbackupStatus = [];
|
||||
public $registered = false;
|
||||
public $myServersMiniGraphConnected = false;
|
||||
public $keyfileBase64 = '';
|
||||
|
||||
@@ -78,11 +87,42 @@ class ServerState
|
||||
// echo "<pre>" . json_encode($this->webguiGlobals, JSON_PRETTY_PRINT) . "</pre>";
|
||||
|
||||
$this->var = (array)parse_ini_file('state/var.ini');
|
||||
$this->nginxCfg = parse_ini_file('/var/local/emhttp/nginx.ini');
|
||||
$this->nginxCfg = @parse_ini_file('/var/local/emhttp/nginx.ini') ?? [];
|
||||
|
||||
$this->flashbackupCfg = '/var/local/emhttp/flashbackup.ini';
|
||||
$this->flashbackupStatus = (file_exists($this->flashbackupCfg)) ? @parse_ini_file($this->flashbackupCfg) : [];
|
||||
$this->osVersion = $this->var['version'];
|
||||
$this->osVersionBranch = trim(@exec('plugin category /var/log/plugins/unRAIDServer.plg') ?? 'stable');
|
||||
|
||||
$caseModelFile = '/boot/config/plugins/dynamix/case-model.cfg';
|
||||
$this->caseModel = file_exists($caseModelFile) ? file_get_contents($caseModelFile) : '';
|
||||
|
||||
$this->rebootDetails = new RebootDetails();
|
||||
|
||||
$this->keyfileBase64 = empty($this->var['regFILE']) ? null : @file_get_contents($this->var['regFILE']);
|
||||
if ($this->keyfileBase64 !== false) {
|
||||
$this->keyfileBase64 = @base64_encode($this->keyfileBase64);
|
||||
$this->keyfileBase64UrlSafe = str_replace(['+', '/', '='], ['-', '_', ''], trim($this->keyfileBase64));
|
||||
}
|
||||
|
||||
$this->updateOsCheck = new UnraidOsCheck();
|
||||
$this->updateOsIgnoredReleases = $this->updateOsCheck->getIgnoredReleases();
|
||||
$this->updateOsNotificationsEnabled = !empty(@$this->getWebguiGlobal('notify', 'unraidos'));
|
||||
$this->updateOsResponse = $this->updateOsCheck->getUnraidOSCheckResult();
|
||||
|
||||
$this->setConnectValues();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the value of a webgui global setting.
|
||||
*/
|
||||
public function getWebguiGlobal(string $key, string $subkey = null) {
|
||||
if (!$subkey) {
|
||||
return _var($this->webguiGlobals, $key, '');
|
||||
}
|
||||
$keyArray = _var($this->webguiGlobals, $key, []);
|
||||
return _var($keyArray, $subkey, '');
|
||||
}
|
||||
|
||||
private function setConnectValues() {
|
||||
if (file_exists('/var/lib/pkgtools/packages/dynamix.unraid.net')) {
|
||||
$this->connectPluginInstalled = 'dynamix.unraid.net.plg';
|
||||
}
|
||||
@@ -93,11 +133,29 @@ class ServerState
|
||||
$this->connectPluginInstalled .= '_installFailed';
|
||||
}
|
||||
|
||||
// exit early if the plugin is not installed
|
||||
if (!$this->connectPluginInstalled) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->connectPluginVersion = file_exists('/var/log/plugins/dynamix.unraid.net.plg')
|
||||
? trim(@exec('/usr/local/sbin/plugin version /var/log/plugins/dynamix.unraid.net.plg 2>/dev/null'))
|
||||
: (file_exists('/var/log/plugins/dynamix.unraid.net.staging.plg')
|
||||
? trim(@exec('/usr/local/sbin/plugin version /var/log/plugins/dynamix.unraid.net.staging.plg 2>/dev/null'))
|
||||
: 'base-' . $this->var['version']);
|
||||
|
||||
$this->getMyServersCfgValues();
|
||||
$this->getConnectKnownOrigins();
|
||||
$this->getFlashBackupStatus();
|
||||
}
|
||||
|
||||
private function getFlashBackupStatus() {
|
||||
$flashbackupCfg = '/var/local/emhttp/flashbackup.ini';
|
||||
$this->flashbackupStatus = (file_exists($flashbackupCfg)) ? @parse_ini_file($flashbackupCfg) : [];
|
||||
$this->flashBackupActivated = empty($this->flashbackupStatus['activated']) ? '' : 'true';
|
||||
}
|
||||
|
||||
private function getMyServersCfgValues() {
|
||||
/**
|
||||
* @todo can we read this from somewhere other than the flash? Connect page uses this path and /boot/config/plugins/dynamix.my.servers/myservers.cfg…
|
||||
* - $myservers_memory_cfg_path ='/var/local/emhttp/myservers.cfg';
|
||||
@@ -122,15 +180,17 @@ class ServerState
|
||||
$this->myServersFlashCfg['remote']['dynamicRemoteAccessType'] = "DISABLED";
|
||||
}
|
||||
|
||||
$this->osVersion = $this->var['version'];
|
||||
$this->osVersionBranch = trim(@exec('plugin category /var/log/plugins/unRAIDServer.plg') ?? 'stable');
|
||||
$this->apiKey = $this->myServersFlashCfg['upc']['apikey'] ?? '';
|
||||
$this->apiVersion = $this->myServersFlashCfg['api']['version'] ?? '';
|
||||
$this->avatar = (!empty($this->myServersFlashCfg['remote']['avatar']) && $this->connectPluginInstalled) ? $this->myServersFlashCfg['remote']['avatar'] : '';
|
||||
$this->email = $this->myServersFlashCfg['remote']['email'] ?? '';
|
||||
$this->hasRemoteApikey = !empty($this->myServersFlashCfg['remote']['apikey']);
|
||||
$this->registered = !empty($this->myServersFlashCfg['remote']['apikey']) && $this->connectPluginInstalled;
|
||||
$this->registeredTime = $this->myServersFlashCfg['remote']['regWizTime'] ?? '';
|
||||
$this->username = $this->myServersFlashCfg['remote']['username'] ?? '';
|
||||
}
|
||||
|
||||
$caseModelFile = '/boot/config/plugins/dynamix/case-model.cfg';
|
||||
$this->caseModel = file_exists($caseModelFile) ? file_get_contents($caseModelFile) : '';
|
||||
|
||||
$this->rebootDetails = new RebootDetails();
|
||||
|
||||
private function getConnectKnownOrigins() {
|
||||
/**
|
||||
* Allowed origins warning displayed when the current webGUI URL is NOT included in the known lists of allowed origins.
|
||||
* Include localhost in the test, but only display HTTP(S) URLs that do not include localhost.
|
||||
@@ -145,6 +205,11 @@ class ServerState
|
||||
$combinedOrigins = $allowedOrigins . "," . $extraOrigins; // combine the two strings for easier searching
|
||||
$combinedOrigins = str_replace(" ", "", $combinedOrigins); // replace any spaces with nothing
|
||||
$hostNotKnown = stripos($combinedOrigins, $this->host) === false; // check if the current host is in the combined list of origins
|
||||
|
||||
if ($extraOrigins) {
|
||||
$this->extraOrigins = explode(",", $extraOrigins);
|
||||
}
|
||||
|
||||
if ($hostNotKnown) {
|
||||
$this->combinedKnownOrigins = explode(",", $combinedOrigins);
|
||||
|
||||
@@ -161,29 +226,8 @@ class ServerState
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->keyfileBase64 = empty($this->var['regFILE']) ? null : @file_get_contents($this->var['regFILE']);
|
||||
if ($this->keyfileBase64 !== false) {
|
||||
$this->keyfileBase64 = @base64_encode($this->keyfileBase64);
|
||||
$this->keyfileBase64UrlSafe = str_replace(['+', '/', '='], ['-', '_', ''], trim($this->keyfileBase64));
|
||||
}
|
||||
|
||||
$this->updateOsCheck = new UnraidOsCheck();
|
||||
$this->updateOsIgnoredReleases = $this->updateOsCheck->getIgnoredReleases();
|
||||
$this->updateOsNotificationsEnabled = !empty(@$this->getWebguiGlobal('notify', 'unraidos'));
|
||||
$this->updateOsResponse = $this->updateOsCheck->getUnraidOSCheckResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the value of a webgui global setting.
|
||||
*/
|
||||
public function getWebguiGlobal(string $key, string $subkey = null) {
|
||||
if (!$subkey) {
|
||||
return _var($this->webguiGlobals, $key, '');
|
||||
}
|
||||
$keyArray = _var($this->webguiGlobals, $key, []);
|
||||
return _var($keyArray, $subkey, '');
|
||||
}
|
||||
/**
|
||||
* Retrieve the server information as an associative array
|
||||
*
|
||||
@@ -192,13 +236,13 @@ class ServerState
|
||||
public function getServerState()
|
||||
{
|
||||
$serverState = [
|
||||
"apiKey" => $this->myServersFlashCfg['upc']['apikey'] ?? '',
|
||||
"apiVersion" => $this->myServersFlashCfg['api']['version'] ?? '',
|
||||
"avatar" => (!empty($this->myServersFlashCfg['remote']['avatar']) && $this->connectPluginInstalled) ? $this->myServersFlashCfg['remote']['avatar'] : '',
|
||||
"apiKey" => $this->apiKey,
|
||||
"apiVersion" => $this->apiVersion,
|
||||
"avatar" => $this->avatar,
|
||||
"caseModel" => $this->caseModel,
|
||||
"config" => [
|
||||
'valid' => ($this->var['configValid'] === 'yes'),
|
||||
'error' => isset($this->configErrorEnum[$this->var['configValid']]) ? $this->configErrorEnum[$this->var['configValid']] : 'UNKNOWN_ERROR',
|
||||
'error' => isset($this->configErrorEnum[$this->var['configValid']]) ? $this->configErrorEnum[$this->var['configValid']] : null,
|
||||
],
|
||||
"connectPluginInstalled" => $this->connectPluginInstalled,
|
||||
"connectPluginVersion" => $this->connectPluginVersion,
|
||||
@@ -207,35 +251,35 @@ class ServerState
|
||||
"date" => @$this->getWebguiGlobal('display', 'date') ?? '',
|
||||
"time" => @$this->getWebguiGlobal('display', 'time') ?? '',
|
||||
],
|
||||
"description" => $this->var['COMMENT'] ? htmlspecialchars($this->var['COMMENT']) : '',
|
||||
"description" => $this->var['COMMENT'] ? htmlspecialchars($this->var['COMMENT'], ENT_HTML5, 'UTF-8') : '',
|
||||
"deviceCount" => $this->var['deviceCount'],
|
||||
"email" => $this->myServersFlashCfg['remote']['email'] ?? '',
|
||||
"email" => $this->email,
|
||||
"expireTime" => 1000 * (($this->var['regTy'] === 'Trial' || strstr($this->var['regTy'], 'expired')) ? $this->var['regTm2'] : 0),
|
||||
"extraOrigins" => explode(',', $this->myServersFlashCfg['api']['extraOrigins'] ?? ''),
|
||||
"extraOrigins" => $this->extraOrigins,
|
||||
"flashProduct" => $this->var['flashProduct'],
|
||||
"flashVendor" => $this->var['flashVendor'],
|
||||
"flashBackupActivated" => empty($this->flashbackupStatus['activated']) ? '' : 'true',
|
||||
"flashBackupActivated" => $this->flashBackupActivated,
|
||||
"guid" => $this->var['flashGUID'],
|
||||
"hasRemoteApikey" => !empty($this->myServersFlashCfg['remote']['apikey']),
|
||||
"hasRemoteApikey" => $this->hasRemoteApikey,
|
||||
"internalPort" => _var($_SERVER, 'SERVER_PORT'),
|
||||
"keyfile" => $this->keyfileBase64UrlSafe,
|
||||
"lanIp" => ipaddr(),
|
||||
"locale" => (!empty($_SESSION) && $_SESSION['locale']) ? $_SESSION['locale'] : 'en_US',
|
||||
"model" => $this->var['SYS_MODEL'],
|
||||
"name" => htmlspecialchars($this->var['NAME']),
|
||||
"model" => $this->var['SYS_MODEL'] ? htmlspecialchars($this->var['SYS_MODEL'], ENT_HTML5, 'UTF-8') : '',
|
||||
"name" => htmlspecialchars($this->var['NAME'], ENT_HTML5, 'UTF-8'),
|
||||
"osVersion" => $this->osVersion,
|
||||
"osVersionBranch" => $this->osVersionBranch,
|
||||
"protocol" => _var($_SERVER, 'REQUEST_SCHEME'),
|
||||
"rebootType" => $this->rebootDetails->getRebootType(),
|
||||
"regDev" => @(int)$this->var['regDev'] ?? 0,
|
||||
"regDevs" => @(int)$this->var['regDevs'] ?? 0,
|
||||
"regGen" => @(int)$this->var['regGen'],
|
||||
"regGuid" => @$this->var['regGUID'] ?? '',
|
||||
"regTo" => @htmlspecialchars($this->var['regTo']) ?? '',
|
||||
"regTo" => @htmlspecialchars($this->var['regTo'], ENT_HTML5, 'UTF-8') ?? '',
|
||||
"regTm" => $this->var['regTm'] ? @$this->var['regTm'] * 1000 : '', // JS expects milliseconds
|
||||
"regTy" => @$this->var['regTy'] ?? '',
|
||||
"regExp" => $this->var['regExp'] ? @$this->var['regExp'] * 1000 : '', // JS expects milliseconds
|
||||
"registered" => $this->registered,
|
||||
"registeredTime" => $this->myServersFlashCfg['remote']['regWizTime'] ?? '',
|
||||
"registeredTime" => $this->registeredTime,
|
||||
"site" => _var($_SERVER, 'REQUEST_SCHEME') . "://" . _var($_SERVER, 'HTTP_HOST'),
|
||||
"state" => strtoupper(empty($this->var['regCheck']) ? $this->var['regTy'] : $this->var['regCheck']),
|
||||
"theme" => [
|
||||
@@ -249,8 +293,8 @@ class ServerState
|
||||
],
|
||||
"ts" => time(),
|
||||
"uptime" => 1000 * (time() - round(strtok(exec("cat /proc/uptime"), ' '))),
|
||||
"username" => $this->myServersFlashCfg['remote']['username'] ?? '',
|
||||
"wanFQDN" => $this->nginxCfg['NGINX_WANFQDN'] ?? '',
|
||||
"username" => $this->username,
|
||||
"wanFQDN" => @$this->nginxCfg['NGINX_WANFQDN'] ?? '',
|
||||
];
|
||||
|
||||
if ($this->combinedKnownOrigins) {
|
||||
@@ -273,11 +317,21 @@ class ServerState
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the server information as a JSON string
|
||||
* Retrieve the server information as JSON
|
||||
*
|
||||
* @return string A JSON string containing server information.
|
||||
* @return string
|
||||
*/
|
||||
public function getServerStateJson() {
|
||||
return json_encode($this->getServerState());
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the server information as JSON string with converted special characters to HTML entities
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getServerStateJsonForHtmlAttr() {
|
||||
$json = json_encode($this->getServerState());
|
||||
return htmlspecialchars($json, ENT_QUOTES, 'UTF-8');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,13 +72,13 @@ class WebComponentTranslations
|
||||
'<p>To continue using Unraid OS you may purchase a license key. Alternately, you may request a Trial extension.</p>' => '<p>' . _('To continue using Unraid OS you may purchase a license key.') . ' ' . _('Alternately, you may request a Trial extension.') . '</p>',
|
||||
'<p>To support more storage devices as your server grows, click Upgrade Key.</p>' => '<p>' . _('To support more storage devices as your server grows, click Upgrade Key.') . '</p>',
|
||||
'<p>You have used all your Trial extensions. To continue using Unraid OS you may purchase a license key.</p>' => '<p>' . _('You have used all your Trial extensions.') . ' ' . _('To continue using Unraid OS you may purchase a license key.') . '</p>',
|
||||
'<p>Your <em>Trial</em> key includes all the functionality and device support of a <em>Pro</em> key.</p><p>After your <em>Trial</em> has reached expiration, your server <strong>still functions normally</strong> until the next time you Stop the array or reboot your server.</p><p>At that point you may either purchase a license key or request a <em>Trial</em> extension.</p>' => '<p>' . _('Your **Trial** key includes all the functionality and device support of a **Pro** key') . '</p><p>' . _('After your **Trial** has reached expiration, your server *still functions normally* until the next time you Stop the array or reboot your server') . '</p><p>' . _('At that point you may either purchase a license key or request a *Trial* extension.') . '</p>',
|
||||
'<p>Your <em>Trial</em> key includes all the functionality and device support of an <em>Unleashed</em> key.</p><p>After your <em>Trial</em> has reached expiration, your server <strong>still functions normally</strong> until the next time you Stop the array or reboot your server.</p><p>At that point you may either purchase a license key or request a <em>Trial</em> extension.</p>' => '<p>' . _('Your **Trial** key includes all the functionality and device support of an **Unleashed** key') . '</p><p>' . _('After your **Trial** has reached expiration, your server *still functions normally* until the next time you Stop the array or reboot your server') . '</p><p>' . _('At that point you may either purchase a license key or request a *Trial* extension.') . '</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.</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>',
|
||||
'<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>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>' => '<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>',
|
||||
'<p>Your server will not be usable until you purchase a Registration key or install a free 30 day <em>Trial</em> key. A <em>Trial</em> key provides all the functionality of a Pro Registration key.</p><p>Registration keys are bound to your USB Flash boot device serial number (GUID). Please use a high quality name brand device at least 1GB in size.</p><p>Note: USB memory card readers are generally not supported because most do not present unique serial numbers.</p><p><strong>Important:</strong></p><ul class="list-disc pl-16px"><li>Please make sure your server time is accurate to within 5 minutes</li><li>Please make sure there is a DNS server specified</li></ul>' => '<p>' . _('Your server will not be usable until you purchase a Registration key or install a free 30 day <em>Trial</em> key.') . ' ' . _('A <em>Trial</em> key provides all the functionality of a Pro Registration key.') . '</p><p>' . _('Registration keys are bound to your USB Flash boot device serial number (GUID).') . ' ' . _('Please use a high quality name brand device at least 1GB in size.') . '</p><p>' . _('Note: USB memory card readers are generally not supported because most do not present unique serial numbers.') . '</p><p>' . _('*Important:*') . '</p><ul class="list-disc pl-16px"><li>' . _('Please make sure your server time is accurate to within 5 minutes') . '</li><li>' . _('Please make sure there is a DNS server specified') . '</li>>' . '</ul>',
|
||||
'<p>Your server will not be usable until you purchase a Registration key or install a free 30 day <em>Trial</em> key. A <em>Trial</em> key provides all the functionality of an Unleashed Registration key.</p><p>Registration keys are bound to your USB Flash boot device serial number (GUID). Please use a high quality name brand device at least 1GB in size.</p><p>Note: USB memory card readers are generally not supported because most do not present unique serial numbers.</p><p><strong>Important:</strong></p><ul class="list-disc pl-16px"><li>Please make sure your server time is accurate to within 5 minutes</li><li>Please make sure there is a DNS server specified</li></ul>' => '<p>' . _('Your server will not be usable until you purchase a Registration key or install a free 30 day <em>Trial</em> key.') . ' ' . _('A <em>Trial</em> key provides all the functionality of an Unleashed Registration key.') . '</p><p>' . _('Registration keys are bound to your USB Flash boot device serial number (GUID).') . ' ' . _('Please use a high quality name brand device at least 1GB in size.') . '</p><p>' . _('Note: USB memory card readers are generally not supported because most do not present unique serial numbers.') . '</p><p>' . _('*Important:*') . '</p><ul class="list-disc pl-16px"><li>' . _('Please make sure your server time is accurate to within 5 minutes') . '</li><li>' . _('Please make sure there is a DNS server specified') . '</li>>' . '</ul>',
|
||||
'<p>Your Trial key requires an internet connection.</p><p><a href="/Settings/NetworkSettings" class="underline">Please check Settings > Network</a></p>' => '<p>' . _('Your Trial key requires an internet connection') . '</p><p><a href="/Settings/NetworkSettings" class="underline">' . _('Please check Settings > Network') . '</a></p>',
|
||||
'<p>Your Unraid registration key is ineligible for replacement as it has been replaced within the last 12 months.</p>' => '<p>' . _('Your Unraid registration key is ineligible for replacement as it has been replaced within the last 12 months.') . '</p>',
|
||||
'A Trial key provides all the functionality of a Pro Registration key' => _('A Trial key provides all the functionality of a Pro Registration key'),
|
||||
'A Trial key provides all the functionality of an Unleashed Registration key' => _('A Trial key provides all the functionality of an Unleashed Registration key'),
|
||||
'Acklowledge that you have made a Flash Backup to enable this action' => _('Acklowledge that you have made a Flash Backup to enable this action'),
|
||||
'ago' => _('ago'),
|
||||
'All you need is an active internet connection, an Unraid.net account, and the Connect plugin. Get started by installing the plugin.' => _('All you need is an active internet connection, an Unraid.net account, and the Connect plugin.') . ' ' . _('Get started by installing the plugin.'),
|
||||
@@ -339,7 +339,7 @@ class WebComponentTranslations
|
||||
'You may still update to releases dated prior to your update expiration date.' => _('You may still update to releases dated prior to your update expiration date.'),
|
||||
'You\'re one step closer to enhancing your Unraid experience' => _('You\'re one step closer to enhancing your Unraid experience'),
|
||||
'Your {0} Key has been replaced!' => sprintf(_('Your %s Key has been replaced!'), '{0}'),
|
||||
'Your free Trial key provides all the functionality of a Pro Registration key' => _('Your free Trial key provides all the functionality of a Pro Registration key'),
|
||||
'Your free Trial key provides all the functionality of an Unleashed Registration key' => _('Your free Trial key provides all the functionality of an Unleashed Registration key'),
|
||||
'Your Trial has expired' => _('Your Trial has expired'),
|
||||
'Your Trial key has been extended!' => _('Your Trial key has been extended!'),
|
||||
];
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -7,7 +7,7 @@
|
||||
"css": [
|
||||
"_nuxt/unraid-components.client-fad7c220.css"
|
||||
],
|
||||
"file": "_nuxt/unraid-components.client-40074634.js",
|
||||
"file": "_nuxt/unraid-components.client-cd1b3939.js",
|
||||
"isEntry": true,
|
||||
"src": ".nuxt/nuxt-custom-elements/entries/unraid-components.client.mjs"
|
||||
}
|
||||
|
||||
@@ -11,6 +11,9 @@
|
||||
*/
|
||||
?>
|
||||
<?
|
||||
$docroot ??= ($_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp');
|
||||
require_once "$docroot/webGui/include/Wrappers.php";
|
||||
|
||||
// Invoke the plugin command with indicated method
|
||||
function plugin($method, $arg = '') {
|
||||
global $docroot;
|
||||
@@ -27,7 +30,7 @@ function language($method, $arg = '') {
|
||||
|
||||
function check_plugin($arg, &$ncsi) {
|
||||
// Get network connection status indicator (NCSI)
|
||||
if ($ncsi===null) $ncsi = exec("wget --spider --no-check-certificate -nv -T10 -t1 https://www.msftncsi.com/ncsi.txt 2>&1|grep -o 'OK'");
|
||||
if ($ncsi===null) $ncsi = check_network_connectivity();
|
||||
return $ncsi ? plugin('check',$arg) : false;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
/* Copyright 2005-2023, Lime Technology
|
||||
* Copyright 2012-2023, Bergware International.
|
||||
/* Copyright 2005-2024, Lime Technology
|
||||
* Copyright 2012-2024, Bergware International.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2,
|
||||
@@ -108,6 +108,7 @@ class UnraidOsCheck
|
||||
function _($text) {return $text;}
|
||||
}
|
||||
|
||||
// this command will set the $notify array
|
||||
extract(parse_plugin_cfg('dynamix', true));
|
||||
|
||||
$var = (array)@parse_ini_file('/var/local/emhttp/var.ini');
|
||||
@@ -115,7 +116,7 @@ class UnraidOsCheck
|
||||
$params = [];
|
||||
$params['branch'] = plugin('category', self::PLG_PATH, 'stable');
|
||||
$params['current_version'] = plugin('version', self::PLG_PATH) ?: _var($var,'version');
|
||||
if (_var($var,'regExp')) $params['update_exp'] = date('m-d-Y', _var($var,'regExp')*1);
|
||||
if (_var($var,'regExp')) $params['update_exp'] = date('Y-m-d', _var($var,'regExp')*1);
|
||||
$defaultUrl = self::BASE_RELEASES_URL;
|
||||
// pass a param of altUrl to use the provided url instead of the default
|
||||
$parsedAltUrl = (array_key_exists('altUrl',$_GET) && $_GET['altUrl']) ? $_GET['altUrl'] : null;
|
||||
@@ -123,21 +124,12 @@ class UnraidOsCheck
|
||||
if ($parsedAltUrl) $params['altUrl'] = $parsedAltUrl;
|
||||
|
||||
$urlbase = $parsedAltUrl ?? $defaultUrl;
|
||||
$url = $urlbase.'?'.http_build_query($params);
|
||||
|
||||
$response = "";
|
||||
// use error handler to convert warnings from file_get_contents to errors so they can be captured
|
||||
function warning_as_error($severity, $message, $filename, $lineno) {
|
||||
throw new ErrorException($message, 0, $severity, $filename, $lineno);
|
||||
$url = $urlbase.'?'.http_build_query($params);
|
||||
$curlinfo = [];
|
||||
$response = http_get_contents($url,[],$curlinfo);
|
||||
if (array_key_exists('error', $curlinfo)) {
|
||||
$response = json_encode(array('error' => $curlinfo['error']), JSON_PRETTY_PRINT);
|
||||
}
|
||||
set_error_handler("warning_as_error");
|
||||
try {
|
||||
$response = file_get_contents($url);
|
||||
} catch (Exception $e) {
|
||||
$response = json_encode(array('error' => $e->getMessage()), JSON_PRETTY_PRINT);
|
||||
}
|
||||
restore_error_handler();
|
||||
|
||||
$responseMutated = json_decode($response, true);
|
||||
if (!$responseMutated) {
|
||||
$response = json_encode(array('error' => 'Invalid response from '.$urlbase), JSON_PRETTY_PRINT);
|
||||
@@ -159,14 +151,17 @@ class UnraidOsCheck
|
||||
|
||||
// send notification if a newer version is available and not ignored
|
||||
$isNewerVersion = array_key_exists('isNewer',$responseMutated) ? $responseMutated['isNewer'] : false;
|
||||
$isReleaseIgnored = in_array($responseMutated['version'], $this->getIgnoredReleases());
|
||||
$isReleaseIgnored = array_key_exists('version',$responseMutated) ? in_array($responseMutated['version'], $this->getIgnoredReleases()) : false;
|
||||
|
||||
if ($responseMutated && $isNewerVersion && !$isReleaseIgnored) {
|
||||
$output = _var($notify,'plugin');
|
||||
$server = strtoupper(_var($var,'NAME','server'));
|
||||
$newver = (array_key_exists('version',$responseMutated) && $responseMutated['version']) ? $responseMutated['version'] : 'unknown';
|
||||
$script = '/usr/local/emhttp/webGui/scripts/notify';
|
||||
exec("$script -e ".escapeshellarg("System - Unraid [$newver]")." -s ".escapeshellarg("Notice [$server] - Version update $newver")." -d ".escapeshellarg("A new version of Unraid is available")." -i ".escapeshellarg("normal $output")." -l '/Tools/Update' -x");
|
||||
$event = "System - Unraid [$newver]";
|
||||
$subject = "Notice [$server] - Version update $newver";
|
||||
$description = "A new version of Unraid is available";
|
||||
exec("$script -e ".escapeshellarg($event)." -s ".escapeshellarg($subject)." -d ".escapeshellarg($description)." -i ".escapeshellarg("normal $output")." -l '/Tools/Update' -x");
|
||||
}
|
||||
|
||||
exit(0);
|
||||
|
||||
@@ -44,7 +44,7 @@ function write(...$messages){
|
||||
}
|
||||
|
||||
write(_("Checking connectivity")." ...\n");
|
||||
if (exec("wget --spider --no-check-certificate -nv -T10 -t1 https://www.msftncsi.com/ncsi.txt 2>&1|grep -om1 'OK'")) {
|
||||
if (check_network_connectivity()) {
|
||||
$check = popen('plugin checkall','r');
|
||||
while (!feof($check)) write(fgets($check));
|
||||
pclose($check);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/php -q
|
||||
<?PHP
|
||||
/* Copyright 2005-2023, Lime Technology
|
||||
* Copyright 2012-2023, Bergware International.
|
||||
/* Copyright 2005-2024, Lime Technology
|
||||
* Copyright 2012-2024, Bergware International.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2,
|
||||
@@ -15,6 +15,7 @@
|
||||
$docroot ??= ($_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp');
|
||||
require_once "$docroot/webGui/include/Wrappers.php";
|
||||
require_once "$docroot/plugins/dynamix.plugin.manager/include/PluginHelpers.php";
|
||||
// this command will set the $notify array
|
||||
extract(parse_plugin_cfg('dynamix', true));
|
||||
|
||||
// Multi-language support
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/php -q
|
||||
<?PHP
|
||||
/* Copyright 2005-2023, Lime Technology
|
||||
* Copyright 2012-2023, Bergware International.
|
||||
/* Copyright 2005-2024, Lime Technology
|
||||
* Copyright 2012-2024, Bergware International.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2,
|
||||
@@ -15,6 +15,7 @@
|
||||
$docroot ??= ($_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp');
|
||||
require_once "$docroot/webGui/include/Wrappers.php";
|
||||
require_once "$docroot/plugins/dynamix.plugin.manager/include/PluginHelpers.php";
|
||||
// this command will set the $notify array
|
||||
extract(parse_plugin_cfg('dynamix',true));
|
||||
|
||||
// Multi-language support
|
||||
|
||||
@@ -254,10 +254,24 @@ function selectsnapshot(uuid, name ,snaps, opt, getlist,state ,fstype){
|
||||
if (data.html) box.find('#targetsnapimages').html(data.html);
|
||||
},'json');
|
||||
}
|
||||
var memorydump = "no";
|
||||
document.getElementById("targetsnaprmv").checked = true;
|
||||
document.getElementById("targetsnaprmvmeta").checked = true;
|
||||
document.getElementById("targetsnapkeep").checked = true;
|
||||
document.getElementById("targetsnapfspc").checked = true;
|
||||
if (fstype == "ZFS") {
|
||||
box.find('#targetsnaprmv').prop('disabled',true);
|
||||
box.find('#targetsnaprmvmeta').prop('disabled',true);
|
||||
}
|
||||
if (state != "running") {
|
||||
box.find('#memoryline').prop('hidden',true);
|
||||
box.find('#targetsnapmem').prop('hidden',true);
|
||||
box.find('#targetsnapmem').prop('checked',false);
|
||||
} else {
|
||||
box.find('#memoryline').prop('hidden',false);
|
||||
box.find('#targetsnapmem').prop('hidden',false);
|
||||
box.find('#targetsnapmem').prop('checked',true);
|
||||
}
|
||||
box.dialog({
|
||||
title: optiontext,
|
||||
height: 'auto',
|
||||
@@ -285,10 +299,11 @@ function selectsnapshot(uuid, name ,snaps, opt, getlist,state ,fstype){
|
||||
if (opt == "create") {
|
||||
free = box.find('#targetsnapfspc').prop('checked') ? 'yes' : 'no';
|
||||
fstypeuse = box.find('#targetsnapfstype').prop('checked') ? 'yes' : 'no';
|
||||
memorydump = box.find('#targetsnapmem').prop('checked') ? 'yes' : 'no';
|
||||
if (fstypeuse == "no") fstype ="QEMU";
|
||||
desc = box.find("#targetsnapdesc").prop('value');
|
||||
}
|
||||
ajaxVMDispatch({action:"snap-" + opt +'-external', uuid:uuid, snapshotname:target, remove:remove, free:free, removemeta:removemeta, keep:keep, desc:desc, fstype:fstype}, "loadlist");
|
||||
ajaxVMDispatch({action:"snap-" + opt +'-external', uuid:uuid, snapshotname:target, remove:remove, free:free, removemeta:removemeta, keep:keep, desc:desc, fstype:fstype,memorydump:memorydump}, "loadlist");
|
||||
box.dialog('close');
|
||||
},
|
||||
"_(Cancel)_": function(){
|
||||
@@ -496,13 +511,15 @@ $(function() {
|
||||
<tr><td>_(VM Name)_:</td><td><label id="VMName"></label></td></tr>
|
||||
<tr><td>_(Snapshot Name)_:</td><td><input type="text" id="targetsnap" autocomplete="off" spellcheck="false" value="--generate" onclick="this.select()">_(Check free space)_: <input type="checkbox" id="targetsnapfspc" checked></td></tr>
|
||||
<tr><td>_(Description )_:</td><td><input type="text" id="targetsnapdesc" autocomplete="off" spellcheck="false" value="" onclick="this.select()"></td></tr>
|
||||
<tr id="fstypeline"><td>_(FS Native Snapshot )_:</td><td><label id="fstype"></label><input type="checkbox" id="targetsnapfstype" checked>_(Unchecked will use QEMU External Snapshot)_</td></tr>
|
||||
<tr id="memoryline"><td>_(Memory dump )_:</td><td><input type="checkbox" id="targetsnapmem" checked></td></tr>
|
||||
<tr id="fstypeline"><td>_(FS Native Snapshot )_:</td><td><label id="fstype"></label><input type="checkbox" id="targetsnapfstype">_(Unchecked will use QEMU External Snapshot)_</td></tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div id="templatesnapshotrevert" class="template">
|
||||
_(VM Name)_: <label id="VMName"></label><br>
|
||||
_(Snapshot Name)_: <input type="text" id="targetsnap" hidden><label id="targetsnapl"></label><br>
|
||||
<tr id="fstypeline"><td>_(Snapshot Method)_:</td><td><label id="fstype"></label><br>
|
||||
_(Remove Images)_: <input type="checkbox" id="targetsnaprmv" checked><br>
|
||||
_(Remove Meta)_:<input type="checkbox" id="targetsnaprmvmeta" checked> <input type="checkbox" id="targetsnapkeep" hidden><label id="targetsnapimages"></label><br>
|
||||
</div>
|
||||
|
||||
@@ -21,7 +21,6 @@ $_SERVER['REQUEST_URI'] = 'vms';
|
||||
require_once "$docroot/webGui/include/Translations.php";
|
||||
|
||||
$user_prefs = '/boot/config/plugins/dynamix.vm.manager/userprefs.cfg';
|
||||
if (file_exists('/boot/config/plugins/dynamix.vm.manager/vmpreview')) $vmpreview = true ; else $vmpreview = false ;
|
||||
$vms = $lv->get_domains();
|
||||
if (empty($vms)) {
|
||||
echo '<tr><td colspan="8" style="text-align:center;padding-top:12px">'._('No Virtual Machines installed').'</td></tr>';
|
||||
@@ -53,7 +52,7 @@ foreach ($vms as $vm) {
|
||||
$image = substr($icon,-4)=='.png' ? "<img src='$icon' class='img'>" : (substr($icon,0,5)=='icon-' ? "<i class='$icon img'></i>" : "<i class='fa fa-$icon img'></i>");
|
||||
$arrConfig = domain_to_config($uuid);
|
||||
$snapshots = getvmsnapshots($vm) ;
|
||||
$cdroms = $lv->get_cdrom_stats($res) ;
|
||||
$cdroms = $lv->get_cdrom_stats($res,true,true) ;
|
||||
if ($state == 'running') {
|
||||
$mem = $dom['memory']/1024;
|
||||
} else {
|
||||
@@ -110,7 +109,7 @@ foreach ($vms as $vm) {
|
||||
}
|
||||
unset($dom);
|
||||
if (!isset($domain_cfg["CONSOLE"])) $vmrcconsole = "web" ; else $vmrcconsole = $domain_cfg["CONSOLE"] ;
|
||||
$menu = sprintf("onclick=\"addVMContext('%s','%s','%s','%s','%s','%s','%s','%s','%s','%s')\"", addslashes($vm),addslashes($uuid),addslashes($template),$state,addslashes($vmrcurl),strtoupper($vmrcprotocol),addslashes($log),addslashes($fstype), $vmrcconsole,$vmpreview);
|
||||
$menu = sprintf("onclick=\"addVMContext('%s','%s','%s','%s','%s','%s','%s','%s','%s','%s')\"", addslashes($vm),addslashes($uuid),addslashes($template),$state,addslashes($vmrcurl),strtoupper($vmrcprotocol),addslashes($log),addslashes($fstype), $vmrcconsole,false);
|
||||
$kvm[] = "kvm.push({id:'$uuid',state:'$state'});";
|
||||
switch ($state) {
|
||||
case 'running':
|
||||
@@ -215,7 +214,7 @@ foreach ($vms as $vm) {
|
||||
$boot= $arrDisk["boot order"];
|
||||
$serial = $arrDisk["serial"];
|
||||
if ($boot < 1) $boot = _('Not set');
|
||||
$reallocation = trim(shell_exec("getfattr --absolute-names --only-values -n system.LOCATION ".escapeshellarg($disk)." 2>/dev/null"));
|
||||
$reallocation = trim(get_realvolume($disk));
|
||||
if (!empty($reallocation)) $reallocationstr = "($reallocation)"; else $reallocationstr = "";
|
||||
echo "<tr><td>$disk $reallocationstr</td><td>$serial</td><td>$bus</td>";
|
||||
if ($state == 'shutoff') {
|
||||
@@ -237,8 +236,10 @@ foreach ($vms as $vm) {
|
||||
|
||||
/* Display VM cdroms */
|
||||
foreach ($cdroms as $arrCD) {
|
||||
$tooltip = "";
|
||||
$capacity = $lv->format_size($arrCD['capacity'], 0);
|
||||
$allocation = $lv->format_size($arrCD['allocation'], 0);
|
||||
if ($arrCD['spundown']) {$capacity = $allocation = "*"; $tooltip = "Drive spun down ISO volume is ".$arrCD['reallocation'];} else $tooltip = "ISO volume is ".$arrCD['reallocation'];
|
||||
$disk = $arrCD['file'] ?? $arrCD['partition'] ?? "" ;
|
||||
$dev = $arrCD['device'];
|
||||
$bus = $arrValidDiskBuses[$arrCD['bus']] ?? 'VirtIO';
|
||||
@@ -247,7 +248,7 @@ foreach ($vms as $vm) {
|
||||
if ($disk != "" ) {
|
||||
$title = _('Eject CD Drive');
|
||||
$changemedia = "changemedia(\"{$uuid}\",\"{$dev}\",\"{$bus}\", \"--eject\")";
|
||||
echo "<tr><td>$disk <a title='$title' href='#' onclick='$changemedia'> <i class='fa fa-eject'></i></a></td><td></td><td>$bus</td><td>$capacity</td><td>$allocation</td><td>$boot</td></tr>";
|
||||
echo "<tr><td>$disk <a title='$title' href='#' onclick='$changemedia'> <i class='fa fa-eject'></i></a></td><td></td><td>$bus</td><td><span title='$tooltip' data-toggle='tooltip'>$capacity</span></td><td>$allocation</td><td>$boot</td></tr>";
|
||||
} else {
|
||||
$title = _('Insert CD');
|
||||
$changemedia = "changemedia(\"{$uuid}\",\"{$dev}\",\"{$bus}\",\"--select\")";
|
||||
@@ -282,7 +283,7 @@ foreach ($vms as $vm) {
|
||||
$snapshotmemory = _(ucfirst($snapshot["memory"]["@attributes"]["snapshot"]));
|
||||
$snapshotparent = $snapshot["parent"] ? $snapshot["parent"] : "None";
|
||||
$snapshotdatetime = my_time($snapshot["creationtime"],"Y-m-d" )."<br>".my_time($snapshot["creationtime"],"H:i:s");
|
||||
$snapmenu = sprintf("onclick=\"addVMSnapContext('%s','%s','%s','%s','%s','%s','%s')\"", addslashes($vm),addslashes($uuid),addslashes($template),$state,$snapshot["name"],$snapshot["method"],$vmpreview);
|
||||
$snapmenu = sprintf("onclick=\"addVMSnapContext('%s','%s','%s','%s','%s','%s')\"", addslashes($vm),addslashes($uuid),addslashes($template),$state,$snapshot["name"],$snapshot["method"]);
|
||||
echo "<tr><td><span id='vmsnap-$uuid' $snapmenu class='hand'>$tab|__ <i class='fa fa-clone'></i></span> ",$snapshot["name"],"</td><td>$snapshotdesc</td><td><span class='inner' style='font-size:1.1rem;'>$snapshotdatetime</span></td><td>$snapshotstate</td><td>$snapshotparent</td><td>$snapshotmemory</td></tr>";
|
||||
$tab .=" ";
|
||||
}
|
||||
|
||||
@@ -338,7 +338,7 @@ case 'snap-create':
|
||||
|
||||
case 'snap-create-external':
|
||||
requireLibvirt();
|
||||
$arrResponse = vm_snapshot($domName,$_REQUEST['snapshotname'],$_REQUEST['desc'],$_REQUEST['free'],$_REQUEST['fstype']) ;
|
||||
$arrResponse = vm_snapshot($domName,$_REQUEST['snapshotname'],$_REQUEST['desc'],$_REQUEST['free'],$_REQUEST['fstype'],$_REQUEST['memorydump']) ;
|
||||
break;
|
||||
|
||||
case 'snap-images':
|
||||
|
||||
@@ -1250,33 +1250,44 @@
|
||||
return $tmp;
|
||||
}
|
||||
|
||||
function get_cdrom_stats($domain, $sort=true) {
|
||||
function get_cdrom_stats($domain, $sort=true,$spincheck = false) {
|
||||
$unraiddisks = array_merge_recursive(@parse_ini_file('state/disks.ini',true)?:[], @parse_ini_file('state/devs.ini',true)?:[]);
|
||||
$dom = $this->get_domain_object($domain);
|
||||
|
||||
$tmp = false;
|
||||
$buses = $this->get_xpath($dom, '//domain/devices/disk[@device="cdrom"]/target/@bus', false);
|
||||
$disks = $this->get_xpath($dom, '//domain/devices/disk[@device="cdrom"]/target/@dev', false);
|
||||
$cds = $this->get_xpath($dom, '//domain/devices/disk[@device="cdrom"]/target/@dev', false);
|
||||
$files = $this->get_xpath($dom, '//domain/devices/disk[@device="cdrom"]/source/@file', false);
|
||||
$boot = $this->get_xpath($dom, '//domain/devices/disk[@device="cdrom"]/boot/@*', false);
|
||||
|
||||
$ret = [];
|
||||
for ($i = 0; $i < $disks['num']; $i++) {
|
||||
$tmp = libvirt_domain_get_block_info($dom, $disks[$i]);
|
||||
for ($i = 0; $i < $cds['num']; $i++) {
|
||||
$spundown = 0;
|
||||
$reallocation = null;
|
||||
if (isset($files[$i])) $reallocation = trim(get_realvolume($files[$i]));
|
||||
if ($spincheck) {
|
||||
if (isset($unraiddisks[$reallocation]['spundown']) && $unraiddisks[$reallocation]['spundown'] == 1) $spundown = 1; else $tmp = libvirt_domain_get_block_info($dom, $cds[$i]);
|
||||
} else $tmp = libvirt_domain_get_block_info($dom, $cds[$i]);
|
||||
|
||||
if ($tmp) {
|
||||
$tmp['bus'] = $buses[$i];
|
||||
$tmp["boot order"] = $boot[$i] ?? "";
|
||||
$tmp['reallocation'] = $reallocation;
|
||||
$tmp['spundown'] = $spundown;
|
||||
$ret[] = $tmp;
|
||||
}
|
||||
else {
|
||||
$this->_set_last_error();
|
||||
|
||||
$ret[] = [
|
||||
'device' => $disks[$i],
|
||||
'device' => $cds[$i],
|
||||
'file' => $files[$i],
|
||||
'type' => '-',
|
||||
'capacity' => '-',
|
||||
'allocation' => '-',
|
||||
'physical' => '-',
|
||||
'bus' => $buses[$i]
|
||||
'bus' => $buses[$i],
|
||||
'reallocation' => $reallocation,
|
||||
'spundown' => $spundown
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1294,7 +1305,7 @@
|
||||
}
|
||||
|
||||
unset($buses);
|
||||
unset($disks);
|
||||
unset($cds);
|
||||
unset($files);
|
||||
|
||||
return $ret;
|
||||
|
||||
@@ -1621,7 +1621,6 @@ private static $encoding = 'UTF-8';
|
||||
$dom = $lv->domain_get_info($res);
|
||||
$state = $lv->domain_state_translate($dom['state']);
|
||||
$vmxml = $lv->domain_get_xml($res) ;
|
||||
file_put_contents("/tmp/cloningxml" ,$vmxml) ; ## Remove before stable.
|
||||
$storage = $lv->_get_single_xpath_result($vm, '//domain/metadata/*[local-name()=\'vmtemplate\']/@storage');
|
||||
if (empty($storage)) $storage = "default" ;
|
||||
# if VM running shutdown. Record was running.
|
||||
@@ -1709,7 +1708,6 @@ private static $encoding = 'UTF-8';
|
||||
write("addLog\0".htmlspecialchars("Creating new XML $clone"));
|
||||
|
||||
$xml = $lv->config_to_xml($config, true) ;
|
||||
file_put_contents("/tmp/clonexml" ,$xml) ; ## Remove before stable.
|
||||
$rtn = $lv->domain_define($xml) ;
|
||||
return($rtn) ;
|
||||
|
||||
@@ -1868,7 +1866,7 @@ private static $encoding = 'UTF-8';
|
||||
return true ;
|
||||
}
|
||||
|
||||
function vm_snapshot($vm,$snapshotname, $snapshotdesc, $free = "yes", $method = "QEMU", $memorysnap = "yes") {
|
||||
function vm_snapshot($vm,$snapshotname, $snapshotdescinput, $free = "yes", $method = "QEMU", $memorysnap = "yes") {
|
||||
global $lv ;
|
||||
|
||||
#Get State
|
||||
@@ -1883,7 +1881,7 @@ private static $encoding = 'UTF-8';
|
||||
$diskspec = "" ;
|
||||
$capacity = 0 ;
|
||||
if ($snapshotname == "--generate") $name= "S" . date("YmdHis") ; else $name=$snapshotname ;
|
||||
if ($snapshotdesc != "") $snapshotdesc = " --description '$snapshotdesc'" ;
|
||||
if ($snapshotdescinput != "") $snapshotdesc = " --description '$snapshotdescinput'" ;
|
||||
|
||||
foreach($disks as $disk) {
|
||||
$file = $disk["file"] ;
|
||||
@@ -1915,7 +1913,7 @@ private static $encoding = 'UTF-8';
|
||||
$cmdstr = "virsh snapshot-create-as '$vm' --name '$name' $snapshotdesc --atomic" ;
|
||||
|
||||
|
||||
if ($state == "running") {
|
||||
if ($state == "running" & $memorysnap == "yes") {
|
||||
$cmdstr .= " --live ".$memspec.$diskspec ;
|
||||
$capacity = $capacity + $memory ;
|
||||
|
||||
@@ -1934,7 +1932,6 @@ private static $encoding = 'UTF-8';
|
||||
if (!empty($lv->domain_get_ovmf($res))) $nvram = $lv->nvram_create_snapshot($lv->domain_get_uuid($vm),$name) ;
|
||||
|
||||
$xmlfile = $dirpath."/".$name.".running" ;
|
||||
file_put_contents("/tmp/xmltst", "$xmlfile" ) ;## Remove before stable.
|
||||
if ($state == "running") exec("virsh dumpxml '$vm' > ".escapeshellarg($xmlfile),$outxml,$rtnxml) ;
|
||||
|
||||
$output= [] ;
|
||||
@@ -1961,7 +1958,7 @@ private static $encoding = 'UTF-8';
|
||||
$arrResponse = ['error' => substr($output[0],6) ] ;
|
||||
} else {
|
||||
$arrResponse = ['success' => true] ;
|
||||
$ret = write_snapshots_database("$vm","$name",$state,$snapshotdesc,$method) ;
|
||||
$ret = write_snapshots_database("$vm","$name",$state,$snapshotdescinput,$method) ;
|
||||
#remove meta data
|
||||
if ($ret != "noxml") $ret = $lv->domain_snapshot_delete($vm, "$name" ,2) ;
|
||||
}
|
||||
@@ -2017,7 +2014,6 @@ private static $encoding = 'UTF-8';
|
||||
if ($method == "ZFS") $xml = $snapslist[$snap]['xml']; else $xml = custom::createXML('domain',$xmlobj)->saveXML();
|
||||
if (!strpos($xml,'<vmtemplate xmlns="unraid"')) $xml=str_replace('<vmtemplate','<vmtemplate xmlns="unraid"',$xml);
|
||||
if (!$dryrun) $new = $lv->domain_define($xml);
|
||||
file_put_contents("/tmp/xmlrevert", "$xml" ) ;## Remove before stable.
|
||||
if ($new) $arrResponse = ['success' => true] ; else $arrResponse = ['error' => $lv->get_last_error()] ;
|
||||
}
|
||||
|
||||
@@ -2028,15 +2024,13 @@ private static $encoding = 'UTF-8';
|
||||
if ($diskname == "hda" || $diskname == "hdb") continue ;
|
||||
$path = $disk["source"]["@attributes"]["file"] ;
|
||||
if (is_file($path) && $action == "yes") if (!$dryrun) unlink("$path") ;else echo "unlink $path\n";
|
||||
file_put_contents("/tmp/rmvsnaps",$path,FILE_APPEND);
|
||||
$item = array_search($path,$snapslist[$snap]['backing']["r".$diskname]) ;
|
||||
$item++ ;
|
||||
while($item > 0)
|
||||
{
|
||||
if (!isset($snapslist[$snap]['backing']["r".$diskname][$item])) break ;
|
||||
$newpath = $snapslist[$snap]['backing']["r".$diskname][$item] ;
|
||||
file_put_contents("/tmp/rmvsnaps",$newpath,FILE_APPEND);
|
||||
if (is_file($newpath) && $action == "yes") if (!$dryrun) unlink("$newpath"); else echo "unlink $newpath\n";
|
||||
if (is_file($newpath) && $action == "yes") if (!$dryrun) unlink("$newpath"); else echo "unlink $newpath\n";
|
||||
$item++ ;
|
||||
}
|
||||
}
|
||||
@@ -2094,7 +2088,7 @@ private static $encoding = 'UTF-8';
|
||||
if (!$dryrun) shell_exec($fssnapcmd); else echo "$fssnapcmd\n";
|
||||
}
|
||||
|
||||
if ($snapslist[$snap]['state'] == "running") {
|
||||
if ($snapslist[$snap]['state'] == "running" || $snapslist[$snap]['state'] == "disk-snapshot") {
|
||||
$xmlfile = $primarypath."/$snap.running" ;
|
||||
$memoryfile = $primarypath."/memory$snap.mem" ;
|
||||
# Set XML to saved XML
|
||||
@@ -2102,14 +2096,16 @@ private static $encoding = 'UTF-8';
|
||||
$xmlobj = custom::createArray('domain',$xml) ;
|
||||
$xml = custom::createXML('domain',$xmlobj)->saveXML();
|
||||
if (!strpos($xml,'<vmtemplate xmlns="unraid"')) $xml=str_replace('<vmtemplate','<vmtemplate xmlns="unraid"',$xml);
|
||||
file_put_contents("/tmp/xmlrevert2", "$xml" ) ;## Remove before stable.
|
||||
if (!$dryrun) $rtn = $lv->domain_define($xml) ;
|
||||
|
||||
|
||||
# Restore Memory.
|
||||
if (!$dryrun) $cmdrtn = exec("virsh restore --running ".escapeshellarg($memoryfile)) ;
|
||||
if (!$dryrun && !$cmdrtn) unlink($xmlfile);
|
||||
if (!$dryrun && !$cmdrtn) unlink($memoryfile);
|
||||
if ($snapslist[$snap]['state'] == "running") {
|
||||
if (!$dryrun) $cmdrtn = exec("virsh restore --running ".escapeshellarg($memoryfile)) ;
|
||||
if (!$dryrun && !$cmdrtn) unlink($xmlfile);
|
||||
if (!$dryrun && !$cmdrtn) unlink($memoryfile);
|
||||
}
|
||||
if ($snapslist[$snap]['state'] == "disk-snapshot") if (!$dryrun) unlink($xmlfile);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@ function ajaxVMDispatchconsoleRV(params, spin){
|
||||
}
|
||||
},'json');
|
||||
}
|
||||
function addVMContext(name, uuid, template, state, vmrcurl, vmrcprotocol, log, fstype="QEMU",console="web", preview=false){
|
||||
function addVMContext(name, uuid, template, state, vmrcurl, vmrcprotocol, log, fstype="QEMU",console="web",usage=false){
|
||||
var opts = [];
|
||||
var path = location.pathname;
|
||||
var x = path.indexOf("?");
|
||||
@@ -198,9 +198,9 @@ function addVMContext(name, uuid, template, state, vmrcurl, vmrcprotocol, log, f
|
||||
}});
|
||||
}
|
||||
}
|
||||
context.attach('#vm-'+uuid, opts);
|
||||
if (usage) context.attach('#vmusage-'+uuid, opts); else context.attach('#vm-'+uuid, opts);
|
||||
}
|
||||
function addVMSnapContext(name, uuid, template, state, snapshotname, method, preview=false){
|
||||
function addVMSnapContext(name, uuid, template, state, snapshotname, method){
|
||||
var opts = [];
|
||||
var path = location.pathname;
|
||||
var x = path.indexOf("?");
|
||||
@@ -211,7 +211,7 @@ function addVMSnapContext(name, uuid, template, state, snapshotname, method, pre
|
||||
|
||||
opts.push({text:_("Revert snapshot"), icon:"fa-fast-backward", action:function(e) {
|
||||
e.preventDefault();
|
||||
selectsnapshot(uuid, name, snapshotname, "revert",true) ;
|
||||
selectsnapshot(uuid, name, snapshotname, "revert",true,state,method) ;
|
||||
}});
|
||||
if (method == "QEMU") {
|
||||
opts.push({text:_("Block Commit"), icon:"fa-hdd-o", action:function(e) {
|
||||
@@ -225,17 +225,12 @@ function addVMSnapContext(name, uuid, template, state, snapshotname, method, pre
|
||||
e.preventDefault();
|
||||
selectblock(uuid, name, snapshotname, "pull",true) ;
|
||||
}});
|
||||
if (preview) {
|
||||
opts.push({text:_("Block Copy"), icon:"fa-stop", action:function(e) {
|
||||
e.preventDefault();
|
||||
ajaxVMDispatch({action:"domain-stop", uuid:uuid}, "loadlist");
|
||||
}}); }
|
||||
}
|
||||
} else {
|
||||
opts.push({text:_("Revert snapshot"), icon:"fa-fast-backward", action:function(e) {
|
||||
e.preventDefault();
|
||||
$('#vm-'+uuid).find('i').removeClass('fa-play fa-square fa-pause').addClass('fa-refresh fa-spin');
|
||||
selectsnapshot(uuid, name, snapshotname, "revert",true) ;
|
||||
selectsnapshot(uuid, name, snapshotname, "revert",true,state,method) ;
|
||||
}});
|
||||
}
|
||||
opts.push({text:_("Remove snapshot"), icon:"fa-trash", action:function(e) {
|
||||
|
||||
@@ -70,6 +70,7 @@ while (true) {
|
||||
$ts = $time1 - $time0;
|
||||
$echodata = "";
|
||||
$running = 0;
|
||||
ksort($vmusagestats);
|
||||
foreach ($vmusagestats as $vm => $vmdata) {
|
||||
|
||||
if ($vmdata['state'] == 1) {
|
||||
|
||||
58
emhttp/plugins/dynamix.vm.manager/scripts/virtiofsd.php
Executable file
58
emhttp/plugins/dynamix.vm.manager/scripts/virtiofsd.php
Executable file
@@ -0,0 +1,58 @@
|
||||
#!/usr/bin/php
|
||||
<?php
|
||||
/* Copyright 2005-2024, Lime Technology
|
||||
* Copyright 2024, Simon Fairweather
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*/
|
||||
|
||||
# Command for bash script /usr/libexec/virtiofsd
|
||||
# eval exec /usr/bin/virtiofsd $(/usr/local/emhttp/plugins/dynamix.vm.manager/scripts/virtiofsd.php "$@")
|
||||
|
||||
$file = "/etc/libvirt/virtiofsd.opt";
|
||||
$whole_cmd = '';
|
||||
$long_options = ["fd:","print-capabilities","syslog","daemonize","rlimit-nofile","thread-pool-size:","socket-path:","socket-group:","help","version","source:"];
|
||||
$short_options = "o:dfV";
|
||||
$argoptions = getopt($short_options,$long_options);
|
||||
|
||||
array_shift($argv);
|
||||
foreach ($argv as $i=>$arg) {
|
||||
if (strpos($arg, "--fd") !== false) unset($argv[$i]) ;
|
||||
if ($arg == "-o") { unset($argv[$i]);unset($argv[$i+1]); }
|
||||
}
|
||||
# Check if options file exists. Each option should be on a new line.
|
||||
if (is_file($file)) $options = explode("\n",file_get_contents($file)) ; else $options = ['--syslog','--inode-file-handles=mandatory','--announce-submounts'];
|
||||
$options[] = "--fd=".$argoptions['fd'];
|
||||
|
||||
if (isset($argoptions['o'])) {
|
||||
$virtiofsoptions = explode(',',$argoptions["o"]);
|
||||
foreach ($virtiofsoptions as $opt) {
|
||||
$optsplit = explode('=',$opt);
|
||||
switch ($optsplit[0]) {
|
||||
case "source":
|
||||
$options[] = "--shared-dir={$optsplit[1]}";
|
||||
break;
|
||||
case "cache":
|
||||
$options[] = "--cache=never";
|
||||
break;
|
||||
case "xattr":
|
||||
$options[] = "--xattr";
|
||||
break;
|
||||
case "sandbox":
|
||||
$options[] = "--sandbox={$optsplit[1]}";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$newargs = array_merge($options,$argv);
|
||||
foreach($newargs as $arg) {
|
||||
if ($arg != "") $whole_cmd.= escapeshellarg($arg).' ';
|
||||
}
|
||||
echo trim($whole_cmd);
|
||||
?>
|
||||
@@ -545,6 +545,9 @@ window.onunload = function(){
|
||||
<? elseif (_var($var,'configValid')=="invalid"):?>
|
||||
<tr><td><?status_indicator()?>**_(Stopped)_.**</td><td><input type="submit" name="cmdStart" value="_(Start)_" disabled></td>
|
||||
<td>_(Too many attached devices. Please consider upgrading your)_ <a href="/Tools/Registration">_(registration key)_</a>.</td></tr>
|
||||
<? elseif (_var($var,'configValid')=="ineligible"):?>
|
||||
<tr><td><?status_indicator()?>**_(Stopped)_.**</td><td><input type="submit" name="cmdStart" value="_(Start)_" disabled></td>
|
||||
<td>_(Ineligible to run this version of Unraid OS. Please consider extending your)_ <a href="/Tools/Registration">_(registration key)_</a>.</td></tr>
|
||||
<? elseif (_var($var,'configValid')=="nokeyserver"):?>
|
||||
<tr><td><?status_indicator()?>**_(Stopped)_.**</td><td><input type="submit" name="cmdStart" value="_(Start)_" disabled></td>
|
||||
<td>_(Cannot contact key-server. Please check your)_ <a href="/Settings/NetworkSettings">_(network settings)_</a>.</td></tr>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
Menu="Dashboard"
|
||||
Nchan="wg_poller,update_1,update_2,update_3,ups_status:stop"
|
||||
Nchan="wg_poller,update_1,update_2,update_3,ups_status:stop,vm_dashusage:stop"
|
||||
---
|
||||
<?PHP
|
||||
/* Copyright 2005-2023, Lime Technology * Copyright 2012-2023, Bergware International.
|
||||
@@ -73,6 +73,10 @@ $vdisk = exec("grep -Pom1 '^DOCKER_IMAGE_TYPE=\"\\K[^\"]+' /boot/config/docker.c
|
||||
$dot = _var($display,'number','.,')[0];
|
||||
$zfs = count(array_filter(array_column($disks,'fsType'),function($fs){return str_replace('luks:','',$fs??'')=='zfs';}));
|
||||
|
||||
$domain_cfgfile = "/boot/config/domain.cfg";
|
||||
$domain_cfg = parse_ini_file($domain_cfgfile);
|
||||
if (!isset($domain_cfg['USAGE'])) $vmusage = "N" ; else $vmusage = $domain_cfg['USAGE'];
|
||||
|
||||
// enable/disable graph elements by making hook script executable or not
|
||||
chmod("$docroot/webGui/system/VM_usage",$libvirtd ? 0755 : 0644);
|
||||
chmod("$docroot/webGui/system/ZFS_cache",$zfs ? 0755 : 0644);
|
||||
@@ -275,10 +279,10 @@ foreach ($cpus as $pair) {
|
||||
<a href='/Dashboard/Tools/Processes' title="_(View Running Processes)_"><i class='fa fa-fw fa-info-circle control'></i></a>
|
||||
</td></tr><tr><td>
|
||||
<span class='w26'><i class='ups fa fa-compress'></i>_(Usable size)_: <?=$ramsize?><br><i class='ups fa fa-expand'></i>_(Maximum size)_: <?="$memory_maximum $unit"?><?=$low?'*':''?></span>
|
||||
<span class='w18 center'><a class='info hand none'>_(RAM usage)_<span>_(Percent of total used memory)_ (<?=$ramsize?>)</span></a></span>
|
||||
<span class='w18 center'><a class='info hand none'>_(Flash device)_<span>_(Percent usage of flash usb device)_ (<?=$flashsize?>)</span></a></span>
|
||||
<span class='w18 center'><a class='info hand none'>_(Log filesystem)_<span>_(Percent usage of LOG file system)_ (<?=$logsize?>)</span></a></span>
|
||||
<span class='w18 center'><a class='info hand none'><?=$vdisk?><span><?=_("Percent usage of $vdisk")?> (<?=$dockersize?>)</span></a></span>
|
||||
<span class='w18 center static'><a class='info hand none'>_(RAM usage)_<span>_(Percent of total used memory)_ (<?=$ramsize?>)</span></a></span>
|
||||
<span class='w18 center static'><a class='info hand none'>_(Flash device)_<span>_(Percent usage of flash usb device)_ (<?=$flashsize?>)</span></a></span>
|
||||
<span class='w18 center static'><a class='info hand none'>_(Log filesystem)_<span>_(Percent usage of LOG file system)_ (<?=$logsize?>)</span></a></span>
|
||||
<span class='w18 center static'><a class='info hand none'><?=$vdisk?><span><?=_("Percent usage of $vdisk")?> (<?=$dockersize?>)</span></a></span>
|
||||
</td></tr><tr><td>
|
||||
<span class='w26'><legend>_(Legend)_</legend><span id='dynamic'></span></span>
|
||||
<span class='w18 center'><div class='pie' id='sys0'><span class='sys0'></span><span class='var0'></span></div></span>
|
||||
@@ -424,6 +428,13 @@ echo "</td></tr>";
|
||||
<a href='/Dashboard/Settings/VMSettings' title="_(Go to VM settings)_"><i class='fa fa-fw fa-cog control'></i></a>
|
||||
</td></tr>
|
||||
</tbody>
|
||||
<?if ($vmusage == "Y"):?>
|
||||
<tbody id='vm_view_usage' title="_(Virtual Machines Usage)_" >
|
||||
<tr><td><i class='icon-virtualization f32'></i><div class='section'>_(Virtual Machines Usage)_</div>
|
||||
<a href='/Dashboard/Settings/VMSettings' title="_(Go to VM settings)_"><i class='fa fa-fw fa-cog control'></i></a>
|
||||
</td></tr>
|
||||
</tbody>
|
||||
<?endif;?>
|
||||
<?endif;?>
|
||||
|
||||
<tbody title="_(Shares Information)_"<?if ($group):?> class="mixed"<?endif;?>>
|
||||
@@ -685,7 +696,8 @@ function hideShow() {
|
||||
<tr><td>_(VM Name)_:</td><td><label id="VMName"></label></td></tr>
|
||||
<tr><td>_(Snapshot Name)_:</td><td><input type="text" id="targetsnap" autocomplete="off" spellcheck="false" value="--generate" onclick="this.select()">_(Check free space)_:<input type="checkbox" id="targetsnapfspc" checked></td></tr>
|
||||
<tr><td>_(Description)_:</td><td><input type="text" id="targetsnapdesc" autocomplete="off" spellcheck="false" value="" onclick="this.select()"></td></tr>
|
||||
<tr id="fstypeline"><td>_(FS Native Snapshot )_:</td><td><label id="fstype"></label><input type="checkbox" id="targetsnapfstype" checked>_(Unchecked will use QEMU External Snapshot)_</td></tr>
|
||||
<tr id="memoryline"><td>_(Memory dump )_:</td><td><input type="checkbox" id="targetsnapmem" checked></td></tr>
|
||||
<tr id="fstypeline"><td>_(FS Native Snapshot )_:</td><td><label id="fstype"></label><input type="checkbox" id="targetsnapfstype" >_(Unchecked will use QEMU External Snapshot)_</td></tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
@@ -932,7 +944,7 @@ function loadlist(init) {
|
||||
$('#vms').is(':checked') ? $.cookie('my_vms','startedOnly',{expires:3650}) : $.removeCookie('my_vms');
|
||||
});
|
||||
}
|
||||
$.post('/webGui/include/DashboardApps.php',{docker:'<?=$dockerd?>',vms:'<?=$libvirtd?>'},function(d) {
|
||||
$.post('/webGui/include/DashboardApps.php',{docker:'<?=$dockerd?>',vms:'<?=$libvirtd?>',vmusage:'<?=$vmusage?>'},function(d) {
|
||||
var data = d.split('\0');
|
||||
$('#docker_view tr.updated').remove();
|
||||
$('#docker_view').append(data[0]).hideMe();
|
||||
@@ -944,6 +956,8 @@ function loadlist(init) {
|
||||
var started_vms = $('#vm_view').find('span.outer.vms.started').length;
|
||||
var stopped_vms = $('#vm_view').find('span.outer.vms.stopped').length;
|
||||
var paused_vms = $('#vm_view').find('span.outer.vms.paused').length;
|
||||
$('#vm_view_usage tr.useupdated').remove();
|
||||
$('#vm_view_usage').append(data[2]).hideMe();
|
||||
$('.apps.switch').html("_(Containers)_ -- _(Started)_: "+started_apps+", _(Stopped)_: "+stopped_apps+", _(Paused)_: "+paused_apps);
|
||||
$('.vms.switch').html("_(VMs)_ -- _(Started)_: "+started_vms+", _(Stopped)_: "+stopped_vms+", _(Paused)_: "+paused_vms);
|
||||
if ($.cookie('my_apps')!=null) $('span.apps.stopped').hide(0,noApps());
|
||||
@@ -1209,7 +1223,7 @@ function addProperties() {
|
||||
$('div#sys3').hover(function(){$('.sys3').hide();$('.var3').show();},function(){$('.sys3').show();$('.var3').hide();});
|
||||
$('#current_time').hover(function(){$.post('/webGui/include/DashboardApps.php',{ntp:'ntp'},function(ntp){$('#current_time').prop('title',ntp+"\n_(Go to date and time settings)_");});});
|
||||
// make truncated descriptions fully visible when hovering over them
|
||||
$('span.w18').hover(
|
||||
$('span.w18').not('.static').hover(
|
||||
function(){if ($(this)[0].offsetWidth < $(this)[0].scrollWidth) {recall = $(this).next(); recover=recall.html(); recall.html(' ');}},
|
||||
function(){if ($(this)[0].offsetWidth < $(this)[0].scrollWidth) {recall.html(recover); recall=null;}}
|
||||
);
|
||||
@@ -1380,7 +1394,7 @@ function VMClone(uuid, name){
|
||||
});
|
||||
dialogStyle();
|
||||
}
|
||||
function selectsnapshot(uuid, name ,snaps, opt, getlist, status,fstype){
|
||||
function selectsnapshot(uuid, name ,snaps, opt, getlist, state,fstype){
|
||||
box = $("#iframe-popup");
|
||||
box.html($("#templatesnapshot"+opt).html());
|
||||
const capopt = opt.charAt(0).toUpperCase() + opt.slice(1);
|
||||
@@ -1394,7 +1408,21 @@ function selectsnapshot(uuid, name ,snaps, opt, getlist, status,fstype){
|
||||
var only = (opt == "remove") ? 0 : 1;
|
||||
$.post("/plugins/dynamix.vm.manager/include/VMajax.php",{action:"snap-images",uuid:uuid,snapshotname:snaps,only:only},function(data){if (data.html) box.find('#targetsnapimages').html(data.html);},'json');
|
||||
}
|
||||
var memorydump = "no";
|
||||
document.getElementById("targetsnapfspc").checked = true;
|
||||
if (fstype == "ZFS") {
|
||||
box.find('#targetsnaprmv').prop('disabled',true);
|
||||
box.find('#targetsnaprmvmeta').prop('disabled',true);
|
||||
}
|
||||
if (state != "running") {
|
||||
box.find('#memoryline').prop('hidden',true);
|
||||
box.find('#targetsnapmem').prop('hidden',true);
|
||||
box.find('#targetsnapmem').prop('checked',false);
|
||||
} else {
|
||||
box.find('#memoryline').prop('hidden',false);
|
||||
box.find('#targetsnapmem').prop('hidden',false);
|
||||
box.find('#targetsnapmem').prop('checked',true);
|
||||
}
|
||||
box.dialog({
|
||||
title: optiontext,
|
||||
height: 'auto',
|
||||
@@ -1422,10 +1450,11 @@ function selectsnapshot(uuid, name ,snaps, opt, getlist, status,fstype){
|
||||
if (opt == "create") {
|
||||
free = box.find('#targetsnapfspc').prop('checked') ? 'yes' : 'no';
|
||||
desc = box.find("#targetsnapdesc").prop('value');
|
||||
memorydump = box.find('#targetsnapmem').prop('checked') ? 'yes' : 'no';
|
||||
fstypeuse = box.find('#targetsnapfstype').prop('checked') ? 'yes' : 'no';
|
||||
if (fstypeuse == "no") fstype ="QEMU";
|
||||
}
|
||||
ajaxVMDispatch({action:"snap-" + opt +'-external', uuid:uuid, snapshotname:target, remove:remove, free:free, desc:desc, fstype:fstype}, "loadlist");
|
||||
ajaxVMDispatch({action:"snap-" + opt +'-external', uuid:uuid, snapshotname:target, remove:remove, free:free, desc:desc, fstype:fstype,memorydump:memorydump}, "loadlist");
|
||||
box.dialog('close');
|
||||
},
|
||||
"_(Cancel)_": function(){
|
||||
@@ -1501,6 +1530,18 @@ function cpu_parse(msg) {
|
||||
return parse;
|
||||
}
|
||||
|
||||
<?if ($vmusage == "Y"):?>
|
||||
var vmdashusage = new NchanSubscriber('/sub/vm_dashusage',{subscriber:'websocket'});
|
||||
vmdashusage.on('message', function(msg){
|
||||
var data = JSON.parse(msg);
|
||||
for (const [vm, vmdata] of Object.entries(data)) {
|
||||
for (const [displayitem, value] of Object.entries(vmdata)) {
|
||||
$('#vmmetrics-'+displayitem + '-' + vm ).html(value);
|
||||
}
|
||||
}
|
||||
});
|
||||
<?endif;?>
|
||||
|
||||
var dashboard = new NchanSubscriber('/sub/cpuload,update1,update2,update3<?=$wireguard?",wireguard":""?>',{subscriber:'websocket'});
|
||||
dashboard.on('message',function(msg,meta) {
|
||||
switch (meta.id.channel()) {
|
||||
@@ -1667,6 +1708,9 @@ $(function() {
|
||||
dropdown('enter_view');
|
||||
startup = false;
|
||||
dashboard.start();
|
||||
<?if ($vmusage == "Y"):?>
|
||||
vmdashusage.start();
|
||||
<?endif;?>
|
||||
<?if ($apcupsd):?>
|
||||
apcups.start();
|
||||
<?endif;?>
|
||||
@@ -1692,6 +1736,9 @@ $(function() {
|
||||
|
||||
window.onunload = function(){
|
||||
dashboard.stop();
|
||||
<?if ($vmusage == "Y"):?>
|
||||
vmdashusage.stop();
|
||||
<?endif;?>
|
||||
<?if ($apcupsd):?>
|
||||
apcups.stop();
|
||||
<?endif;?>
|
||||
|
||||
@@ -313,7 +313,14 @@ function setGlue(form,reset) {
|
||||
{glue:'/',more:3,dev:1,type:'',min1:1,max1:4,min2:1,max2:128,min3:1,max3:4}, // highpoint
|
||||
{glue:'' ,more:1,dev:1,type:'',min1:0,max1:15}, // hp cciss
|
||||
{glue:'' ,more:0,dev:0,type:''}, // marvell
|
||||
{glue:',',more:1,dev:1,type:'',min1:0,max1:127} // megaraid
|
||||
{glue:',',more:1,dev:1,type:'',min1:0,max1:127}, // megaraid
|
||||
{glue:',',more:1,dev:0,type:'input',min1:'',max1:'0xffffffff'}, // cypress
|
||||
{glue:',',more:3,dev:0,type:'select',min1:'',max1:'p',min2:'',max2:'x',min3:1,max3:128},// jmicron ata
|
||||
{glue:'' ,more:0,dev:0,type:''}, // prolific
|
||||
{glue:'' ,more:0,dev:0,type:''}, // sunplus
|
||||
{glue:'' ,more:0,dev:0,type:''}, // asmedia
|
||||
{glue:'' ,more:0,dev:0,type:''}, // jmicron nvme
|
||||
{glue:'' ,more:0,dev:0,type:''}, // realtek
|
||||
];
|
||||
var n = form.smType.selectedIndex>0 ? form.smType.selectedIndex-1 : <?=_var($var,'smIndex',0)?>;
|
||||
var x = data[n]['more'];
|
||||
@@ -603,7 +610,7 @@ _(Spin down delay)_:
|
||||
_(File system status)_:
|
||||
: <?=_(_var($disk,'fsStatus'))?>
|
||||
|
||||
<?$disabled = (_var($var,'fsState')=="Stopped" && !empty(_var($disk,'uuid'))) || (_var($var,'fsState')=="Started" && _var($disk,'fsStatus')=='Mounted') ? "disabled" : ""?>
|
||||
<?$disabled = (_var($var,'fsState')=="Stopped" && !empty(_var($disk,'uuid'))) || (_var($var,'fsState')=="Started" && _var($disk,'fsType')!='auto') ? "disabled" : ""?>
|
||||
<?if (diskType('Data') || (!isSubpool($name) && _var($disk,'slots',0)==1)):?>
|
||||
_(File system type)_:
|
||||
: <select id="diskFsType" name="diskFsType.<?=_var($disk,'idx',0)?>" onchange="changeFsType()" <?=$disabled?>>
|
||||
@@ -1246,6 +1253,13 @@ _(SMART controller type)_:
|
||||
<?=mk_option(_var($disk,'smType'), "-d cciss", "HP cciss")?>
|
||||
<?=mk_option(_var($disk,'smType'), "-d marvell", "Marvell")?>
|
||||
<?=mk_option(_var($disk,'smType'), "-d megaraid", "MegaRAID")?>
|
||||
<?=mk_option(_var($disk,'smType'), "-d usbcypress", "Cypress ATACB")?>
|
||||
<?=mk_option(_var($disk,'smType'), "-d usbjmicron", "JMicron ATA pass-through")?>
|
||||
<?=mk_option(_var($disk,'smType'), "-d usbprolific", "Prolific ATA pass-through")?>
|
||||
<?=mk_option(_var($disk,'smType'), "-d usbsunplus", "Sunplus ATA pass-through")?>
|
||||
<?=mk_option(_var($disk,'smType'), "-d sntasmedia", "ASMedia NVMe pass-through")?>
|
||||
<?=mk_option(_var($disk,'smType'), "-d sntjmicron", "JMicron NVMe pass-through")?>
|
||||
<?=mk_option(_var($disk,'smType'), "-d sntrealtek", "Realtek NVMe pass-through")?>
|
||||
</select>
|
||||
<input type="text" name="smPort1" value="<?=_var($disk,'smPort1')?>" class="option"><select name="smPort1" class="narrow option" disabled></select>
|
||||
<input type="text" name="smPort2" value="<?=_var($disk,'smPort2')?>" class="option"><select name="smPort2" class="narrow option" disabled></select>
|
||||
|
||||
@@ -364,6 +364,13 @@ _(Default SMART controller type)_:
|
||||
<?=mk_option(_var($var,'smType'), "-d cciss", "HP cciss")?>
|
||||
<?=mk_option(_var($var,'smType'), "-d marvell", "Marvell")?>
|
||||
<?=mk_option(_var($var,'smType'), "-d megaraid", "MegaRAID")?>
|
||||
<?=mk_option(_var($var,'smType'), "-d usbcypress", "Cypress ATACB")?>
|
||||
<?=mk_option(_var($var,'smType'), "-d usbjmicron", "JMicron ATA pass-through")?>
|
||||
<?=mk_option(_var($var,'smType'), "-d usbprolific", "Prolific ATA pass-through")?>
|
||||
<?=mk_option(_var($var,'smType'), "-d usbsunplus", "Sunplus ATA pass-through")?>
|
||||
<?=mk_option(_var($var,'smType'), "-d sntasmedia", "ASMedia NVMe pass-through")?>
|
||||
<?=mk_option(_var($var,'smType'), "-d sntjmicron", "JMicron NVMe pass-through")?>
|
||||
<?=mk_option(_var($var,'smType'), "-d sntrealtek", "Realtek NVMe pass-through")?>
|
||||
</select>
|
||||
|
||||
:disk_default_smart_controller_help:
|
||||
|
||||
@@ -5,8 +5,8 @@ Icon="icon-key"
|
||||
Tag="expeditedssl"
|
||||
---
|
||||
<?PHP
|
||||
/* Copyright 2005-2023, Lime Technology
|
||||
* Copyright 2012-2023, Bergware International.
|
||||
/* Copyright 2005-2024, Lime Technology
|
||||
* Copyright 2012-2024, Bergware International.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2,
|
||||
@@ -75,7 +75,7 @@ if ($cert1Present) {
|
||||
$cert1SelfSigned = ($cert1Subject == $cert1Issuer);
|
||||
}
|
||||
|
||||
// unraid.net, myunraid.net LE cert. could potentially be user provided as well
|
||||
// myunraid.net LE cert. could potentially be user provided as well
|
||||
$cert2File = "/boot/config/ssl/certs/certificate_bundle.pem";
|
||||
$cert2Present = file_exists("$cert2File");
|
||||
if ($cert2Present) {
|
||||
@@ -84,6 +84,8 @@ if ($cert2Present) {
|
||||
$cert2Expires = exec("/usr/bin/openssl x509 -in $cert2File -noout -text | sed -n -e 's/^.*Not After : //p'");
|
||||
$isWildcardCert = preg_match('/.*\.myunraid\.net$/', $cert2Subject);
|
||||
$subject2URL = $cert2Subject;
|
||||
$dnsValid = false;
|
||||
$dnsRebindingProtection = false;
|
||||
if ($isWildcardCert) {
|
||||
exec("openssl x509 -checkend 2592000 -noout -in $cert2File 2>/dev/null", $arrout, $retval_expired);
|
||||
if (!$addr) {
|
||||
@@ -119,8 +121,8 @@ $http_port = _var($var,'PORT','80') != '80' ? ":{$var['PORT']}" : '';
|
||||
$https_port = _var($var,'PORTSSL','443') != '443' ? ":{$var['PORTSSL']}" : '';
|
||||
$http_ip_url = "http://"._var($nginx,'NGINX_LANIP')."{$http_port}/";
|
||||
$https_ip_url = "https://"._var($nginx,'NGINX_LANIP')."{$https_port}/";
|
||||
$http_ip6_url = "http://"._var($nginx,'NGINX_LANIP6')."{$http_port}/";
|
||||
$https_ip6_url = "https://"._var($nginx,'NGINX_LANIP6')."{$https_port}/";
|
||||
$http_ip6_url = "http://["._var($nginx,'NGINX_LANIP6')."]{$http_port}/";
|
||||
$https_ip6_url = "https://["._var($nginx,'NGINX_LANIP6')."]{$https_port}/";
|
||||
$http_mdns_url = "http://"._var($nginx,'NGINX_LANMDNS')."{$http_port}/";
|
||||
$https_mdns_url = "https://"._var($nginx,'NGINX_LANMDNS')."{$https_port}/";
|
||||
$https_fqdn_url = "https://"._var($nginx,'NGINX_LANFQDN')."{$https_port}/";
|
||||
@@ -164,7 +166,6 @@ $cert_time_format = $display['date'].($display['date']!='%c' ? ', '.str_replac
|
||||
$provisionlabel = $isWildcardCert ? _('Renew') : _('Provision');
|
||||
$disabled_provision = $keyfile===false || ($isWildcardCert && $retval_expired===0) || !$addr ? 'disabled' : '';
|
||||
$disabled_provision_msg = !$addr ? _('Ensure the primary network card eth0 has an IP address.') : '';
|
||||
$disabled_updatedns = $keyfile!==false && $isWildcardCert ? '' : 'disabled';
|
||||
$disabled_delete = $cert2Present && $var['USE_SSL']!='auto' ? '' : 'disabled';
|
||||
$disabled_auto = $isWildcardCert && !$dnsRebindingProtection && $dnsValid ? '' : 'disabled';
|
||||
|
||||
@@ -189,23 +190,6 @@ function provisionHandler(event, form) { // provisions and renewals require bein
|
||||
if (event.submitter.value === 'Renew') return true; // always allow renewals
|
||||
};
|
||||
|
||||
function updateDNS(button) {
|
||||
$(button).prop("disabled", true).html("<i class='fa fa-circle-o-notch fa-spin fa-fw'></i>_(Update DNS)_");
|
||||
var failure = function(data) {
|
||||
var status = data.status;
|
||||
var obj = data.responseJSON;
|
||||
var msg = "_(Sorry, an error occurred updating unraid.net DNS records)_. _(The error is)_: "+obj.error+".";
|
||||
$(button).prop("disabled", false).html("_(Update DNS)_");
|
||||
swal({title:"_(Oops)_",text:msg,type:"error",html:true,confirmButtonText:"_(Ok)_"});
|
||||
};
|
||||
var success = function(data) {
|
||||
$(button).prop("disabled", false).html("_(Update DNS)_");
|
||||
<?$text = _('Your local IP address %s has been updated for unraid.net')?>
|
||||
swal({title:"",text:"<?=sprintf($text,$addr)?>",type:"success",html:true,confirmButtonText:"_(Ok)_"});
|
||||
};
|
||||
$.post("/webGui/include/UpdateDNS.php",success).fail(failure);
|
||||
}
|
||||
|
||||
function checkPorts(form) {
|
||||
var portsInUse = [<?=implode(',',$portsInUse)?>];
|
||||
var range = [], list = [], duplicates = [];
|
||||
@@ -359,12 +343,10 @@ _(Local access URLs)_:
|
||||
$n = 0;
|
||||
foreach($urls as $url) {
|
||||
$msg = "";
|
||||
$url0 = substr_count($url[0]??'',':')>3 ? preg_replace('#(://)(.+?)(:?\d*)/$#','$1[$2]$3/',$url[0]) : $url[0]; // IPv6 - IPv4 notation
|
||||
$url1 = substr_count($url[1]??'',':')>3 ? preg_replace('#(://)(.+?)(:?\d*)/$#','$1[$2]$3/',$url[1]) : $url[1]; // IPv6 - IPv4 notation
|
||||
if ($url[1]) $msg .= " "._("redirects to")." <a href='$url1'>$url1</a>";
|
||||
if ($url[1]) $msg .= " "._("redirects to")." <a href='$url[1]'>$url[1]</a>";
|
||||
if ($url[2]) $msg .= " "._("uses")." ".$url[2];
|
||||
if ($url[3]) $msg .= "<span class='warning'> <i class='fa fa-warning fa-fw'></i> "._("is a self-signed certificate, ignore the browser's warning and proceed to the GUI")."</span>";
|
||||
echo ($n ? "<dt> </dt><dd>" : ""),"<a href='$url0'>$url0</a>$msg",($n++ ? "</dd>" : "");
|
||||
echo ($n ? "<dt> </dt><dd>" : ""),"<a href='$url[0]'>$url[0]</a>$msg",($n++ ? "</dd>" : "");
|
||||
}?>
|
||||
|
||||
:mgmt_local_access_urls_help:
|
||||
@@ -431,7 +413,7 @@ _(CA-signed certificate file)_:
|
||||
|
||||
<?endif;?>
|
||||
|
||||
: <button type="submit" name="changePorts" value="Provision" <?=$disabled_provision?>><?=$provisionlabel?></button><button type="submit" name="changePorts" value="Delete" <?=$disabled_delete?> >_(Delete)_</button><!-- <button type="button" onclick="updateDNS(this)" <?=$disabled_updatedns?>>_(Update DNS)_</button> --><?=$disabled_provision_msg?>
|
||||
: <button type="submit" name="changePorts" value="Provision" <?=$disabled_provision?>><?=$provisionlabel?></button><button type="submit" name="changePorts" value="Delete" <?=$disabled_delete?> >_(Delete)_</button><?=$disabled_provision_msg?>
|
||||
|
||||
:mgmt_certificate_expiration_help:
|
||||
|
||||
|
||||
@@ -18,8 +18,7 @@ Tag="folder-o"
|
||||
<?
|
||||
$width = [166,300];
|
||||
function data_disks($disk) {
|
||||
global $pools;
|
||||
return (_var($disk,'type')=="Data" || (_var($disk,'type')=="Cache" && in_array(_var($disk,'name'),$pools))) && _var($disk,'status')=='DISK_OK';
|
||||
return in_array(_var($disk,'type'),['Data','Cache']) && array_key_exists('exportable',$disk) && _var($disk,'fsStatus')=='Mounted';
|
||||
}
|
||||
?>
|
||||
<script>
|
||||
|
||||
@@ -101,7 +101,7 @@ function textsave(module,remove = false) {
|
||||
if (data.modprobe == "") $('#text'+module).attr('hidden', true); else $('#text'+module).attr('rows', 3);
|
||||
if (data.supportpage == true) {
|
||||
if (data.support == true) {
|
||||
document.getElementById("link" + module).innerHTML = "<a href='" + data.supporturl + "'target='_blank'><i title='"+_("Support page")_+"' class='fa fa-phone-square'></i></a>";
|
||||
document.getElementById("link" + module).innerHTML = "<a href='" + data.supporturl + "'target='_blank'><i title='"+"_(Support page)_"+"' class='fa fa-phone-square'></i></a>";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,6 +108,15 @@ _(Local syslog folder)_:
|
||||
|
||||
:syslog_local_folder_help:
|
||||
|
||||
_(System identifier for logfile name)_:
|
||||
: <select name="server_filename">
|
||||
<?=mk_option($syslog['server_filename'], "syslog-%FROMHOST-IP%.log", _("IP Address"))?>
|
||||
<?=mk_option($syslog['server_filename'], "syslog-%HOSTNAME%.log", _("Hostname (from syslog message)"))?>
|
||||
<?=mk_option($syslog['server_filename'], "syslog-%FROMHOST%.log", _("Hostname (from DNS reverse lookup)"))?>
|
||||
</select>
|
||||
|
||||
:syslog_remote_system_identifier_help:
|
||||
|
||||
_(Local syslog rotation)_:
|
||||
: <select name="log_rotation" onchange="logOptions(this.value,'slow')">
|
||||
<?=mk_option(_var($syslog,'log_rotation'), "", _("Disabled"))?>
|
||||
@@ -146,7 +155,7 @@ _(Local syslog number of files)_:
|
||||
</div>
|
||||
|
||||
_(Remote syslog server)_:
|
||||
: <span class="span"><input type="text" name="remote_server" class="narrow" value="<?=_var($syslog,'remote_server')?>" maxlength="23" placeholder="_(name or ip address)_"></span>
|
||||
: <span class="span"><input type="text" name="remote_server" class="narrow" value="<?=_var($syslog,'remote_server')?>" maxlength="50" placeholder="_(name or ip address)_"></span>
|
||||
<select name="remote_protocol" class="narrow">
|
||||
<?=mk_option(_var($syslog,'remote_protocol'), "udp", _("UDP"))?>
|
||||
<?=mk_option(_var($syslog,'remote_protocol'), "tcp", _("TCP"))?>
|
||||
|
||||
@@ -30,6 +30,8 @@ $(function() {
|
||||
$globals = [];
|
||||
$names = ['_SERVER','devs','disks','sec','sec_nfs','shares','users','var'];
|
||||
foreach ($names as $name) $globals[$name] = $$name;
|
||||
// show outgoing proxy information, is in the environment but not a superglobal
|
||||
$globals['environment'] = ['http_proxy' => getenv('http_proxy'), 'no_proxy' => getenv('no_proxy')];
|
||||
echo "<pre class='up'>",htmlspecialchars(print_r($globals,true)),"</pre>";
|
||||
?>
|
||||
<input type="button" value="_(Done)_" onclick="done()">
|
||||
|
||||
@@ -1,121 +0,0 @@
|
||||
Menu="UNRAID-OS"
|
||||
Title="Wake On LAN"
|
||||
Icon="fa-bell"
|
||||
Tag="server"
|
||||
---
|
||||
<?PHP
|
||||
/* Copyright 2005-2023, Lime Technology
|
||||
* Copyright 2012-2023, Bergware International.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*/
|
||||
|
||||
if (count($_POST)) {
|
||||
$cfg = NULL ;
|
||||
if ($_POST['#apply'] == "_(Save)_") {
|
||||
foreach($_POST as $postkey=>$data) {
|
||||
if ($postkey=="#apply") continue;
|
||||
$keys = explode(";",$postkey);
|
||||
if (count($keys) >1) $update_file[$keys[1]][$keys[2]][$keys[0]]=$data;
|
||||
}
|
||||
|
||||
foreach($update_file as $type => $types) {
|
||||
foreach($types as $name => $details) {
|
||||
if ($details['user_mac'] == "") $details['user_mac'] = "None Defined";
|
||||
if ($details['user_mac'] == "None Defined" && ($details['enable'] == "enable" || $details['enable'] == "shutdown")) unset($update_file[$type][$name]) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
unset($_POST) ;
|
||||
file_put_contents("/boot/config/wol.json",json_encode($update_file));
|
||||
#echo '<meta http-equiv="refresh" content="0;url=/Tools">';
|
||||
echo '<meta http-equiv="refresh" content="0">';
|
||||
#unset($_SESSION['csrf_token']);
|
||||
|
||||
|
||||
|
||||
}
|
||||
?>
|
||||
<script src="/webGui/javascript/jquery.tablesorter.widgets.js"></script>
|
||||
|
||||
<script>
|
||||
function showWOL(options, init = false) {
|
||||
option = options;
|
||||
if (init) {
|
||||
$('#wolsearch').prop('disabled', true);
|
||||
$.post('/webGui/include/WOL.php',{table:'t1load',option:"all"},function(data){
|
||||
clearTimeout(timers.refresh);
|
||||
filter = [];
|
||||
$("#t1").trigger("destroy");
|
||||
$('#t1').html(data.html);
|
||||
$('#t1').tablesorter({
|
||||
sortList: [[0,0]],
|
||||
sortAppend: [[0,0]],
|
||||
widgets: ['stickyHeaders','filter','zebra'],
|
||||
widgetOptions: {
|
||||
// on black and white, offset is height of #menu
|
||||
// on azure and gray, offset is height of #header
|
||||
stickyHeaders_offset: ($('#menu').height() < 50) ? $('#menu').height() : $('#header').height(),
|
||||
filter_columnFilters: false,
|
||||
zebra: ["normal-row","alt-row"]
|
||||
}
|
||||
});
|
||||
$('div.spinner.fixed').hide('slow');
|
||||
$('#wolsearch').prop('disabled', false);
|
||||
$('#select').prop('disabled', false);
|
||||
$('#rebuild').prop('disabled', data.init);
|
||||
},"json");
|
||||
} else {
|
||||
filter = [];
|
||||
filterWOL();
|
||||
}
|
||||
}
|
||||
|
||||
function filterWOL() {
|
||||
var totalColumns = $('#t1')[0].config.columns;
|
||||
var filter = [];
|
||||
filter[totalColumns] = $('#wolsearch').val(); // this searches all columns
|
||||
$('#t1').trigger('search', [filter]);
|
||||
}
|
||||
|
||||
function showWOLupdate() {
|
||||
$('#rebuild').prop('disabled', true);
|
||||
$('#t1').html("");
|
||||
$('#wolsearch').prop('disabled', true);
|
||||
$('#select').prop('disabled', true);
|
||||
$('div.spinner.fixed').show('slow');
|
||||
$.post('/webGui/include/WOL.php',{table:'t1create',option:"all"},function(data){
|
||||
$('#rebuild').prop('disabled', false);
|
||||
showWOL("all",true);
|
||||
$('div.spinner.fixed').hide('slow');
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function maccreate(name) {
|
||||
|
||||
$.post('/webGui/include/WOL.php',{table:'macaddress'}, function( data ) {
|
||||
if (data.mac) {
|
||||
$('#'+name).val(data.mac);
|
||||
}
|
||||
},'json');
|
||||
}
|
||||
|
||||
showWOL("all",true);
|
||||
</script>
|
||||
|
||||
:WOL_intro_help:
|
||||
|
||||
<form autocomplete="off" onsubmit="return false;"><span><input class="t1 search" id="wolsearch" type="search" placeholder="Search..." onchange="filterWOL();"></span></form>
|
||||
<pre><form name="WOL" id="WOL" method="POST" class="js-confirm-leave" >
|
||||
<table name="t1"id='t1' class="t1 unraid tablesorter" >
|
||||
<tr><td><div class="spinner"></div></td></tr></table></pre><br>
|
||||
<input type="button" value="_(Done)_" onclick="done()">
|
||||
<input type="submit" name="#apply" id='#apply' value="_(Save)_" >
|
||||
</form>
|
||||
|
||||
@@ -1,102 +0,0 @@
|
||||
Menu="OtherSettings"
|
||||
Type="xmenu"
|
||||
Title="Wake on Lan Settings"
|
||||
Icon="fa-bell"
|
||||
Tag="share-alt"
|
||||
---
|
||||
<?PHP
|
||||
/* Copyright 2005-2023, Lime Technology
|
||||
* Copyright 2012-2023, Bergware International.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*/
|
||||
?>
|
||||
<?
|
||||
exec("ls --indicator-style=none /sys/class/net|grep -P '^eth[1-9][0-9]*$'",$ports);
|
||||
$disabled = _var($var,'fsState')!='Stopped' ? 'disabled' : '';
|
||||
$width = [166,300];
|
||||
$file = '/boot/config/wol.cfg';
|
||||
$current = parse_ini_file($file);
|
||||
if (!isset($current['LOGFILE'])) $current['LOGFILE'] = "syslog"
|
||||
?>
|
||||
<script>
|
||||
showStatus('pid','unraidwold');
|
||||
</script>
|
||||
<form markdown="1" name="WOLsettings" method="POST" action="/update.php" target="progressFrame" >
|
||||
<input type="hidden" name="#file" value="<?=$file;?>">
|
||||
<input type="hidden" name="#command" value="/webGui/scripts/WOL_action">
|
||||
<input type="hidden" name="#arg[1]" value="load">
|
||||
|
||||
_(Enable Wake on Lan)_:
|
||||
: <select name="WOLENABLED" >
|
||||
<?=mk_option($current['WOLENABLED'], "no", _('No'))?>
|
||||
<?=mk_option($current['WOLENABLED'], "yes", _('Yes'))?>
|
||||
</select>
|
||||
|
||||
:WOL_enable_help:
|
||||
|
||||
_(Enable Docker actions)_:
|
||||
|
||||
: <select name="RUNDOCKER" >
|
||||
<?=mk_option($current['RUNDOCKER'], "y", _('Yes'))?>
|
||||
<?=mk_option($current['RUNDOCKER'], "n", _('No'))?>
|
||||
</select>
|
||||
|
||||
:WOL_run_docker_help:
|
||||
|
||||
_(Enable LXC actions)_:
|
||||
: <select name="RUNLXC" >
|
||||
<?=mk_option($current['RUNLXC'], "y", _('Yes'))?>
|
||||
<?=mk_option($current['RUNLXC'], "n", _('No'))?>
|
||||
</select>
|
||||
|
||||
:WOL_run_LXC_help:
|
||||
|
||||
_(Enable VM actions)_:
|
||||
: <select name="RUNVM" >
|
||||
<?=mk_option($current['RUNVM'], "y", _('Yes'))?>
|
||||
<?=mk_option($current['RUNVM'], "n", _('No'))?>
|
||||
</select>
|
||||
|
||||
:WOL_run_VM_help:
|
||||
|
||||
_(Enable Shutdown actions)_:
|
||||
: <select name="RUNSHUT" >
|
||||
<?=mk_option($current['RUNSHUT'], "n", _('No'))?>
|
||||
<?=mk_option($current['RUNSHUT'], "y", _('Yes'))?>
|
||||
</select>
|
||||
|
||||
:WOL_run_shutdown_help:
|
||||
|
||||
_(Interface to listern on)_:
|
||||
: <select id="INTERFACE" name="INTERFACE" >
|
||||
<?=mk_option(_var($eth0,'INTERFACE'),'eth0','eth0','selected')?>
|
||||
<?foreach ($ports as $port):?>
|
||||
<?if (!locked('eth0',$port)) echo mk_option_check($current['INTERFACE'],$port,$port)?>
|
||||
<?endforeach;?>
|
||||
</select>
|
||||
|
||||
:WOL_interface_help:
|
||||
|
||||
_(Interface promiscuous mode)_:
|
||||
: <select id="IFMODE" name="IFMODE" >
|
||||
<?=mk_option($current['IFMODE'], "n", _('No'))?>
|
||||
<?=mk_option($current['IFMODE'], "y", _('Yes'))?>
|
||||
</select>
|
||||
|
||||
:WOL_promiscuous_mode_help:
|
||||
|
||||
_(Log file)_:
|
||||
: <input name="LOGFILE" class="narrow"type="text" value=<?=$current['LOGFILE']?>>
|
||||
|
||||
|
||||
:WOL_log_file_help:
|
||||
|
||||
|
||||
: <input type="submit" value="_(Apply)_" disabled><input type="button" value="_(Done)_" onclick="done()">
|
||||
</form>
|
||||
@@ -1,3 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
/usr/local/emhttp/plugins/dynamix/scripts/WOL_action load &
|
||||
@@ -1,3 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
/usr/local/emhttp/plugins/dynamix/include/script/WOL_action stop &
|
||||
@@ -68,6 +68,8 @@ if ($_POST['docker']) {
|
||||
}
|
||||
echo "\0";
|
||||
if ($_POST['vms']) {
|
||||
$vmusage = $_POST['vmusage'];
|
||||
$vmusagehtml = [];
|
||||
$user_prefs = '/boot/config/plugins/dynamix.vm.manager/userprefs.cfg';
|
||||
$vms = $lv->get_domains() ?: [];
|
||||
if (file_exists($user_prefs)) {
|
||||
@@ -78,6 +80,7 @@ if ($_POST['vms']) {
|
||||
natcasesort($vms);
|
||||
}
|
||||
echo "<tr title='' class='updated'><td>";
|
||||
$running = 0;
|
||||
foreach ($vms as $vm) {
|
||||
$res = $lv->get_domain_by_name($vm);
|
||||
$uuid = libvirt_domain_get_uuid_string($res);
|
||||
@@ -123,6 +126,7 @@ if ($_POST['vms']) {
|
||||
$shape = 'play';
|
||||
$status = 'started';
|
||||
$color = 'green-text';
|
||||
$running++;
|
||||
break;
|
||||
case 'paused':
|
||||
case 'pmsuspended':
|
||||
@@ -138,8 +142,30 @@ if ($_POST['vms']) {
|
||||
}
|
||||
$image = substr($icon,-4)=='.png' ? "<img src='$icon' class='img'>" : (substr($icon,0,5)=='icon-' ? "<i class='$icon img'></i>" : "<i class='fa fa-$icon img'></i>");
|
||||
echo "<span class='outer solid vms $status'><span id='vm-$uuid' $menu class='hand'>$image</span><span class='inner'>$vm<br><i class='fa fa-$shape $status $color'></i><span class='state'>"._($status)."</span></span></span>";
|
||||
if ($state == "running") {
|
||||
#Build VM Usage array.
|
||||
$menuusage = sprintf("onclick=\"addVMContext('%s','%s','%s','%s','%s','%s','%s','%s','%s','%s')\"", addslashes($vm), addslashes($uuid), addslashes($template), $state, addslashes($vmrcurl), strtoupper($vmrcprotocol), addslashes($log),addslashes($fstype), $vmrcconsole,true);
|
||||
$vmusagehtml[] = "<span class='outer solid vmsuse $status'><span id='vmusage-$uuid' $menuusage class='hand'>$image</span><span class='inner'>$vm<br><i class='fa fa-$shape $status $color'></i><span class='state'>"._($status)."</span></span>";
|
||||
$vmusagehtml[] = "<br><br><span id='vmmetrics-gcpu-".$uuid."'>"._("Loading")."....</span>";
|
||||
$vmusagehtml[] = "<br><span id='vmmetrics-hcpu-".$uuid."'>"._("Loading")."....</span>";
|
||||
$vmusagehtml[] = "<br><span id='vmmetrics-mem-".$uuid."'>"._("Loading")."....</span>";
|
||||
$vmusagehtml[] = "<br><span id='vmmetrics-disk-".$uuid."'>"._("Loading")."....</span>";
|
||||
$vmusagehtml[] = "<br><span id='vmmetrics-net-".$uuid."'>"._("Loading")."....</span>";
|
||||
$vmusagehtml[] = "</span>";
|
||||
}
|
||||
}
|
||||
$none = count($vms) ? _('No running virtual machines') : _('No virtual machines defined');
|
||||
echo "<span id='no_vms' style='display:none'>$none<br><br></span>";
|
||||
echo "</td></tr>";
|
||||
|
||||
echo "\0";
|
||||
echo "<tr title='' class='useupdated'><td>";
|
||||
if ($vmusage == "Y") {
|
||||
foreach ($vmusagehtml as $vmhtml) {
|
||||
echo $vmhtml;
|
||||
}
|
||||
if (!count($vmusagehtml)) echo "<span id='no_usagevms'><br> "._('No running virtual machines')."<br></span>";
|
||||
if ($running < 1 && count($vmusagehtml)) echo "<span id='no_usagevms'><br>". _('No running virtual machines')."<br></span>";
|
||||
echo "</td></tr>";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -291,4 +291,13 @@ function my_mkdir($dirname,$permissions = 0777,$recursive = false) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
function get_realvolume($path) {
|
||||
if (strpos($path,"/mnt/user/",0) === 0)
|
||||
$reallocation = trim(shell_exec("getfattr --absolute-names --only-values -n system.LOCATION ".escapeshellarg($path)." 2>/dev/null"));
|
||||
else {
|
||||
$realexplode = explode("/",str_replace("/mnt/","",$path));
|
||||
$reallocation = $realexplode[0];
|
||||
}
|
||||
return $reallocation;
|
||||
}
|
||||
?>
|
||||
|
||||
@@ -39,13 +39,13 @@ foreach ($files as $file) {
|
||||
$c = 0;
|
||||
foreach ($fields as $field) {
|
||||
if ($c==5) break;
|
||||
$text = $field ? explode('=',$field,2)[1] : "-";
|
||||
$text = $field ? (explode('=',$field,2)[1]??"") : "-";
|
||||
$tag = ($c<4) ? "" : " data='".str_replace(['alert','warning','normal'],['0','1','2'],$text)."'";
|
||||
echo (!$c++) ? "<tr>".str_replace('*',$text,$td_).date($dynamix['notify']['date'].' '.$dynamix['notify']['time'],$text)."$_td" : "<td$tag>"._($text)."</td>";
|
||||
}
|
||||
echo "<td><a href='#' onclick='$(this).hide();$.post(\"/webGui/include/DeleteLogFile.php\",{log:\"$archive\"},function(){archiveList();});return false' title=\""._('Delete notification')."\"><i class='fa fa-trash-o'></i></a></td></tr>";
|
||||
if ($extra) {
|
||||
$text = explode('=',$field,2)[1];
|
||||
$text = explode('=',$field,2)[1]??"";
|
||||
echo "<tr class='tablesorter-childRow row$row'><td colspan='4'>$text</td><td></td></tr><tr class='tablesorter-childRow row$row'><td colspan='5'></td></tr>";
|
||||
$row++;
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ case 't1load':
|
||||
} else {
|
||||
$supporturl = $module['supporturl'];
|
||||
$pluginname = $module['plugin'];
|
||||
$supporthtml = "<span id='link$modname'><a href='$supporturl' target='_blank'><i title='"._("Support page $pluginname")."' class='fa fa-phone-square'></i></a></span>";
|
||||
$supporthtml = "<span id='link$modname'><a href='$supporturl' target='_blank'><i title='"._("Support page")." $pluginname' class='fa fa-phone-square'></i></a></span>";
|
||||
}
|
||||
}
|
||||
if (!empty($module["version"])) $version = " (".$module["version"].")"; else $version = "";
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?PHP
|
||||
/* Copyright 2005-2023, Lime Technology
|
||||
* Copyright 2012-2023, Bergware International.
|
||||
/* Copyright 2005-2024, Lime Technology
|
||||
* Copyright 2012-2024, Bergware International.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2,
|
||||
@@ -12,353 +12,15 @@
|
||||
?>
|
||||
<?
|
||||
$docroot ??= ($_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp');
|
||||
require_once "$docroot/webGui/include/Helpers.php";
|
||||
|
||||
// add translations
|
||||
$_SERVER['REQUEST_URI'] = 'settings';
|
||||
require_once "$docroot/webGui/include/Translations.php";
|
||||
|
||||
function host_lookup_ip($host) {
|
||||
$result = @dns_get_record($host, DNS_A);
|
||||
$ip = $result ? _var($result[0],'ip') : '';
|
||||
return($ip);
|
||||
}
|
||||
function rebindDisabled() {
|
||||
global $isLegacyCert;
|
||||
$rebindtesturl = $isLegacyCert ? "rebindtest.unraid.net" : "rebindtest.myunraid.net";
|
||||
// DNS Rebind Protection - this checks the server but clients could still have issues
|
||||
$validResponse = ["192.168.42.42", "fd42"];
|
||||
$response = host_lookup_ip($rebindtesturl);
|
||||
return in_array(explode('::',$response)[0], $validResponse);
|
||||
}
|
||||
function format_port($port) {
|
||||
return ($port != 80 && $port != 443) ? ':'.$port : '';
|
||||
}
|
||||
function anonymize_host($host) {
|
||||
global $anon;
|
||||
if ($anon) {
|
||||
$host = preg_replace('/.*\.myunraid\.net/', '*.hash.myunraid.net', $host);
|
||||
$host = preg_replace('/.*\.unraid\.net/', 'hash.unraid.net', $host);
|
||||
}
|
||||
return $host;
|
||||
}
|
||||
function anonymize_ip($ip) {
|
||||
global $anon;
|
||||
if ($anon && filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE)) {
|
||||
$ip = "[redacted]";
|
||||
}
|
||||
return $ip;
|
||||
}
|
||||
function generate_internal_host($host, $ip) {
|
||||
if (strpos($host,'.myunraid.net') !== false) {
|
||||
$host = str_replace('*', str_replace('.', '-', $ip), $host);
|
||||
}
|
||||
return $host;
|
||||
}
|
||||
function generate_external_host($host, $ip) {
|
||||
if (strpos($host,'.myunraid.net') !== false) {
|
||||
$host = str_replace('*', str_replace('.', '-', $ip), $host);
|
||||
} elseif (strpos($host,'.unraid.net') !== false) {
|
||||
$host = "www.".$host;
|
||||
}
|
||||
return $host;
|
||||
}
|
||||
function verbose_output($httpcode, $result) {
|
||||
global $cli, $verbose, $anon, $plgversion, $post, $var, $isRegistered, $myservers, $reloadNginx, $nginx, $isLegacyCert;
|
||||
global $remoteaccess;
|
||||
global $icon_warn, $icon_ok;
|
||||
if (!$cli || !$verbose) return;
|
||||
|
||||
if ($anon) echo "(Output is anonymized, use '-vv' to see full details)".PHP_EOL;
|
||||
echo "Unraid OS "._var($var,'version','???').((strpos($plgversion, "base-") === false) ? " with My Servers plugin version {$plgversion}" : '').PHP_EOL;
|
||||
echo ($isRegistered) ? "{$icon_ok}Signed in to Unraid.net as {$myservers['remote']['username']}".PHP_EOL : "{$icon_warn}Not signed in to Unraid.net".PHP_EOL ;
|
||||
echo "Use SSL is "._var($nginx,'NGINX_USESSL','No').PHP_EOL;
|
||||
echo (rebindDisabled()) ? "{$icon_ok}Rebind protection is disabled" : "{$icon_warn}Rebind protection is enabled";
|
||||
echo " for ".($isLegacyCert ? "unraid.net" : "myunraid.net").PHP_EOL;
|
||||
if ($post) {
|
||||
$wanip = trim(@file_get_contents("https://wanip4.unraid.net/"));
|
||||
// check the data
|
||||
$certhostname = _var($nginx,'NGINX_CERTNAME');
|
||||
if ($certhostname) {
|
||||
// $certhostname is $nginx['NGINX_CERTNAME'] (certificate_bundle.pem)
|
||||
$certhostip = host_lookup_ip(generate_internal_host($certhostname, _var($post,'internalip')));
|
||||
$certhosterr = ($certhostip != _var($post,'internalip'));
|
||||
}
|
||||
if (_var($post,'internalhostname') != $certhostname) {
|
||||
// $post['internalhostname'] is $nginx['NGINX_LANMDNS'] (no cert, or Server_unraid_bundle.pem) || $nginx['NGINX_CERTNAME'] (certificate_bundle.pem)
|
||||
$internalhostip = host_lookup_ip(generate_internal_host(_var($post,'internalhostname'), _var($post,'internalip')));
|
||||
$internalhosterr = ($internalhostip != _var($post,'internalip'));
|
||||
}
|
||||
if (!empty($post['externalhostname'])) {
|
||||
// $post['externalhostname'] is $nginx['NGINX_CERTNAME'] (certificate_bundle.pem)
|
||||
$externalhostip = host_lookup_ip(generate_external_host($post['externalhostname'], $wanip));
|
||||
$externalhosterr = ($externalhostip != $wanip);
|
||||
}
|
||||
// anonymize data. no caclulations can be done with this data beyond this point.
|
||||
if ($anon) {
|
||||
if (!empty($certhostip)) $certhostip = anonymize_ip($certhostip);
|
||||
if (!empty($certhostname)) $certhostname = anonymize_host($certhostname);
|
||||
if (!empty($internalhostip)) $internalhostip = anonymize_ip($internalhostip);
|
||||
if (!empty($externalhostip)) $externalhostip = anonymize_ip($externalhostip);
|
||||
if (!empty($wanip)) $wanip = anonymize_ip($wanip);
|
||||
if (!empty($post['internalip'])) $post['internalip'] = anonymize_ip($post['internalip']);
|
||||
if (!empty($post['internalhostname'])) $post['internalhostname'] = anonymize_host($post['internalhostname']);
|
||||
if (!empty($post['externalhostname'])) $post['externalhostname'] = anonymize_host($post['externalhostname']);
|
||||
if (!empty($post['externalport'])) $post['externalport'] = "[redacted]";
|
||||
}
|
||||
// always anonymize the keyfile
|
||||
if (!empty($post['keyfile'])) $post['keyfile'] = "[redacted]";
|
||||
// output notes
|
||||
if (!empty($post['internalprotocol']) && !empty($post['internalhostname']) && !empty($post['internalport'])) {
|
||||
$localurl = $post['internalprotocol']."://".generate_internal_host($post['internalhostname'], _var($post,'internalip')).format_port($post['internalport']);
|
||||
echo 'Local Access url: '.$localurl.PHP_EOL;
|
||||
if ($internalhostip) {
|
||||
// $internalhostip will not be defined for .local domains, ok to skip
|
||||
echo ($internalhosterr) ? $icon_warn : $icon_ok;
|
||||
echo generate_internal_host($post['internalhostname'], _var($post,'internalip'))." resolves to {$internalhostip}";
|
||||
echo ($internalhosterr) ? ", it should resolve to "._var($post,'internalip') : "";
|
||||
echo PHP_EOL;
|
||||
}
|
||||
if ($certhostname) {
|
||||
echo ($certhosterr) ? $icon_warn : $icon_ok;
|
||||
echo generate_internal_host($certhostname, _var($post,'internalip')).' ';
|
||||
echo ($certhostip) ? "resolves to {$certhostip}" : "does not resolve to an IP address";
|
||||
echo ($certhosterr) ? ", it should resolve to "._var($post,'internalip') : "";
|
||||
echo PHP_EOL;
|
||||
}
|
||||
if ($remoteaccess == 'yes' && !empty($post['externalprotocol']) && !empty($post['externalhostname']) && !empty($post['externalport'])) {
|
||||
$remoteurl = $post['externalprotocol']."://".generate_external_host($post['externalhostname'], $wanip).format_port($post['externalport']);
|
||||
echo 'Remote Access url: '.$remoteurl.PHP_EOL;
|
||||
echo ($externalhosterr) ? $icon_warn : $icon_ok;
|
||||
echo generate_external_host($post['externalhostname'], $wanip).' ';
|
||||
echo ($externalhosterr) ? "does not resolve to an IP address" : "resolves to ".($externalhostip??'');
|
||||
echo PHP_EOL;
|
||||
}
|
||||
if ($reloadNginx) {
|
||||
echo "IP address changes were detected, nginx was reloaded".PHP_EOL;
|
||||
}
|
||||
}
|
||||
// output post data
|
||||
echo PHP_EOL.'Request:'.PHP_EOL;
|
||||
echo @json_encode($post, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT) . PHP_EOL;
|
||||
}
|
||||
if ($result) {
|
||||
echo "Response (HTTP $httpcode):".PHP_EOL;
|
||||
$mutatedResult = is_array($result) ? json_encode($result) : $result;
|
||||
echo @json_encode(@json_decode($mutatedResult, true), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT) . PHP_EOL;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @name response_complete
|
||||
* @param {HTTP Response Status Code} $httpcode https://developer.mozilla.org/en-US/docs/Web/HTTP/Status
|
||||
* @param {String|Array} $result - strings are assumed to be encoded JSON. Arrays will be encoded to JSON.
|
||||
* @param {String} $cli_success_msg
|
||||
*/
|
||||
function response_complete($httpcode, $result, $cli_success_msg='') {
|
||||
global $cli, $verbose;
|
||||
$mutatedResult = is_array($result) ? json_encode($result) : $result;
|
||||
if ($cli) {
|
||||
if ($verbose) verbose_output($httpcode, $result);
|
||||
$json = @json_decode($mutatedResult,true);
|
||||
if (!empty($json['error'])) {
|
||||
echo 'Error: '.$json['error'].PHP_EOL;
|
||||
exit(1);
|
||||
}
|
||||
exit($cli_success_msg.PHP_EOL);
|
||||
}
|
||||
header('Content-Type: application/json');
|
||||
http_response_code($httpcode);
|
||||
exit((string)$mutatedResult);
|
||||
}
|
||||
require_once "$docroot/webGui/include/Wrappers.php";
|
||||
|
||||
// This is a stub, does nothing but return success
|
||||
my_logger("This is a stub and should not be called", "UpdateDNS");
|
||||
$cli = php_sapi_name()=='cli';
|
||||
$verbose = $anon = false;
|
||||
if ($cli && ($argc > 1) && $argv[1] == "-v") {
|
||||
$verbose = true;
|
||||
$anon = true;
|
||||
}
|
||||
if ($cli && ($argc > 1) && $argv[1] == "-vv") {
|
||||
$verbose = true;
|
||||
}
|
||||
$var = (array)@parse_ini_file('/var/local/emhttp/var.ini');
|
||||
$nginx = (array)@parse_ini_file('/var/local/emhttp/nginx.ini');
|
||||
$is69 = version_compare(_var($var,'version'),"6.9.9","<");
|
||||
$reloadNginx = false;
|
||||
$dnserr = false;
|
||||
$icon_warn = "⚠️ ";
|
||||
$icon_ok = "✅ ";
|
||||
|
||||
$myservers_flash_cfg_path='/boot/config/plugins/dynamix.my.servers/myservers.cfg';
|
||||
$myservers = (array)@parse_ini_file($myservers_flash_cfg_path,true);
|
||||
// ensure some vars are defined here so we don't have to test them later
|
||||
if (empty($myservers['remote']['apikey'])) {
|
||||
$myservers['remote']['apikey'] = "";
|
||||
}
|
||||
if (empty($myservers['remote']['wanaccess'])) {
|
||||
$myservers['remote']['wanaccess'] = "no";
|
||||
}
|
||||
if (empty($myservers['remote']['wanport'])) {
|
||||
$myservers['remote']['wanport'] = 443;
|
||||
}
|
||||
// remoteaccess, externalport
|
||||
if ($cli) {
|
||||
$remoteaccess = empty($nginx['NGINX_WANFQDN']) ? 'no' : 'yes';
|
||||
$externalport = $myservers['remote']['wanport'];
|
||||
} else {
|
||||
$remoteaccess = _var($_POST,'remoteaccess','no');
|
||||
$externalport = intval(_var($_POST,'externalport',443));
|
||||
|
||||
if ($remoteaccess != 'yes') {
|
||||
$remoteaccess = 'no';
|
||||
}
|
||||
|
||||
if ($externalport < 1 || $externalport > 65535) {
|
||||
$externalport = 443;
|
||||
}
|
||||
|
||||
if ($myservers['remote']['wanaccess'] != $remoteaccess) {
|
||||
// update the wanaccess ini value
|
||||
$orig = file_exists($myservers_flash_cfg_path) ? parse_ini_file($myservers_flash_cfg_path,true) : [];
|
||||
if (!$orig) {
|
||||
$orig = ['remote' => $myservers['remote']];
|
||||
}
|
||||
$orig['remote']['wanaccess'] = $remoteaccess;
|
||||
$text = '';
|
||||
foreach ($orig as $section => $block) {
|
||||
$pairs = "";
|
||||
foreach ($block as $key => $value) if (strlen($value)) $pairs .= "$key=\"$value\"\n";
|
||||
if ($pairs) $text .= "[$section]\n".$pairs;
|
||||
}
|
||||
if ($text) file_put_contents($myservers_flash_cfg_path, $text);
|
||||
// need nginx reload
|
||||
$reloadNginx = true;
|
||||
}
|
||||
exit("success".PHP_EOL);
|
||||
}
|
||||
$isRegistered = !empty($myservers['remote']['username']);
|
||||
|
||||
// protocols, hostnames, ports
|
||||
$internalprotocol = 'http';
|
||||
$internalport = _var($nginx,'NGINX_PORT');
|
||||
$internalhostname = _var($nginx,'NGINX_LANMDNS');
|
||||
$externalprotocol = 'https';
|
||||
// keyserver will expand *.hash.myunraid.net or add www to hash.unraid.net as needed
|
||||
$externalhostname = _var($nginx,'NGINX_CERTNAME');
|
||||
$isLegacyCert = preg_match('/.*\.unraid\.net$/', _var($nginx,'NGINX_CERTNAME'));
|
||||
$isWildcardCert = preg_match('/.*\.myunraid\.net$/', _var($nginx,'NGINX_CERTNAME'));
|
||||
$internalip = _var($nginx,'NGINX_LANIP');
|
||||
|
||||
if (_var($nginx,'NGINX_USESSL')=='yes') {
|
||||
// When NGINX_USESSL is 'yes' in 6.9, it could be using either Server_unraid_bundle.pem or certificate_bundle.pem
|
||||
// When NGINX_USESSL is 'yes' in 6.10, it is is using Server_unraid_bundle.pem
|
||||
$internalprotocol = 'https';
|
||||
$internalport = _var($nginx,'NGINX_PORTSSL');
|
||||
if ($is69 && _var($nginx,'NGINX_CERTNAME')) {
|
||||
// this is from certificate_bundle.pem
|
||||
$internalhostname = _var($nginx,'NGINX_CERTNAME');
|
||||
}
|
||||
}
|
||||
if (_var($nginx,'NGINX_USESSL')=='auto') {
|
||||
// NGINX_USESSL cannot be 'auto' in 6.9, it is either 'yes' or 'no'
|
||||
// When NGINX_USESSL is 'auto' in 6.10, it is using certificate_bundle.pem
|
||||
$internalprotocol = 'https';
|
||||
$internalport = _var($nginx,'NGINX_PORTSSL');
|
||||
// keyserver will expand *.hash.myunraid.net as needed
|
||||
$internalhostname = _var($nginx,'NGINX_CERTNAME');
|
||||
}
|
||||
|
||||
// My Servers version
|
||||
$plgversion = file_exists("/var/log/plugins/dynamix.unraid.net.plg") ? trim(exec('/usr/local/sbin/plugin version /var/log/plugins/dynamix.unraid.net.plg 2>/dev/null'))
|
||||
: (file_exists("/var/log/plugins/dynamix.unraid.net.staging.plg") ? trim(exec('/usr/local/sbin/plugin version /var/log/plugins/dynamix.unraid.net.staging.plg 2>/dev/null'))
|
||||
: 'base-'._var($var,'version'));
|
||||
|
||||
// only proceed when when signed in or when legacy unraid.net SSL certificate exists
|
||||
if (!$isRegistered && !$isLegacyCert) {
|
||||
response_complete(406, ['error' => _('Nothing to do')]);
|
||||
}
|
||||
|
||||
// keyfile
|
||||
$keyfile = empty($var['regFILE']) ? false : @file_get_contents($var['regFILE']);
|
||||
if ($keyfile === false) {
|
||||
response_complete(406, ['error' => _('Registration key required')]);
|
||||
}
|
||||
$keyfile = @base64_encode($keyfile);
|
||||
|
||||
// build post array
|
||||
$post = [
|
||||
'keyfile' => $keyfile,
|
||||
'plgversion' => $plgversion
|
||||
];
|
||||
if ($isLegacyCert) {
|
||||
// sign in not required to maintain local ddns for unraid.net cert
|
||||
// enable local ddns regardless of use_ssl value
|
||||
$post['internalip'] = $internalip;
|
||||
// if host.unraid.net does not resolve to the internalip and DNS Rebind Protection is disabled, disable caching
|
||||
if (host_lookup_ip(generate_internal_host(_var($nginx,'NGINX_CERTNAME'), $post['internalip'])) != $post['internalip'] && rebindDisabled()) $dnserr = true;
|
||||
}
|
||||
if ($isRegistered) {
|
||||
// if signed in, send data needed to maintain My Servers Dashboard
|
||||
$post['internalhostname'] = $internalhostname;
|
||||
$post['internalport'] = $internalport;
|
||||
$post['internalprotocol'] = $internalprotocol;
|
||||
$post['remoteaccess'] = $remoteaccess;
|
||||
$post['servercomment'] = _var($var,'COMMENT');
|
||||
$post['servername'] = _var($var,'NAME');
|
||||
if ($isWildcardCert) {
|
||||
// keyserver needs the internalip to generate the local access url
|
||||
$post['internalip'] = $internalip;
|
||||
}
|
||||
if ($remoteaccess == 'yes') {
|
||||
// include wanip in the cache file so we can track if it changes
|
||||
$post['_wanip'] = trim(@file_get_contents("https://wanip4.unraid.net/"));
|
||||
$post['externalhostname'] = $externalhostname;
|
||||
$post['externalport'] = $externalport;
|
||||
$post['externalprotocol'] = $externalprotocol;
|
||||
// if wanip.hash.myunraid.net or www.hash.unraid.net does not resolve to the wanip, disable caching
|
||||
if (host_lookup_ip(generate_external_host($post['externalhostname'], $post['_wanip'])) != $post['_wanip']) $dnserr = true;
|
||||
}
|
||||
}
|
||||
|
||||
// if remoteaccess is enabled in 6.10.0-rc3+ and WANIP has changed since nginx started, reload nginx
|
||||
if (_var($post,'_wanip') != _var($nginx,'NGINX_WANIP') && version_compare(_var($var,'version'),"6.10.0-rc2",">")) $reloadNginx = true;
|
||||
// if remoteaccess is currently disabled (perhaps because a wanip was not available when nginx was started)
|
||||
// BUT the system is configured to have it enabled AND a wanip is now available
|
||||
// then reload nginx
|
||||
if ($remoteaccess == 'no' && _var($nginx,'NGINX_WANACCESS') == 'yes' && !empty(trim(@file_get_contents("https://wanip4.unraid.net/")))) $reloadNginx = true;
|
||||
if ($reloadNginx) {
|
||||
exec("/etc/rc.d/rc.nginx reload &>/dev/null");
|
||||
}
|
||||
|
||||
// maxage is 36 hours
|
||||
$maxage = 36*60*60;
|
||||
if ($dnserr || $verbose) $maxage = 0;
|
||||
$datafile = "/tmp/UpdateDNS.txt";
|
||||
$datafiletmp = "/tmp/UpdateDNS.txt.new";
|
||||
$dataprev = @file_get_contents($datafile) ?: '';
|
||||
$datanew = implode("\n",$post)."\n";
|
||||
if ($datanew == $dataprev && (time()-filemtime($datafile) < $maxage)) {
|
||||
response_complete(204, null, _('No change to report'));
|
||||
}
|
||||
file_put_contents($datafiletmp,$datanew);
|
||||
rename($datafiletmp, $datafile);
|
||||
|
||||
// do not submit the wanip, it will be captured from the submission if needed for remote access
|
||||
unset($post['_wanip']);
|
||||
|
||||
// report necessary server details to limetech for DNS updates
|
||||
$ch = curl_init('https://keys.lime-technology.com/account/server/register');
|
||||
curl_setopt($ch, CURLOPT_POST, 1);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
$result = curl_exec($ch);
|
||||
$httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
$error = curl_error($ch);
|
||||
curl_close($ch);
|
||||
|
||||
if ( ($result === false) || ($httpcode != "200") ) {
|
||||
// delete cache file to retry submission on next run
|
||||
@unlink($datafile);
|
||||
response_complete($httpcode ?? "500", ['error' => $error]);
|
||||
}
|
||||
|
||||
response_complete($httpcode, $result, _('success'));
|
||||
header('Content-Type: application/json');
|
||||
http_response_code(204);
|
||||
exit(0);
|
||||
?>
|
||||
|
||||
@@ -1,125 +0,0 @@
|
||||
<?PHP
|
||||
/* Copyright 2005-2023, Lime Technology
|
||||
* Copyright 2012-2023, Bergware International.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*/
|
||||
?>
|
||||
<?
|
||||
global $lv;
|
||||
$docroot ??= ($_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp');
|
||||
require_once "$docroot/webGui/include/Helpers.php";
|
||||
require_once "$docroot/webGui/include/SysDriversHelpers.php";
|
||||
require_once "$docroot/plugins/dynamix.plugin.manager/include/PluginHelpers.php";
|
||||
require_once "$docroot/plugins/dynamix.vm.manager/include/libvirt_helpers.php";
|
||||
// add translations
|
||||
$_SERVER['REQUEST_URI'] = 'tools';
|
||||
require_once "$docroot/webGui/include/Translations.php";
|
||||
require_once "$docroot/plugins/dynamix.docker.manager/include/DockerClient.php";
|
||||
require_once "$docroot/plugins/dynamix.vm.manager/include/libvirt.php";
|
||||
|
||||
function macbyte($val) {
|
||||
if ($val < 16)
|
||||
return '0'.dechex($val);
|
||||
|
||||
return dechex($val);
|
||||
}
|
||||
|
||||
$arrEntries = [];
|
||||
$vms = $lv->get_domains() ?:[];
|
||||
sort($vms,SORT_NATURAL);
|
||||
foreach($vms as $vm){
|
||||
$arrEntries['VM'][$vm]['interfaces'] = $lv->get_nic_info($vm);
|
||||
$arrEntries['VM'][$vm]['name'] = $vm;
|
||||
}
|
||||
|
||||
$DockerClient = new DockerClient();
|
||||
$containers = $DockerClient->getDockerJSON("/containers/json?all=1");
|
||||
foreach($containers as $ct)
|
||||
$arrEntries['Docker'][substr($ct["Names"][0],1)] = [
|
||||
'interfaces' => ['0 '=> ['mac' => isset($ct["NetworkSettings"]["Networks"]["bridge"]["MacAddress"]) ? $ct["NetworkSettings"]["Networks"]["bridge"]["MacAddress"] : ""]],
|
||||
'name' => substr($ct["Names"][0],1),
|
||||
];
|
||||
|
||||
$lxc = explode("\n",shell_exec("lxc-ls -1")) ;
|
||||
$lxcpath = trim(shell_exec("lxc-config lxc.lxcpath"));
|
||||
foreach ($lxc as $lxcname) {
|
||||
if ($lxcname == "") continue;
|
||||
$value = explode("=",shell_exec("cat $lxcpath/$lxcname/config | grep 'hwaddr'"));
|
||||
$arrEntries['LXC'][$lxcname]['interfaces'][0]['mac'] = trim($value[1]);
|
||||
$arrEntries['LXC'][$lxcname]['name'] = $lxcname;
|
||||
}
|
||||
|
||||
if (is_file("/boot/config/wol.json")) $user_mac = json_decode(file_get_contents("/boot/config/wol.json"),true); else $user_mac = [];
|
||||
|
||||
foreach($arrEntries as $key => $data) {
|
||||
$type=$key;
|
||||
foreach($data as $data2){
|
||||
$name=$data2['name'];
|
||||
if (isset($user_mac[$type][$name])) {
|
||||
$name=$name;
|
||||
$arrEntries[$type][$name]['enable'] = $user_mac[$type][$name]['enable'];
|
||||
$arrEntries[$type][$name]['user_mac'] = strtolower($user_mac[$type][$name]['user_mac']);
|
||||
} else {
|
||||
$arrEntries[$type][$name]['enable'] = 'enable';
|
||||
$arrEntries[$type][$name]['user_mac'] = 'None Defined';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch ($_POST['table']) {
|
||||
|
||||
case 't1load':
|
||||
$arrMacs = $arrEntries;
|
||||
$html = "<thead><tr><th>"._('Service')."</th><th>"._('Name')."</th><th>"._('Mac Address')."</th><th>"._('Enabled')."</th><th>"._('User Mac Address')."</th></tr></thead>";
|
||||
$html .= "<tbody>";
|
||||
ksort($arrMacs);
|
||||
foreach($arrMacs as $systype => $m) {
|
||||
foreach($m as $macaddr) {
|
||||
if ($systype == "") continue;
|
||||
|
||||
$html .= "<tr id='row$systype'>";
|
||||
$macs = "";
|
||||
foreach($macaddr['interfaces'] as $intdetail)
|
||||
{
|
||||
$macs .= " {$intdetail['mac']}" ;
|
||||
}
|
||||
$html .= "<td>$systype</td>";
|
||||
$selecttypename="enable;".$systype.";".$macaddr['name'];
|
||||
$mactypename=htmlspecialchars("user_mac;".$systype.";".$macaddr['name']);
|
||||
$mactypeid=htmlspecialchars("user_mac".$systype."".$macaddr['name']);
|
||||
$user_mac_str = '<input type="text" name="'.$mactypename.'" id="'.$mactypeid.'" class="narrow" value="'.htmlspecialchars($macaddr['user_mac']).'" title="'._("random mac, you can supply your own").'" /><a><i onclick="maccreate(\''.$mactypeid.'\')" class="fa fa-refresh mac_generate" title="re-generate random mac address"></i></a>';
|
||||
$html .= "<td>{$macaddr['name']}</td><td id=\"status$systype\">$macs</td><td>";
|
||||
$html .="<select name='$selecttypename' class='audio narrow'>";
|
||||
$html .= mk_option($macaddr["enable"] , "disable", _("Disabled"));
|
||||
$html .= mk_option($macaddr["enable"] , "enable", _("Enabled"));
|
||||
$html .= mk_option($macaddr["enable"] , "shutdown", _("Enabled and Shutdown"));
|
||||
$html .= "</select></td><td>".$user_mac_str."</td></tr>";
|
||||
$text = "";
|
||||
}
|
||||
}
|
||||
if (count($arrMacs) < 1) {
|
||||
$html .= "<tr id='row'>";
|
||||
$html .= "<td></td><td></td><td>"._("No Entries")."</td><td></td><td></td></tr>";
|
||||
}
|
||||
$html .= "</tbody>";
|
||||
|
||||
$rtn = array();
|
||||
$rtn['html'] = $html;
|
||||
echo json_encode($rtn);
|
||||
break;
|
||||
|
||||
case "macaddress":
|
||||
$seed = 1;
|
||||
$prefix = '62:00:00';
|
||||
$prefix .=':'.macbyte(($seed * rand()) % 256).':'.macbyte(($seed * rand()) % 256).':'.macbyte(($seed * rand()) % 256);
|
||||
echo json_encode(['mac' => $prefix]);
|
||||
break;
|
||||
|
||||
}
|
||||
?>
|
||||
@@ -1,180 +0,0 @@
|
||||
#!/usr/bin/php
|
||||
<?php
|
||||
|
||||
|
||||
$docroot = $docroot ?? $_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp';
|
||||
require_once "$docroot/webGui/include/Helpers.php";
|
||||
require_once "$docroot/webGui/include/Custom.php";
|
||||
require_once "$docroot/plugins/dynamix.vm.manager/include/libvirt_helpers.php";
|
||||
require_once "$docroot/plugins/dynamix.vm.manager/include/libvirt.php";
|
||||
require_once "$docroot/plugins/dynamix.plugin.manager/include/PluginHelpers.php";
|
||||
require_once "$docroot/plugins/dynamix.docker.manager/include/DockerClient.php";
|
||||
|
||||
function getContainerStats($container, $option) {
|
||||
exec("lxc-info " . $container, $content);
|
||||
foreach($content as $index => $string) {
|
||||
if (strpos($string, $option) !== FALSE)
|
||||
return trim(explode(':', $string)[1]);
|
||||
}
|
||||
}
|
||||
|
||||
$mac = strtolower($argv[1]);
|
||||
|
||||
$libvirtd_running = is_file('/var/run/libvirt/libvirtd.pid') ;
|
||||
$dockerd_running = is_file('/var/run/dockerd.pid');
|
||||
$lxc_ls_exist = is_file('/usr/bin/lxc-ls');
|
||||
#$RUNDOCKER = $RUNLXC = $RUNVM = true;
|
||||
extract(parse_ini_file("/boot/config/wol.cfg")) ;
|
||||
if (!isset($RUNLXC)) $RUNLXC = "y";
|
||||
if (!isset($RUNVM)) $RUNVM = "y";
|
||||
if (!isset($RUNDocker)) $RUNDocker = "y";
|
||||
if (!isset($RUNSHUT)) $RUNSHUT = "n";
|
||||
|
||||
$arrEntries = [] ;
|
||||
if ($libvirtd_running && $RUNVM == "y") {
|
||||
$vms = $lv->get_domains();
|
||||
sort($vms,SORT_NATURAL);
|
||||
foreach($vms as $vm){
|
||||
$arrEntries['VM'][$vm]['interfaces'] = $lv->get_nic_info($vm);
|
||||
$arrEntries['VM'][$vm]['name'] = $vm;
|
||||
}
|
||||
}
|
||||
if ($dockerd_running && $RUNDOCKER == "y") {
|
||||
$DockerClient = new DockerClient();
|
||||
$containers = $DockerClient->getDockerJSON("/containers/json?all=1");
|
||||
foreach($containers as $container)
|
||||
$arrEntries['Docker'][ substr($container["Names"][0],1) ] = [
|
||||
'interfaces' => ['0' => ['mac' => isset($container["NetworkSettings"]["Networks"]["bridge"]["MacAddress"]) ? $container["NetworkSettings"]["Networks"]["bridge"]["MacAddress"]:""]],
|
||||
'name' => substr($container["Names"][0],1),
|
||||
'state' => $container["State"],
|
||||
];
|
||||
}
|
||||
|
||||
if ($lxc_ls_exist && $RUNLXC == "y") {
|
||||
$lxc = explode("\n",shell_exec("lxc-ls -1")) ;
|
||||
$lxcpath = trim(shell_exec("lxc-config lxc.lxcpath"));
|
||||
foreach ($lxc as $lxcname) {
|
||||
if ($lxcname == "") continue;
|
||||
$values = explode("=",shell_exec("cat $lxcpath/$lxcname/config | grep 'hwaddr'"));
|
||||
$arrEntries['LXC'][$lxcname]['interfaces'][0]['mac'] = trim($values[1]);
|
||||
$arrEntries['LXC'][$lxcname]['name'] = $lxcname;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_file("/boot/config/wol.json")) $user_mac = json_decode(file_get_contents("/boot/config/wol.json"),true); else $user_mac = [];
|
||||
|
||||
foreach($arrEntries as $typekey => $typedata)
|
||||
{
|
||||
foreach($typedata as $typeEntry){
|
||||
$name=$typeEntry['name'];
|
||||
if (isset($user_mac[$typekey][$name])) {
|
||||
|
||||
$name=$name;
|
||||
|
||||
$arrEntries[$typekey][$name]['enable'] = $user_mac[$typekey][$name]['enable'];
|
||||
$arrEntries[$typekey][$name]['user_mac'] = strtolower($user_mac[$typekey][$name]['user_mac']);
|
||||
|
||||
} else {
|
||||
$arrEntries[$typekey][$name]['enable'] = "enable";
|
||||
$arrEntries[$typekey][$name]['user_mac'] = 'None Defined';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$mac_list=[];
|
||||
foreach($arrEntries as $type => $detail)
|
||||
{
|
||||
foreach($detail as $name => $entryDetail)
|
||||
{
|
||||
foreach($entryDetail['interfaces'] as $interfaces)
|
||||
{
|
||||
$interfaces['mac'] = strtolower($interfaces['mac']);
|
||||
if($interfaces['mac'] == "" && $entryDetail['user_mac'] == "None Defined") continue;
|
||||
if (isset($entryDetail['state'])) $state = $entryDetail['state']; else $state = "";
|
||||
if (isset($entryDetail['enable']) && !$entryDetail['enable'] ) $enable = false; else $enable = true;
|
||||
if ($entryDetail['user_mac'] != "None Defined") {
|
||||
$mac_list[$entryDetail['user_mac']] = [
|
||||
'type' => $type,
|
||||
'name' => $name,
|
||||
'state' => $state,
|
||||
'enable' => $entryDetail['enable'],
|
||||
];
|
||||
}
|
||||
if ($interfaces['mac'] != "") {
|
||||
$mac_list[$interfaces['mac']] = [
|
||||
'type' => $type,
|
||||
'name' => $name,
|
||||
'state' => $state,
|
||||
'enable' => $entryDetail['enable'],
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
$found = array_key_exists($mac,$mac_list);
|
||||
|
||||
|
||||
if ($found && $mac_list[$mac]['enable'] != "disable") {
|
||||
echo _("Found"). " " . $mac . " " .$mac_list[$mac]['type'] . " " . $mac_list[$mac]['name'];
|
||||
switch ($mac_list[$mac]['type']) {
|
||||
|
||||
case "VM":
|
||||
if ($libvirtd_running && $RUNVM == "y") {
|
||||
$res = $lv->get_domain_by_name($mac_list[$mac]['name']);
|
||||
$dom = $lv->domain_get_info($res);
|
||||
$state = $lv->domain_state_translate($dom['state']);
|
||||
switch ($state) {
|
||||
case 'running':
|
||||
if ($RUNSHUT == "y" && $mac_list[$mac]['enable'] == "shutdown") $lv->domain_shutdown("{$mac_list[$mac]['name']}");
|
||||
break;
|
||||
case 'paused':
|
||||
case 'pmsuspended':
|
||||
$lv->domain_resume("{$mac_list[$mac]['name']}");
|
||||
break;
|
||||
default:
|
||||
$lv->domain_start("{$mac_list[$mac]['name']}");
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "LXC":
|
||||
if ($lxc_ls_exist && $RUNLXC == "y") {
|
||||
$state = getContainerStats($mac_list[$mac]['name'], "State");
|
||||
switch ($state) {
|
||||
case 'RUNNING':
|
||||
if ($RUNSHUT == "y" && $mac_list[$mac]['enable'] == "shutdown") shell_exec("lxc-stop {$mac_list[$mac]['name']}");
|
||||
break;
|
||||
case 'FROZEN':
|
||||
shell_exec("lxc-unfreeze {$mac_list[$mac]['name']}");
|
||||
break;
|
||||
default:
|
||||
shell_exec("lxc-start {$mac_list[$mac]['name']}");
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "Docker":
|
||||
if ($dockerd_running && $RUNDOCKER == "y") {
|
||||
|
||||
switch ($mac_list[$mac]['state']) {
|
||||
case "running":
|
||||
if ($RUNSHUT == "y" && $mac_list[$mac]['enable'] == "shutdown") shell_exec("docker stop {$mac_list[$mac]['name']}");
|
||||
break;
|
||||
case "exited":
|
||||
case "created":
|
||||
shell_exec("docker start {$mac_list[$mac]['name']}");
|
||||
break;
|
||||
case "paused":
|
||||
shell_exec("docker unpause {$mac_list[$mac]['name']}");
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if ($mac_list[$mac]['enable'] == "disable") echo $mac . " " . _(" has not been actioned as set to disabled");
|
||||
else echo _("Not Found"). " " . $mac . " " . _("ignoring or Maybe actions disabled for type(Docker/VM/LXC)");
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -149,4 +149,56 @@ function my_date($fmt, $time) {
|
||||
function my_logger($message, $logger='webgui') {
|
||||
exec('logger -t '.escapeshellarg($logger).' -- '.escapeshellarg($message));
|
||||
}
|
||||
// Original PHP code by Chirp Internet: www.chirpinternet.eu
|
||||
// Please acknowledge use of this code by including this header.
|
||||
// https://www.the-art-of-web.com/php/http-get-contents/
|
||||
// Modified for Unraid
|
||||
/**
|
||||
* Fetches URL and returns content
|
||||
* @param string $url The URL to fetch
|
||||
* @param array $opts Array of options to pass to curl_setopt()
|
||||
* @param array $getinfo Empty array passed by reference, will contain results of curl_getinfo and curl_error
|
||||
* @return string|false $out The fetched content
|
||||
*/
|
||||
function http_get_contents(string $url, array $opts = [], array &$getinfo = NULL) {
|
||||
$ch = curl_init();
|
||||
if(isset($getinfo)) {
|
||||
curl_setopt($ch, CURLINFO_HEADER_OUT, TRUE);
|
||||
}
|
||||
curl_setopt($ch, CURLOPT_URL, $url);
|
||||
curl_setopt($ch, CURLOPT_FRESH_CONNECT, true);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 15);
|
||||
curl_setopt($ch, CURLOPT_TIMEOUT, 45);
|
||||
curl_setopt($ch, CURLOPT_ENCODING, "");
|
||||
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
|
||||
curl_setopt($ch, CURLOPT_REFERER, "");
|
||||
curl_setopt($ch, CURLOPT_FAILONERROR, true);
|
||||
if(is_array($opts) && $opts) {
|
||||
foreach($opts as $key => $val) {
|
||||
curl_setopt($ch, $key, $val);
|
||||
}
|
||||
}
|
||||
$out = curl_exec($ch);
|
||||
if(isset($getinfo)) {
|
||||
$getinfo = curl_getinfo($ch);
|
||||
}
|
||||
if (curl_errno($ch)) {
|
||||
$msg = curl_error($ch) . " {$url}";
|
||||
if(isset($getinfo)) {
|
||||
$getinfo['error'] = $msg;
|
||||
}
|
||||
my_logger($msg, "http_get_contents");
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
/**
|
||||
* Detect network connectivity via Network Connectivity Status Indicator
|
||||
* @return bool
|
||||
*/
|
||||
function check_network_connectivity(): bool {
|
||||
$url = 'http://www.msftncsi.com/ncsi.txt';
|
||||
$out = http_get_contents($url);
|
||||
return ($out=="Microsoft NCSI");
|
||||
}
|
||||
?>
|
||||
|
||||
@@ -39,4 +39,8 @@ if ($_SERVER['SCRIPT_NAME'] != '/login.php' && $_SERVER['SCRIPT_NAME'] != '/auth
|
||||
if ($var['csrf_token'] != $_POST['csrf_token']) csrf_terminate("wrong");
|
||||
unset($_POST['csrf_token']);
|
||||
}
|
||||
$proxy_cfg = (array)@parse_ini_file('/var/local/emhttp/proxy.ini',true);
|
||||
putenv('http_proxy='.((array_key_exists('http_proxy', $proxy_cfg)) ? $proxy_cfg['http_proxy'] : ''));
|
||||
putenv('https_proxy='.((array_key_exists('https_proxy', $proxy_cfg)) ? $proxy_cfg['https_proxy'] : ''));
|
||||
putenv('no_proxy='.((array_key_exists('http_proxy', $proxy_cfg)) ? $proxy_cfg['no_proxy'] : ''));
|
||||
?>
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
<?
|
||||
$docroot ??= ($_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp');
|
||||
require_once "$docroot/webGui/include/Helpers.php";
|
||||
require_once "$docroot/webGui/include/Wrappers.php";
|
||||
|
||||
// add translations
|
||||
$_SERVER['REQUEST_URI'] = 'settings';
|
||||
@@ -425,11 +426,10 @@ case 'public':
|
||||
$ip = _var($_POST,'#ip');
|
||||
$v4 = _var($_POST,'#prot')!='6';
|
||||
$v6 = _var($_POST,'#prot')!='';
|
||||
$context = stream_context_create(['https'=>['timeout'=>12]]);
|
||||
$int_ipv4 = $v4 ? (preg_match("/^$validIP4$/",$ip) ? $ip : (@dns_get_record($ip,DNS_A)[0]['ip'] ?: '')) : '';
|
||||
$ext_ipv4 = $v4 ? (@file_get_contents('https://wanip4.unraid.net',false,$context) ?: '') : '';
|
||||
$ext_ipv4 = $v4 ? (http_get_contents('https://wanip4.unraid.net') ?: '') : '';
|
||||
$int_ipv6 = $v6 ? (preg_match("/^$validIP6$/",$ip) ? $ip : (@dns_get_record($ip,DNS_AAAA)[0]['ipv6'] ?: '')) : '';
|
||||
$ext_ipv6 = $v6 ? (@file_get_contents('https://wanip6.unraid.net',false,$context) ?: '') : '';
|
||||
$ext_ipv6 = $v6 ? (http_get_contents('https://wanip6.unraid.net') ?: '') : '';
|
||||
echo "$int_ipv4;$ext_ipv4;$int_ipv6;$ext_ipv6";
|
||||
break;
|
||||
case 'addtunnel':
|
||||
|
||||
@@ -78,7 +78,7 @@ function device_info(&$disk,$online) {
|
||||
$help .= "<br>"._("Click to spin $action device");
|
||||
}
|
||||
$status = "<a class='info'><i ".($ctrl?"id='dev-$named' ":"")."class='fa fa-$orb orb $color-orb'$ctrl></i><span>$help</span></a>";
|
||||
$link = (($parity || $data || $pool) && !str_contains($disk_status,'_NP')) || $name=='flash' || in_array($name,$pools) || $type=='New'
|
||||
$link = (($parity || $data || $pool) && $disk_status!='DISK_NP') || $name=='flash' || in_array($name,$pools) || $type=='New'
|
||||
? "<a href=\"".htmlspecialchars("/Main/Settings/$source?name=$name")."\">$fancy</a>"
|
||||
: $fancy;
|
||||
return $view.$status.$link;
|
||||
|
||||
@@ -20,10 +20,12 @@ require_once "$docroot/webGui/include/publish.php";
|
||||
|
||||
while (true) {
|
||||
$echo = shell_exec("$notify get");
|
||||
$md5_new = md5($echo,true);
|
||||
if ($md5_new !== $md5_old) {
|
||||
publish('notify', $echo);
|
||||
$md5_old = $md5_new;
|
||||
if ( $echo ) {
|
||||
$md5_new = md5($echo,true);
|
||||
if ($md5_new !== $md5_old) {
|
||||
publish('notify', $echo);
|
||||
$md5_old = $md5_new;
|
||||
}
|
||||
}
|
||||
sleep(3);
|
||||
}
|
||||
|
||||
91
emhttp/plugins/dynamix/nchan/vm_dashusage
Executable file
91
emhttp/plugins/dynamix/nchan/vm_dashusage
Executable file
@@ -0,0 +1,91 @@
|
||||
#!/usr/bin/php -q
|
||||
<?PHP
|
||||
/* Copyright 2005-2024, Lime Technology
|
||||
* Copyright 2024-2024, Simon Fairweather.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*/
|
||||
?>
|
||||
<?
|
||||
$docroot = '/usr/local/emhttp';
|
||||
$varroot = '/var/local/emhttp';
|
||||
$md5_old = -1;
|
||||
|
||||
require_once "$docroot/webGui/include/Helpers.php";
|
||||
require_once "$docroot/webGui/include/publish.php";
|
||||
require_once "$docroot/plugins/dynamix.vm.manager/include/libvirt_helpers.php";
|
||||
global $vmusagestats;
|
||||
exec("/etc/rc.d/rc.libvirt status >/dev/null",$dummy,$libvirtd);
|
||||
$libvirtd = $libvirtd==0;
|
||||
if (!$libvirtd) return;
|
||||
|
||||
extract(parse_plugin_cfg('dynamix',true));
|
||||
get_vm_usage_stats();
|
||||
sleep(1);
|
||||
|
||||
// add translations
|
||||
$_SERVER['REQUEST_URI'] = 'dashboard';
|
||||
$login_locale = _var($display,'locale');
|
||||
require_once "$docroot/webGui/include/Translations.php";
|
||||
|
||||
// remember current language
|
||||
$locale_init = $locale;
|
||||
function update_translation($locale) {
|
||||
global $docroot,$language;
|
||||
$language = [];
|
||||
if ($locale) {
|
||||
$text = "$docroot/languages/$locale/translations.txt";
|
||||
if (file_exists($text)) {
|
||||
$store = "$docroot/languages/$locale/translations.dot";
|
||||
if (!file_exists($store)) file_put_contents($store,serialize(parse_lang_file($text)));
|
||||
$language = unserialize(file_get_contents($store));
|
||||
}
|
||||
$text = "$docroot/languages/$locale/dashboard.txt";
|
||||
if (file_exists($text)) {
|
||||
$store = "$docroot/languages/$locale/dashboard.dot";
|
||||
if (!file_exists($store)) file_put_contents($store,serialize(parse_lang_file($text)));
|
||||
$language = array_merge($language,unserialize(file_get_contents($store)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$domain_cfgfile = "/boot/config/domain.cfg";
|
||||
$domain_cfg = parse_ini_file($domain_cfgfile);
|
||||
if (isset($domain_cfg['USAGE']) && $domain_cfg['USAGE'] != 'Y' ) return;
|
||||
if (!isset($domain_cfg['USAGETIMER'])) $timer = 3 ; else $timer = $domain_cfg['USAGETIMER'];
|
||||
|
||||
while (true) {
|
||||
extract(parse_plugin_cfg('dynamix',true));
|
||||
if (_var($display,'locale') != $locale_init) {
|
||||
$locale_init = _var($display,'locale');
|
||||
update_translation($locale_init);
|
||||
}
|
||||
|
||||
get_vm_usage_stats();
|
||||
$echo = [];
|
||||
foreach ($vmusagestats as $vm => $vmdata) {
|
||||
|
||||
if ($vmdata['state'] == 1) {
|
||||
$vmencode = str_replace(" "," ",$vm);
|
||||
$vmencode = $lv->domain_get_uuid($vm);
|
||||
$echo[$vmencode ]['gcpu'] = "<span class='advanced'>"._("Guest CPU").": <span class='cpug-".$vm."'>".$vmdata['cpuguest']."%</span><div class='usage-disk mm'><span id='cpug-".$vm."' style='width:".$vmdata['cpuguest']."%;'></span><span></span></div></span>";
|
||||
$echo[$vmencode ]['hcpu'] = "<span class='advanced'>"._("Host CPU").": <span class='cpug-".$vm."'>".$vmdata['cpuhost']."%</span><div class='usage-disk mm'><span id='cpug-".$vm."' style='width:".$vmdata['cpuhost']."%;'></span><span></span></div></span>";
|
||||
$echo[$vmencode ]['mem'] .= "<span>Mem: ".my_scale($vmdata['mem'],$unit)."$unit / ".my_scale($vmdata['maxmem'],$unit)."$unit</span>";
|
||||
$echo[$vmencode ]['disk'] .= "<span>Disk: "._("Rd").": ".my_scale($vmdata['rdrate'],$unit)."$unit/s "._("Wr").": ".my_scale($vmdata['wrrate'],$unit)."$unit/s</span>";
|
||||
$echo[$vmencode ]['net'] .= "<span>Net: "._("RX").": ".my_scale($vmdata['rxrate'],$unit)."$unit/s "._("TX").": ".my_scale($vmdata['txrate'],$unit)."$unit/s</span>";
|
||||
}
|
||||
}
|
||||
|
||||
$echo = json_encode($echo);
|
||||
$md5_new = md5($echo,true);
|
||||
if ($md5_new !== $md5_old) {
|
||||
$md5_old = publish('vm_dashusage',$echo)!==false ? $md5_new : -1;
|
||||
}
|
||||
sleep($timer);
|
||||
}
|
||||
?>
|
||||
@@ -1,93 +0,0 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# script: WOL_action
|
||||
#
|
||||
# Startup script for unraidwold
|
||||
#
|
||||
# Simon Fairweather - Initial Script October 2023
|
||||
|
||||
DAEMON="unraidwold"
|
||||
BINARY="/usr/local/bin/unraidwold"
|
||||
|
||||
# run & log functions
|
||||
. /etc/rc.d/rc.runlog
|
||||
. /boot/config/wol.cfg
|
||||
|
||||
unraidwold_running(){
|
||||
sleep 0.1
|
||||
ps axc | grep -q ' unraidwold'
|
||||
}
|
||||
|
||||
unraidwold_start(){
|
||||
log "Starting $DAEMON..."
|
||||
local REPLY
|
||||
if unraidwold_running; then
|
||||
REPLY="Already started"
|
||||
else
|
||||
nohup $BINARY $1 $2 $3 $4 $5 $6 > /dev/null &
|
||||
fi
|
||||
log "$DAEMON... $REPLY."
|
||||
}
|
||||
|
||||
unraidwold_stop(){
|
||||
log "Stopping $DAEMON..."
|
||||
local REPLY
|
||||
if ! unraidwold_running; then
|
||||
REPLY="Already stopped"
|
||||
else
|
||||
killall -TERM $DAEMON
|
||||
if ! unraidwold_running; then REPLY="Stopped"; else REPLY="Failed"; fi
|
||||
fi
|
||||
log "$DAEMON... $REPLY."
|
||||
}
|
||||
|
||||
unraidwold_status(){
|
||||
if unraidwold_running; then
|
||||
echo "$DAEMON is currently running."
|
||||
else
|
||||
echo "$DAEMON is not running."
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
unraidwold_load()
|
||||
{
|
||||
if unraidwold_running; then
|
||||
unraidwold_stop
|
||||
fi
|
||||
sleep 1
|
||||
if [ "$WOLENABLED" == "yes" ]; then
|
||||
interfacemode=""
|
||||
logoptions=""
|
||||
|
||||
if [ "$IFMODE" == "y" ]; then
|
||||
interfacemode="--promiscuous"
|
||||
fi
|
||||
|
||||
if [ "$LOGFILE" != "syslog" ]; then
|
||||
logoptions="--log $LOGFILE"
|
||||
fi
|
||||
|
||||
unraidwold_start --interface $INTERFACE $interfacemode $logoptions
|
||||
fi
|
||||
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
'start')
|
||||
unraidwold_start $2 $3 $4 $5 $6
|
||||
;;
|
||||
'stop')
|
||||
unraidwold_stop
|
||||
;;
|
||||
'status')
|
||||
unraidwold_status
|
||||
;;
|
||||
'load')
|
||||
unraidwold_load
|
||||
;;
|
||||
*)
|
||||
echo "Usage: $BDAEMON start|stop|restart|status"
|
||||
exit 1
|
||||
esac
|
||||
exit 0
|
||||
@@ -25,6 +25,7 @@ $zip = $all ? ($argv[2]??'') : ($argv[1]??'');
|
||||
$cli = empty($zip);
|
||||
|
||||
$docroot ??= ($_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp');
|
||||
require_once "$docroot/webGui/include/Helpers.php";
|
||||
require_once "$docroot/webGui/include/Wrappers.php";
|
||||
|
||||
$folders = ['/boot','/boot/config','/boot/config/plugins','/boot/syslinux','/var/log','/var/log/plugins','/boot/extra','/var/log/packages','/var/lib/pkgtools/packages','/tmp'];
|
||||
@@ -115,16 +116,6 @@ function maskIP($file) {
|
||||
// anonymize full IPv6 addresses
|
||||
run("sed -ri 's/([\"\[ ]([0-9a-f]{1,4}:){4})(([0-9a-f]{1,4}:){3}|:)([0-9a-f]{1,4})([/\" .]|$)/\\1XXXX:XXXX:XXXX:\\5\\6/g' ".escapeshellarg($file)." 2>/dev/null");
|
||||
}
|
||||
|
||||
function cache_only($disk) {
|
||||
return _var($disk,'type')=='Cache';
|
||||
}
|
||||
function cache_filter($disks) {
|
||||
return array_filter($disks,'cache_only');
|
||||
}
|
||||
function pools_filter($disks) {
|
||||
return array_unique(array_map('prefix',array_keys(cache_filter($disks))));
|
||||
}
|
||||
function download_url($url, $path="", $bg=false, $timeout=15) {
|
||||
$ch = curl_init();
|
||||
curl_setopt_array($ch,[
|
||||
@@ -661,6 +652,13 @@ if (file_exists($dhcplog)) {
|
||||
if (!$all) maskIP($log);
|
||||
}
|
||||
|
||||
// copy phplog
|
||||
$phplog = "/var/log/phplog";
|
||||
if (file_exists($phplog)) {
|
||||
$log = "/$diag/logs/phplog.txt";
|
||||
run("todos <$phplog >".escapeshellarg($log));
|
||||
}
|
||||
|
||||
// copy graphql-api.log
|
||||
$graphql = "/var/log/graphql-api.log";
|
||||
if (file_exists($graphql)) {
|
||||
|
||||
@@ -35,7 +35,7 @@ if [[ -n $local_server ]]; then
|
||||
sed -ri "\$a\\\$InputUDPServerBindRuleset remote\n\\\$UDPServerRun ${server_port:-514}" $ETC
|
||||
[[ $server_protocol == udp ]] && sed -ri 's/^(\$ModLoad imtcp)/#\1/;/^\$InputTCPServerBindRuleset remote$/d;/^\$InputTCPServerRun [0-9]+$/d' $ETC
|
||||
fi
|
||||
sed -ri "/^\\\$template remote,.*$/d;/^#\\\$UDPServerRun [0-9]+.*$/a\\\$template remote,\"${server_folder:-/mnt/user/system}/syslog-%FROMHOST-IP%.log\"" $ETC
|
||||
sed -ri "/^\\\$template remote,.*$/d;/^#\\\$UDPServerRun [0-9]+.*$/a\\\$template remote,\"${server_folder:-/mnt/user/system}/${server_filename:-syslog-%FROMHOST-IP%.log}\"" $ETC
|
||||
else
|
||||
sed -ri '/^\$RuleSet remote$/d;/^\$FileOwner nobody$/d;/^\$FileGroup users$/d;/^\$FileCreateMode 06[46][46]$/d;/^\$IncludeConfig \/etc\/rsyslog\.d\/\*\.conf # remote$/d;/^\*\.\* \?remote$/d;/^\$template remote,".*"$/d;/^\$Input(TCP|UDP)ServerBindRuleset remote$/d;/^\$(InputTCP|UDP)ServerRun [0-9]+$/d;s/^#?\$(ModLoad imtcp|ModLoad imudp)/#\$\1/' $ETC
|
||||
fi
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/php -q
|
||||
<?PHP
|
||||
/* Copyright 2005-2023, Lime Technology
|
||||
* Copyright 2012-2023, Bergware International.
|
||||
/* Copyright 2005-2024, Lime Technology
|
||||
* Copyright 2012-2024, Bergware International.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2,
|
||||
@@ -21,6 +21,7 @@ $disks = (array)@parse_ini_file("/var/local/emhttp/disks.ini",true);
|
||||
require_once "$docroot/webGui/include/CustomMerge.php";
|
||||
|
||||
$script = "$docroot/webGui/scripts/notify";
|
||||
// this command will set the $notify array
|
||||
extract(parse_plugin_cfg("dynamix",true));
|
||||
$output = _var($notify,'report');
|
||||
$server = strtoupper(_var($var,'NAME','tower'));
|
||||
@@ -178,7 +179,8 @@ $warn = ($error0 || $error3) ? "alert" : (($error1 || $error2) ? "warning" : "no
|
||||
$stat = $warn=="normal" ? "[PASS]" : "[FAIL]";
|
||||
$info = "Array has $size disk".($size==1 ? "" : "s").($parity ? " ({$word}parity".($pools ? " & pools)" : ")") : ($pools ? " ({$word}pools)" : ""));
|
||||
$message = implode('\n', $data);
|
||||
exec("$script -s ".escapeshellarg("Notice [$server] - array health report $stat")." -d ".escapeshellarg("$info")." -m ".escapeshellarg("$message")." -i ".escapeshellarg("$warn $output")." -l '/Main'");
|
||||
$subject = "Notice [$server] - array health report $stat";
|
||||
exec("$script -s ".escapeshellarg($subject)." -d ".escapeshellarg("$info")." -m ".escapeshellarg("$message")." -i ".escapeshellarg("$warn $output")." -l '/Main'");
|
||||
|
||||
exit(0);
|
||||
?>
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
table#t1{margin-top:0;font-family:clear-sans}
|
||||
table#t1 thead tr th{font-weight:bold}
|
||||
table#t1 tbody tr td{padding:4px 20px 4px 0;margin:0;text-align:left;white-space:normal}
|
||||
table#t1 tbody tr td:nth-child(1){width:10%}
|
||||
table#t1 tbody tr td:nth-child(2){width:30%}
|
||||
table#t1 tbody tr td:nth-child(3){width:15%}
|
||||
table#t1 tbody tr td:nth-child(4){width:20%}
|
||||
table#t1 tbody tr td:nth-child(5){width:25%;padding-right:0}
|
||||
table.t1.tablesorter .filtered{display:none}
|
||||
.tablesorter-header-inner{font-family:clear-sans;font-weight:bold}
|
||||
#macform .mac_generate{cursor:pointer;margin-left:-5px;color:#08C;font-size:1.3rem;transform:translate(0px, 2px)}
|
||||
@@ -122,7 +122,9 @@ table.unraid thead tr:first-child>td{font-size:1.2rem;text-transform:uppercase;l
|
||||
table.unraid tbody tr:not(.tr_last):hover>td{background-color:rgba(0,0,0,0.05)}
|
||||
table.unraid tr>td{overflow:hidden;text-overflow:ellipsis;padding-left:8px}
|
||||
table.unraid tr>td:hover{overflow:visible}
|
||||
table.legacy{table-layout:auto}
|
||||
table.legacy{table-layout:auto!important}
|
||||
table.legacy thead td{line-height:normal;height:auto;padding:7px 0}
|
||||
table.legacy tbody td{line-height:normal;height:auto;padding:5px 0}
|
||||
table.disk_status{table-layout:fixed}
|
||||
table.disk_status tr>td:last-child{padding-right:8px}
|
||||
table.disk_status tr>td:nth-child(1){width:13%}
|
||||
|
||||
@@ -120,7 +120,9 @@ table.unraid tbody tr:nth-child(even){background-color:#212121}
|
||||
table.unraid tbody tr:not(.tr_last):hover>td{background-color:rgba(255,255,255,0.1)}
|
||||
table.unraid tr>td{overflow:hidden;text-overflow:ellipsis;padding-left:8px}
|
||||
table.unraid tr>td:hover{overflow:visible}
|
||||
table.legacy{table-layout:auto}
|
||||
table.legacy{table-layout:auto!important}
|
||||
table.legacy thead td{line-height:normal;height:auto;padding:7px 0}
|
||||
table.legacy tbody td{line-height:normal;height:auto;padding:5px 0}
|
||||
table.disk_status{table-layout:fixed}
|
||||
table.disk_status tr>td:last-child{padding-right:8px}
|
||||
table.disk_status tr>td:nth-child(1){width:13%}
|
||||
|
||||
@@ -122,7 +122,9 @@ table.unraid thead tr:first-child>td{font-size:1.2rem;text-transform:uppercase;l
|
||||
table.unraid tbody tr:not(.tr_last):hover>td{background-color:rgba(255,255,255,0.05)}
|
||||
table.unraid tr>td{overflow:hidden;text-overflow:ellipsis;padding-left:8px}
|
||||
table.unraid tr>td:hover{overflow:visible}
|
||||
table.legacy{table-layout:auto}
|
||||
table.legacy{table-layout:auto!important}
|
||||
table.legacy thead td{line-height:normal;height:auto;padding:7px 0}
|
||||
table.legacy tbody td{line-height:normal;height:auto;padding:5px 0}
|
||||
table.disk_status{table-layout:fixed}
|
||||
table.disk_status tr>td:last-child{padding-right:8px}
|
||||
table.disk_status tr>td:nth-child(1){width:13%}
|
||||
|
||||
@@ -120,7 +120,9 @@ table.unraid tbody tr:nth-child(even){background-color:#ededed}
|
||||
table.unraid tbody tr:not(.tr_last):hover>td{background-color:rgba(0,0,0,0.1)}
|
||||
table.unraid tr>td{overflow:hidden;text-overflow:ellipsis;padding-left:8px}
|
||||
table.unraid tr>td:hover{overflow:visible}
|
||||
table.legacy{table-layout:auto}
|
||||
table.legacy{table-layout:auto!important}
|
||||
table.legacy thead td{line-height:normal;height:auto;padding:7px 0}
|
||||
table.legacy tbody td{line-height:normal;height:auto;padding:5px 0}
|
||||
table.disk_status{table-layout:fixed}
|
||||
table.disk_status tr>td:last-child{padding-right:8px}
|
||||
table.disk_status tr>td:nth-child(1){width:13%}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.jGrowl{position:fixed;font-size:1.3rem}
|
||||
.jGrowl{position:fixed;font-size:1.3rem;z-index:10001}
|
||||
.jGrowl.top-left{left:10px;top:90px}
|
||||
.jGrowl.top-right{right:10px;top:90px}
|
||||
.jGrowl.bottom-left{left:10px;bottom:24px}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.jGrowl{position:fixed;font-size:1.3rem}
|
||||
.jGrowl{position:fixed;font-size:1.3rem;z-index:10001}
|
||||
.jGrowl.top-left{left:10px;top:130px}
|
||||
.jGrowl.top-right{right:10px;top:130px}
|
||||
.jGrowl.bottom-left{left:10px;bottom:24px}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.jGrowl{position:fixed;font-size:1.3rem}
|
||||
.jGrowl{position:fixed;font-size:1.3rem;z-index:10001}
|
||||
.jGrowl.top-left{left:10px;top:90px}
|
||||
.jGrowl.top-right{right:10px;top:90px}
|
||||
.jGrowl.bottom-left{left:10px;bottom:24px}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.jGrowl{position:fixed;font-size:1.3rem}
|
||||
.jGrowl{position:fixed;font-size:1.3rem;z-index:10001}
|
||||
.jGrowl.top-left{left:10px;top:130px}
|
||||
.jGrowl.top-right{right:10px;top:130px}
|
||||
.jGrowl.bottom-left{left:10px;bottom:24px}
|
||||
|
||||
@@ -50,7 +50,7 @@ fi
|
||||
# initrd has already done so):
|
||||
if [[ -d /run ]]; then
|
||||
if ! /bin/grep -wq "tmpfs /run tmpfs" /proc/mounts; then
|
||||
/sbin/mount -v -n -t tmpfs tmpfs /run -o mode=0755,size=32M,nodev,nosuid,noexec
|
||||
/sbin/mount -v -n -t tmpfs tmpfs /run -o mode=0755,size=128M,nodev,nosuid,noexec
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
@@ -42,7 +42,8 @@ SYSTEM="/sys/devices/system/cpu"
|
||||
# provides power savings on Intel processors while avoiding the ramp-up lag
|
||||
# present when using the powersave governor (which is the default if ondemand
|
||||
# is requested on these machines):
|
||||
if [[ $(cat $SYSTEM/cpu0/cpufreq/scaling_driver 2>/dev/null) == intel_pstate ]]; then
|
||||
if [[ $(cat $SYSTEM/cpu0/cpufreq/scaling_driver 2>/dev/null) == intel_pstate ||
|
||||
$(cat $SYSTEM/cpu0/cpufreq/scaling_driver 2>/dev/null) == amd-pstate-epp ]]; then
|
||||
SCALING_GOVERNOR="performance"
|
||||
fi
|
||||
|
||||
|
||||
@@ -501,7 +501,7 @@ docker_container_start(){
|
||||
log "$CONTAINER: $OUT" &
|
||||
else
|
||||
run container_add_route $CONTAINER
|
||||
log "$CONTAINER: started succesfully!" &
|
||||
log "$CONTAINER: started successfully!" &
|
||||
if [[ $WAIT -gt 0 ]]; then
|
||||
log "$CONTAINER: wait $WAIT seconds" &
|
||||
sleep $WAIT
|
||||
@@ -566,7 +566,7 @@ docker_service_stop(){
|
||||
run ip link del docker0
|
||||
fi
|
||||
REPLY="Stopped"
|
||||
# signal succesful stop
|
||||
# signal successful stop
|
||||
TIMER=-1
|
||||
else
|
||||
# show waiting message
|
||||
|
||||
@@ -69,7 +69,10 @@
|
||||
# Adapted by Bergware for use in Unraid OS - December 2023
|
||||
# - remove leading zeros in IPv4 and IPv6 addresses
|
||||
|
||||
# Bergware - modified for Unraid OS, December 2023
|
||||
# Adapted by Bergware for use in Unraid OS - February 2024
|
||||
# - revised bond interface creation for linux kernel 6.6.14 and later point releases
|
||||
|
||||
# Bergware - modified for Unraid OS, February 2024
|
||||
|
||||
###########
|
||||
# LOGGING #
|
||||
@@ -175,8 +178,8 @@ bond_up(){
|
||||
for BONDIF in ${BONDNICS[$i]}; do
|
||||
if [[ -e $SYSTEM/$BONDIF ]]; then
|
||||
[[ -z $PRIMARY ]] && PRIMARY=$BONDIF
|
||||
run ip link set $BONDIF down
|
||||
run ip link set $BONDIF master ${BONDNAME[$i]} up type bond_slave
|
||||
run ip link set $BONDIF up
|
||||
run ip link set $BONDIF master ${BONDNAME[$i]} down type bond_slave
|
||||
else
|
||||
[[ $DEBUG_ETH_UP == yes ]] && log "interface $BONDIF not present, can't add to ${BONDNAME[$i]}"
|
||||
fi
|
||||
|
||||
@@ -237,6 +237,7 @@ libvirtd_start(){
|
||||
|
||||
check_processor
|
||||
modprobe -a $MODULE $MODULES
|
||||
echo 0 > /sys/module/kvm/parameters/report_ignored_msrs
|
||||
libvirtd -d -l $LIBVIRTD_OPTS
|
||||
log "$DAEMON... Started."
|
||||
}
|
||||
|
||||
@@ -14,6 +14,28 @@
|
||||
# run & log functions
|
||||
. /etc/rc.d/rc.runlog
|
||||
|
||||
# import CA proxy
|
||||
UnProxy=/boot/config/proxy.cfg
|
||||
CAProxy=/boot/config/plugins/community.applications/proxy.cfg
|
||||
if [[ -f "${CAProxy}" && ! -f "${UnProxy}" ]]; then
|
||||
proxy=
|
||||
port=
|
||||
. "${CAProxy}"
|
||||
# proxy and port were set by the previous command
|
||||
if [[ -n "${proxy}" && -n "${port}" ]]; then
|
||||
cat << EOF > "${UnProxy}"
|
||||
proxy_active="1"
|
||||
proxy_url_1="${proxy}:${port}"
|
||||
proxy_name_1="Imported from CA"
|
||||
EOF
|
||||
fi
|
||||
mv "${CAProxy}" "${CAProxy}.bak"
|
||||
fi
|
||||
|
||||
# load proxy environment vars so it is used for plugin updates and the go script
|
||||
/usr/local/sbin/set_proxy
|
||||
[[ -x /etc/profile.d/proxy.sh ]] && . /etc/profile.d/proxy.sh
|
||||
|
||||
# irqbalance daemon distributes interrupts over processors and cores
|
||||
# if [[ -x /usr/sbin/irqbalance ]]; then
|
||||
# /usr/sbin/irqbalance
|
||||
@@ -69,7 +91,7 @@ rm -f /boot/plugins/unRAIDServer.plg
|
||||
rm -f $CONFIG/plugins/unRAIDServer.plg
|
||||
|
||||
# These plugins are now integrated in the OS or obsolete and may interfere
|
||||
OBSOLETE="vfio.pci dynamix.wireguard dynamix.ssd.trim dynamix.file.manager gui.search unlimited-width"
|
||||
OBSOLETE="vfio.pci dynamix.wireguard dynamix.ssd.trim dynamix.file.manager gui.search unlimited-width proxy.editor"
|
||||
for PLUGIN in $OBSOLETE; do
|
||||
if [[ -e $CONFIG/plugins/$PLUGIN.plg ]]; then
|
||||
log "moving obsolete plugin $PLUGIN.plg to $CONFIG/plugins-error"
|
||||
@@ -166,6 +188,20 @@ if [[ $PERSISTENT_BASH_HISTORY == 1 ]]; then
|
||||
ln -s /boot/config/history/bash_history /root/.bash_history
|
||||
fi
|
||||
|
||||
# cleanup the 'go' script
|
||||
# delete emhttp line with trailing & (could also have leading env vars), add new line with just call to emhttp
|
||||
GOTEST1='^[^#]*/usr/local/sbin/emhttp.*&$'
|
||||
if grep -q "$GOTEST1" $CONFIG/go; then
|
||||
cp $CONFIG/go $CONFIG/go-
|
||||
sed -i "s@$GOTEST1@/usr/local/sbin/emhttp@g" $CONFIG/go
|
||||
fi
|
||||
# delete lines added by ProxyEditor
|
||||
GOTEST2='# Added by ProxyEditor'
|
||||
if grep -q "$GOTEST2" $CONFIG/go; then
|
||||
[[ ! -f $CONFIG/go- ]] && cp $CONFIG/go $CONFIG/go-
|
||||
sed -i "/$GOTEST2/d" $CONFIG/go
|
||||
fi
|
||||
|
||||
# Invoke the 'go' script
|
||||
if [[ -f $CONFIG/go ]]; then
|
||||
log "Starting go script"
|
||||
|
||||
@@ -686,8 +686,6 @@ nginx_reload(){
|
||||
if nginx_check; then
|
||||
log "Reloading $DAEMON configuration..."
|
||||
kill -HUP $(cat $PID)
|
||||
# update DNS
|
||||
php -f /usr/local/emhttp/webGui/include/UpdateDNS.php
|
||||
sleep 3
|
||||
else
|
||||
log "Invalid configuration, $DAEMON not reloaded"
|
||||
@@ -705,8 +703,6 @@ nginx_renew(){
|
||||
build_ssl
|
||||
# start unconditionally
|
||||
$NGINX -c $CONF 2>/dev/null
|
||||
# update DNS
|
||||
php -f /usr/local/emhttp/webGui/include/UpdateDNS.php
|
||||
}
|
||||
|
||||
nginx_update(){
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
#!/bin/bash
|
||||
DISABLE="no"
|
||||
source /boot/config/domain.cfg
|
||||
if [ $DISABLE == "yes" ]
|
||||
then
|
||||
exit ;
|
||||
printf '\n%s\n' "Start/autostart is disabled in VM settings." >&2 ## Send message to stderr.
|
||||
exit 1 ;
|
||||
fi
|
||||
eval exec /usr/bin/qemu-system-x86_64 $(/usr/local/emhttp/plugins/dynamix.vm.manager/scripts/qemu.php "$@")
|
||||
129
sbin/set_proxy
129
sbin/set_proxy
@@ -154,3 +154,132 @@ if ($proxy_active != "0") {
|
||||
remove_proxy_from_generated_files();
|
||||
}
|
||||
?>
|
||||
=======
|
||||
#!/bin/bash
|
||||
#
|
||||
# script: set_proxy
|
||||
#
|
||||
# Copyright 2005-2024, Lime Technology
|
||||
#
|
||||
# call this script (/usr/local/sbin/set_proxy) when /boot/config/proxy.cfg changes
|
||||
|
||||
# proxy.cfg is the source of all proxy information
|
||||
CFG=/boot/config/proxy.cfg
|
||||
|
||||
# these files are generated by this script based on the data in proxy.cfg
|
||||
PROXY_SH=/etc/profile.d/proxy.sh
|
||||
PROXY_INI=/usr/local/emhttp/state/proxy.ini
|
||||
|
||||
# random file extension for atomic writes
|
||||
RND=$RANDOM
|
||||
|
||||
VERBOSE=
|
||||
[[ "$1" == "-v" ]] && VERBOSE=1
|
||||
|
||||
# global vars defined later
|
||||
proxy_active=
|
||||
proxy_url=
|
||||
no_proxy=
|
||||
|
||||
# write environment variables to /etc/profile.d/proxy.sh
|
||||
set_proxy_sh() {
|
||||
local FILE
|
||||
FILE="${PROXY_SH}"
|
||||
cat <<EOF >"${FILE}.${RND}"
|
||||
#!/bin/bash
|
||||
# Do not edit. This file is autogenerated by /usr/local/sbin/set_proxy
|
||||
export http_proxy="${proxy_url}"
|
||||
export https_proxy="${proxy_url}"
|
||||
export no_proxy="${no_proxy}"
|
||||
EOF
|
||||
chmod 755 "${FILE}.${RND}"
|
||||
mv "${FILE}.${RND}" "${FILE}"
|
||||
}
|
||||
|
||||
# clear environment variables from /etc/profile.d/proxy.sh
|
||||
unset_proxy_sh() {
|
||||
local FILE
|
||||
FILE="${PROXY_SH}"
|
||||
cat <<EOF >"${FILE}.${RND}"
|
||||
#!/bin/bash
|
||||
# Do not edit. This file is autogenerated by /usr/local/sbin/set_proxy
|
||||
unset http_proxy
|
||||
unset https_proxy
|
||||
unset no_proxy
|
||||
EOF
|
||||
chmod 755 "${FILE}.${RND}"
|
||||
mv "${FILE}.${RND}" "${FILE}"
|
||||
}
|
||||
|
||||
set_proxy_ini() {
|
||||
local FILE
|
||||
FILE="${PROXY_INI}"
|
||||
cat <<EOF >"${FILE}.${RND}"
|
||||
http_proxy="${proxy_url}"
|
||||
https_proxy="${proxy_url}"
|
||||
no_proxy="${no_proxy}"
|
||||
EOF
|
||||
chmod 644 "${FILE}.${RND}"
|
||||
mv "${FILE}.${RND}" "${FILE}"
|
||||
}
|
||||
|
||||
# clear /usr/local/emhttp/state/proxy.ini
|
||||
unset_proxy_ini() {
|
||||
# vars are empty now, call set_proxy_ini to add empty vars to proxy.ini
|
||||
set_proxy_ini
|
||||
}
|
||||
|
||||
# generate proxy files
|
||||
add_proxy_to_generated_files_and_exit() {
|
||||
echo "generating proxy files"
|
||||
set_proxy_sh
|
||||
set_proxy_ini
|
||||
[[ -n "${VERBOSE}" ]] && display_generated_files
|
||||
exit 0
|
||||
}
|
||||
|
||||
# remove proxy info from all generated files and exit
|
||||
remove_proxy_from_generated_files_and_exit() {
|
||||
echo "removing proxy info from generated files"
|
||||
unset_proxy_sh
|
||||
unset_proxy_ini
|
||||
[[ -n "${VERBOSE}" ]] && display_generated_files
|
||||
exit 0
|
||||
}
|
||||
|
||||
# when verbose mode enabled
|
||||
display_generated_files() {
|
||||
echo
|
||||
display_generated_file "${PROXY_SH}"
|
||||
display_generated_file "${PROXY_INI}"
|
||||
}
|
||||
|
||||
# when verbose mode enabled
|
||||
display_generated_file() {
|
||||
local FILE
|
||||
FILE=$1
|
||||
echo "${FILE}"
|
||||
[[ -f "${FILE}" ]] && cat "${FILE}" || echo "file does not exist"
|
||||
echo
|
||||
}
|
||||
|
||||
# if no proxy config, remove proxy info from all generated files and exit
|
||||
[[ ! -f "${CFG}" ]] && remove_proxy_from_generated_files_and_exit
|
||||
|
||||
# read current proxy information from /boot/config/proxy.cfg
|
||||
# shellcheck source=/dev/null
|
||||
. <(/usr/bin/fromdos <"${CFG}")
|
||||
|
||||
# determine proxy information
|
||||
proxy_url_var="proxy_url_${proxy_active:=}"
|
||||
proxy_url="${!proxy_url_var}"
|
||||
|
||||
# if no active proxies, remove proxy info from all generated files and exit
|
||||
if [[ "${proxy_active:=0}" == "0" || "${proxy_url}" == "" ]]; then
|
||||
remove_proxy_from_generated_files_and_exit
|
||||
fi
|
||||
|
||||
# proxies are defined, write generated files
|
||||
no_proxy="127.0.0.1,localhost"
|
||||
add_proxy_to_generated_files_and_exit
|
||||
|
||||
|
||||
2
sbin/virtiofsd
Executable file
2
sbin/virtiofsd
Executable file
@@ -0,0 +1,2 @@
|
||||
#!/bin/bash
|
||||
eval exec /usr/bin/virtiofsd $(/usr/local/emhttp/plugins/dynamix.vm.manager/scripts/virtiofsd.php "$@")
|
||||
Reference in New Issue
Block a user