mirror of
https://github.com/unraid/webgui.git
synced 2026-05-12 15:20:29 -05:00
Merge pull request #302 from bergware/master
Change docker caching to private variables
This commit is contained in:
@@ -34,13 +34,14 @@ img.stopped{opacity:0.3}
|
||||
.started{color:#009900}
|
||||
.stopped{color:#EF3D47}
|
||||
.switch-button-label.off{color:inherit}
|
||||
th.three{width:3%}
|
||||
th.five{width:5%}
|
||||
th.eight{width:8%}
|
||||
</style>
|
||||
<div id="dialog-confirm" style="display:none;" title="Dialog Title"></div>
|
||||
<div id="iframe-popup" style="display:none;-webkit-overflow-scrolling:touch;"></div>
|
||||
<span class="status" style="margin-top:-44px"><span><input type="checkbox" class="advancedview"></span></span>
|
||||
<table class="tablesorter shift" id="docker_containers">
|
||||
<thead><tr><th></th><th>Application</th><th>Version</th><th>Network</th><th>Port Mappings <small>(App to Host)</small></th><th>Volume Mappings <small>(App to Host)</small></th><th width="80px" style="text-align:center">Autostart</th><th class="three">Log</th></tr></thead>
|
||||
<thead><tr><th></th><th>Application</th><th>Version</th><th>Network</th><th>Port Mappings <small>(App to Host)</small></th><th>Volume Mappings <small>(App to Host)</small></th><th class="eight">Autostart</th><th class="five">Log</th><th class="five" style="text-align:right;padding-right:24px"><a href="#" style="cursor:hand" onclick="resetSorting()" title="Reset sorting"><i class="fa fa-sort"></i></a></th></tr></thead>
|
||||
<tbody id="docker_list"><tr><td colspan='8' style='text-align:center;padding:24px'><i class='fa fa-circle-o-notch fa-spin fa-3x fa-fw'></i></td></tr></tbody>
|
||||
</table>
|
||||
<input type="button" onclick="addContainer()" value="Add Container" style="display:none">
|
||||
@@ -65,6 +66,10 @@ function resize(bind) {
|
||||
}
|
||||
}
|
||||
<?endif;?>
|
||||
function resetSorting() {
|
||||
$('input[type=button]').prop('disabled',true);
|
||||
$.post('/plugins/dynamix.docker.manager/include/UserPrefs.php',{reset:true},function(){loadlist();});
|
||||
}
|
||||
function listview() {
|
||||
if ($.cookie('docker_listview_mode')=='basic') {
|
||||
$('.docker_readmore').readmore({maxHeight:32,moreLink:"<a href='#' style='text-align:center'><i class='fa fa-chevron-down'></i></a>",lessLink:"<a href='#' style='text-align:center'><i class='fa fa-chevron-up'></i></a>"});
|
||||
@@ -85,10 +90,6 @@ function loadlist(update) {
|
||||
$('.autostart').change(function() {
|
||||
$.post( "/plugins/dynamix.docker.manager/include/UpdateConfig.php",{action:'autostart',container:$(this).attr('container'),response:'json'},function(data){$(this).prop('checked',data.autostart);},'json');
|
||||
});
|
||||
$('#docker_containers').tablesorter({
|
||||
sortList:[[1,0]],headers:{0:{sorter:false},4:{sorter:false},5:{sorter:false},7:{sorter:false}},
|
||||
textExtraction:{6:function(node,table,cellIndex){return $(node).find('input').prop('checked')?1:0;}}
|
||||
});
|
||||
if ($.cookie('docker_listview_mode')=='advanced') {$('.advanced').show(); $('.basic').hide();}
|
||||
listview();
|
||||
context.init({preventDoubleContext:false});
|
||||
@@ -98,6 +99,24 @@ function loadlist(update) {
|
||||
} else {
|
||||
$('input#checkAll').show(); $('input#updateAll').hide();
|
||||
}
|
||||
$('i.up,i.down').click(function() {
|
||||
var row = $(this).parents('tr:first');
|
||||
var color1 = row.css('background-color');
|
||||
if ($(this).is('.up')) {
|
||||
var color2 = row.prev().css('background-color');
|
||||
row.prev().css('background-color',color1);
|
||||
row.css('background-color',color2);
|
||||
row.insertBefore(row.prev());
|
||||
} else {
|
||||
var color2 = row.next().css('background-color');
|
||||
row.next().css('background-color',color1);
|
||||
row.css('background-color',color2);
|
||||
row.insertAfter(row.next());
|
||||
}
|
||||
var names = ''; var index = '';
|
||||
row.parent().children().find('td.ct-name').each(function(){names+=$(this).text().replace(/Container ID.*$/,'')+';';index+=$(this).parent().parent().children().index($(this).parent())+';';});
|
||||
$.post('/plugins/dynamix.docker.manager/include/UserPrefs.php',{names:names,index:index});
|
||||
});
|
||||
});
|
||||
}
|
||||
$(function() {
|
||||
|
||||
@@ -12,16 +12,23 @@
|
||||
*/
|
||||
?>
|
||||
<?
|
||||
$docroot = $docroot ?? $_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp';
|
||||
$user_prefs = '/boot/config/plugins/dockerMan/userprefs.cfg';
|
||||
|
||||
exec("docker ps -a --format='{{.Names}}'",$container);
|
||||
exec("docker ps -a --format='{{.Names}}'",$all_containers);
|
||||
|
||||
if (file_exists($user_prefs)) {
|
||||
$prefs = parse_ini_file($user_prefs); $sort = [];
|
||||
foreach ($all_containers as $ct) $sort[] = array_search($ct,$prefs) ?? 999;
|
||||
array_multisort($sort,SORT_NUMERIC,$all_containers);
|
||||
}
|
||||
|
||||
$action = $_POST['action'];
|
||||
switch ($action) {
|
||||
case 'stop' : $state = 'true'; break;
|
||||
case 'stop' : $state = 'true'; $all_containers = array_reverse($all_containers); break;
|
||||
case 'start': $state = 'false'; break;
|
||||
}
|
||||
foreach ($container as $ct) {
|
||||
|
||||
foreach ($all_containers as $ct) {
|
||||
if (exec("docker inspect --format='{{.State.Running}}' $ct")==$state) exec("docker $action $ct >/dev/null");
|
||||
}
|
||||
?>
|
||||
|
||||
@@ -439,8 +439,7 @@ function xmlToCommand($xml, $create_paths=false) {
|
||||
|
||||
function execCommand($command) {
|
||||
// $command should have all its args already properly run through 'escapeshellarg'
|
||||
$cmdTmp = explode(";",$command);
|
||||
$command = $cmdTmp[0];
|
||||
// $command = explode(';',$command)[0]; // commented out, not sure if we want this!
|
||||
|
||||
$descriptorspec = [
|
||||
0 => ["pipe", "r"], // stdin is a pipe that the child will read from
|
||||
|
||||
@@ -20,6 +20,7 @@ $dockerManPaths = [
|
||||
'template-repos' => '/boot/config/plugins/dockerMan/template-repos',
|
||||
'templates-user' => '/boot/config/plugins/dockerMan/templates-user',
|
||||
'templates-storage' => '/boot/config/plugins/dockerMan/templates',
|
||||
'user-prefs' => '/boot/config/plugins/dockerMan/userprefs.cfg',
|
||||
'images-ram' => '/usr/local/emhttp/state/plugins/dynamix.docker.manager/images',
|
||||
'images-storage' => '/boot/config/plugins/dockerMan/images',
|
||||
'webui-info' => '/usr/local/emhttp/state/plugins/dynamix.docker.manager/docker.json',
|
||||
@@ -569,6 +570,9 @@ class DockerUpdate{
|
||||
######################################
|
||||
class DockerClient {
|
||||
|
||||
private static $allContainersCache = null;
|
||||
private static $allImagesCache = null;
|
||||
|
||||
private function build_sorter($key) {
|
||||
return function ($a, $b) use ($key) {
|
||||
return strnatcmp(strtolower($a[$key]), strtolower($b[$key]));
|
||||
@@ -660,7 +664,7 @@ class DockerClient {
|
||||
|
||||
public function startContainer($id) {
|
||||
$this->getDockerJSON("/containers/${id}/start", 'POST', $code);
|
||||
DockerUtil::$allContainersCache = null; // flush cache
|
||||
$this::$allContainersCache = null; // flush cache
|
||||
$codes = [
|
||||
'204' => true, // No error
|
||||
'304' => 'Container already started',
|
||||
@@ -672,7 +676,7 @@ class DockerClient {
|
||||
|
||||
public function stopContainer($id) {
|
||||
$this->getDockerJSON("/containers/${id}/stop?t=10", 'POST', $code);
|
||||
DockerUtil::$allContainersCache = null; // flush cache
|
||||
$this::$allContainersCache = null; // flush cache
|
||||
$codes = [
|
||||
'204' => true, // No error
|
||||
'304' => 'Container already stopped',
|
||||
@@ -684,7 +688,7 @@ class DockerClient {
|
||||
|
||||
public function restartContainer($id) {
|
||||
$this->getDockerJSON("/containers/${id}/restart?t=10", 'POST', $code);
|
||||
DockerUtil::$allContainersCache = null; // flush cache
|
||||
$this::$allContainersCache = null; // flush cache
|
||||
$codes = [
|
||||
'204' => true, // No error
|
||||
'404' => 'No such container',
|
||||
@@ -709,7 +713,7 @@ class DockerClient {
|
||||
}
|
||||
// Attempt to remove container
|
||||
$this->getDockerJSON("/containers/${id}?force=1", 'DELETE', $code);
|
||||
DockerUtil::$allContainersCache = null; // flush cache
|
||||
$this::$allContainersCache = null; // flush cache
|
||||
$codes = [
|
||||
'204' => true, // No error
|
||||
'400' => 'Bad parameter',
|
||||
@@ -721,7 +725,7 @@ class DockerClient {
|
||||
|
||||
public function pullImage($image, $callback = null) {
|
||||
$ret = $this->getDockerJSON("/images/create?fromImage=".urlencode($image), 'POST', $code, $callback);
|
||||
DockerUtil::$allImagesCache = null; // flush cache
|
||||
$this::$allImagesCache = null; // flush cache
|
||||
return $ret;
|
||||
}
|
||||
|
||||
@@ -730,7 +734,7 @@ class DockerClient {
|
||||
$image = $this->getImageName($id);
|
||||
// Attempt to remove image
|
||||
$this->getDockerJSON("/images/${id}?force=1", 'DELETE', $code);
|
||||
DockerUtil::$allImagesCache = null; // flush cache
|
||||
$this::$allImagesCache = null; // flush cache
|
||||
if (in_array($code, ['200', '404'])) {
|
||||
// Purge cached image information (only if delete was successful)
|
||||
$image = DockerUtil::ensureImageTag($image);
|
||||
@@ -755,8 +759,8 @@ class DockerClient {
|
||||
|
||||
public function getDockerContainers() {
|
||||
// Return cached values
|
||||
if (is_array(DockerUtil::$allContainersCache)) return DockerUtil::$allContainersCache;
|
||||
DockerUtil::$allContainersCache = [];
|
||||
if (is_array($this::$allContainersCache)) return $this::$allContainersCache;
|
||||
$this::$allContainersCache = [];
|
||||
foreach ($this->getDockerJSON("/containers/json?all=1") as $obj) {
|
||||
$details = $this->getContainerDetails($obj['Id']);
|
||||
$c = [];
|
||||
@@ -778,10 +782,10 @@ class DockerClient {
|
||||
$c['Ports'][] = ['IP' => $value[0]['HostIP'] ?? '0.0.0.0', 'PrivatePort' => $PrivatePort, 'PublicPort' => $value[0]['HostPort'], 'Type' => $Type ];
|
||||
}
|
||||
}
|
||||
DockerUtil::$allContainersCache[] = $c;
|
||||
$this::$allContainersCache[] = $c;
|
||||
}
|
||||
usort(DockerUtil::$allContainersCache, $this->build_sorter('Name'));
|
||||
return DockerUtil::$allContainersCache;
|
||||
usort($this::$allContainersCache, $this->build_sorter('Name'));
|
||||
return $this::$allContainersCache;
|
||||
}
|
||||
|
||||
public function getContainerID($Container) {
|
||||
@@ -818,8 +822,8 @@ class DockerClient {
|
||||
|
||||
public function getDockerImages() {
|
||||
// Return cached values
|
||||
if (is_array(DockerUtil::$allImagesCache)) return DockerUtil::$allImagesCache;
|
||||
DockerUtil::$allImagesCache = [];
|
||||
if (is_array($this::$allImagesCache)) return $this::$allImagesCache;
|
||||
$this::$allImagesCache = [];
|
||||
foreach ($this->getDockerJSON('/images/json?all=0') as $obj) {
|
||||
$c = [];
|
||||
$c['Created'] = $this->humanTiming($obj['Created']);
|
||||
@@ -830,14 +834,14 @@ class DockerClient {
|
||||
$c['Tags'] = array_map('htmlspecialchars', $obj['RepoTags'] ?? []);
|
||||
$c['Repository'] = vsprintf('%1$s/%2$s', preg_split("#[:\/]#", DockerUtil::ensureImageTag($obj['RepoTags'][0])));
|
||||
$c['usedBy'] = $this->usedBy($c['Id']);
|
||||
DockerUtil::$allImagesCache[$c['Id']] = $c;
|
||||
$this::$allImagesCache[$c['Id']] = $c;
|
||||
}
|
||||
return DockerUtil::$allImagesCache;
|
||||
return $this::$allImagesCache;
|
||||
}
|
||||
|
||||
public function flushCaches() {
|
||||
DockerUtil::$allContainersCache = null;
|
||||
DockerUtil::$allImagesCache = null;
|
||||
$this::$allContainersCache = null;
|
||||
$this::$allImagesCache = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -846,9 +850,6 @@ class DockerClient {
|
||||
######################################
|
||||
class DockerUtil {
|
||||
|
||||
public static $allContainersCache = null;
|
||||
public static $allImagesCache = null;
|
||||
|
||||
public static function ensureImageTag($image) {
|
||||
list($strRepo, $strTag) = explode(':', $image.':');
|
||||
if (strpos($strRepo, 'sha256:') === 0) {
|
||||
|
||||
@@ -17,6 +17,7 @@ $docroot = $docroot ?? $_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp';
|
||||
// Add the Docker JSON client
|
||||
require_once "$docroot/plugins/dynamix.docker.manager/include/DockerClient.php";
|
||||
|
||||
$user_prefs = $dockerManPaths['user-prefs'];
|
||||
$DockerClient = new DockerClient();
|
||||
$DockerTemplates = new DockerTemplates();
|
||||
|
||||
@@ -26,17 +27,23 @@ if (!$all_containers) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (file_exists($user_prefs)) {
|
||||
$prefs = parse_ini_file($user_prefs); $sort = [];
|
||||
foreach ($all_containers as $ct) $sort[] = array_search($ct['Name'],$prefs) ?? 999;
|
||||
array_multisort($sort,SORT_NUMERIC,$all_containers);
|
||||
}
|
||||
|
||||
// Read network settings
|
||||
extract(parse_ini_file('state/network.ini',true));
|
||||
|
||||
// Read container info
|
||||
$all = $DockerTemplates->getAllInfo();
|
||||
$all_info = $DockerTemplates->getAllInfo();
|
||||
$menu = [];
|
||||
$docker = ['var docker=[];'];
|
||||
|
||||
foreach ($all_containers as $ct) {
|
||||
$name = $ct['Name'];
|
||||
$info = &$all[$name];
|
||||
$info = &$all_info[$name];
|
||||
$mode = $ct['NetworkMode'];
|
||||
$id = $ct['Id'];
|
||||
$imageID = $ct['ImageId'];
|
||||
@@ -80,7 +87,7 @@ foreach ($all_containers as $ct) {
|
||||
echo "<div id='$id' style='display:block; cursor:pointer'><div style='position:relative;width:48px;height:48px;margin:0px auto'>";
|
||||
echo "<img src='".htmlspecialchars($icon)."' class='".htmlspecialchars($status)."' style='position:absolute;top:0;bottom:0;left:0;right:0;width:48px;height:48px'>";
|
||||
echo "<i class='fa iconstatus fa-$shape $status' title='".htmlspecialchars($status)."'></i></div></div>";
|
||||
echo "</td><td>";
|
||||
echo "</td><td class='ct-name'>";
|
||||
if ($template) {
|
||||
echo "<a class='exec' onclick=\"editContainer('".addslashes(htmlspecialchars($name))."','".addslashes(htmlspecialchars($template))."')\">".htmlspecialchars($name)."</a>";
|
||||
} else {
|
||||
@@ -109,7 +116,9 @@ foreach ($all_containers as $ct) {
|
||||
echo "<td style='white-space:nowrap'><span class='docker_readmore'>".implode('<br>',$ports)."</span></td>";
|
||||
echo "<td style='word-break:break-all'><span class='docker_readmore'>".implode('<br>',$paths)."</span></td>";
|
||||
echo "<td><input type='checkbox' class='autostart' container='".htmlspecialchars($name)."'".($info['autostart'] ? ' checked':'')."></td>";
|
||||
echo "<td><a class='log' onclick=\"containerLogs('".addslashes(htmlspecialchars($name))."','$id',false,false)\"><img class='basic' src='/plugins/dynamix/icons/log.png'><div class='advanced' style='width:124px;'>".htmlspecialchars(str_replace('Up','Uptime',$ct['Status']))."</div><div class='advanced'>Created ".htmlspecialchars($ct['Created'])."</div></a></td></tr>";
|
||||
echo "<td><a class='log' onclick=\"containerLogs('".addslashes(htmlspecialchars($name))."','$id',false,false)\"><img class='basic' src='/plugins/dynamix/icons/log.png'><div class='advanced'>";
|
||||
echo htmlspecialchars(str_replace('Up','Uptime',$ct['Status']))."</div><div class='advanced' style='margin-top:4px'>Created ".htmlspecialchars($ct['Created'])."</div></a></td>";
|
||||
echo "<td style='text-align:right;padding-right:12px'><a href='#' title='Move row up'><i class='fa fa-arrow-up up'></i></a> <a href='#' title='Move row down'><i class='fa fa-arrow-down down'></i></a></td></tr>";
|
||||
}
|
||||
foreach ($DockerClient->getDockerImages() as $image) {
|
||||
if (count($image['usedBy'])) continue;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<?PHP
|
||||
/* Copyright 2005-2017, Lime Technology
|
||||
* Copyright 2014-2017, Guilherme Jardim, Eric Schultz, Jon Panozzo.
|
||||
/* Copyright 2005-2018, Lime Technology
|
||||
* Copyright 2014-2018, Guilherme Jardim, Eric Schultz, Jon Panozzo.
|
||||
* Copyright 2012-2018, 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,
|
||||
@@ -14,13 +15,12 @@
|
||||
$docroot = $docroot ?? $_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp';
|
||||
require_once "$docroot/plugins/dynamix.docker.manager/include/DockerClient.php";
|
||||
|
||||
// Autostart file
|
||||
global $dockerManPaths;
|
||||
$autostart_file = $dockerManPaths['autostart-file'];
|
||||
$template_repos = $dockerManPaths['template-repos'];
|
||||
$user_prefs = $dockerManPaths['user-prefs'];
|
||||
|
||||
// Update the start/stop configuration
|
||||
if ($_POST['action'] == "autostart" ){
|
||||
if ($_POST['action'] == 'autostart' ){
|
||||
$json = ($_POST['response'] == 'json') ? true : false;
|
||||
|
||||
if (!$json) readfile("$docroot/update.htm");
|
||||
@@ -28,21 +28,27 @@ if ($_POST['action'] == "autostart" ){
|
||||
$container = urldecode(($_POST['container']));
|
||||
unset($_POST['container']);
|
||||
|
||||
$allAutoStart = @file($autostart_file, FILE_IGNORE_NEW_LINES);
|
||||
if ($allAutoStart===FALSE) $allAutoStart = [];
|
||||
$allAutoStart = @file($autostart_file, FILE_IGNORE_NEW_LINES) ?: [];
|
||||
$key = array_search($container, $allAutoStart);
|
||||
if ($key===FALSE) {
|
||||
if ($key===false) {
|
||||
array_push($allAutoStart, $container);
|
||||
if ($json) echo json_encode(['autostart' => true]);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
unset($allAutoStart[$key]);
|
||||
if ($json) echo json_encode(['autostart' => false]);
|
||||
}
|
||||
file_put_contents($autostart_file, implode(PHP_EOL, $allAutoStart).(count($allAutoStart)? PHP_EOL : ""));
|
||||
// sort containers for start-up
|
||||
if (file_exists($user_prefs)) {
|
||||
$prefs = parse_ini_file($user_prefs); $sort = [];
|
||||
foreach ($allAutoStart as $ct) $sort[] = array_search($ct,$prefs) ?? 999;
|
||||
array_multisort($sort,SORT_NUMERIC,$allAutoStart);
|
||||
} else {
|
||||
natcasesort($allAutoStart);
|
||||
}
|
||||
$allAutoStart ? file_put_contents($autostart_file, implode(PHP_EOL, $allAutoStart).PHP_EOL) : @unlink($autostart_file);
|
||||
}
|
||||
|
||||
if ($_POST['#action'] == "templates" ){
|
||||
if ($_POST['#action'] == 'templates' ){
|
||||
readfile("$docroot/update.htm");
|
||||
$repos = $_POST['template_repos'];
|
||||
file_put_contents($template_repos, $repos);
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
<?PHP
|
||||
/* Copyright 2005-2018, Lime Technology
|
||||
* Copyright 2015-2018, Derek Macias, Eric Schultz, Jon Panozzo.
|
||||
* Copyright 2012-2018, 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.
|
||||
*/
|
||||
?>
|
||||
<?
|
||||
$docroot = $docroot ?? $_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp';
|
||||
require_once "$docroot/plugins/dynamix.docker.manager/include/DockerClient.php";
|
||||
|
||||
$autostart_file = $dockerManPaths['autostart-file'];
|
||||
$user_prefs = $dockerManPaths['user-prefs'];
|
||||
|
||||
if (isset($_POST['reset'])) {
|
||||
@unlink($user_prefs);
|
||||
if (file_exists($autostart_file)) {
|
||||
$allAutoStart = file($autostart_file, FILE_IGNORE_NEW_LINES);
|
||||
natcasesort($allAutoStart);
|
||||
file_put_contents($autostart_file, implode(PHP_EOL, $allAutoStart).PHP_EOL);
|
||||
}
|
||||
} else {
|
||||
$names = explode(';',$_POST['names']);
|
||||
$index = explode(';',$_POST['index']);
|
||||
$save = []; $i = 0;
|
||||
|
||||
foreach ($names as $name) if ($name) $save[] = $index[$i++]."=\"".$name."\""; else $i++;
|
||||
file_put_contents($user_prefs, implode("\n",$save)."\n");
|
||||
|
||||
// sort containers for start-up
|
||||
if (file_exists($autostart_file)) {
|
||||
$prefs = parse_ini_file($user_prefs); $sort = [];
|
||||
$allAutoStart = file($autostart_file, FILE_IGNORE_NEW_LINES);
|
||||
foreach ($allAutoStart as $ct) $sort[] = array_search($ct,$prefs) ?? 999;
|
||||
array_multisort($sort,SORT_NUMERIC,$allAutoStart);
|
||||
file_put_contents($autostart_file, implode(PHP_EOL, $allAutoStart).PHP_EOL);
|
||||
}
|
||||
}
|
||||
?>
|
||||
@@ -111,7 +111,7 @@ div.PanelText{display:none;}
|
||||
th.five{width:5%}
|
||||
</style>
|
||||
<table class="tablesorter shift kvm" id="kvm_table">
|
||||
<thead><tr><th><i class="fa fa-th-list"></i></th><th>Name</th><th>Description</th><th>CPUs</th><th>Memory</th><th>vDisks</th><th>Graphics</th><th class="five">Autostart</th><th class="five"><i class="fa fa-sort"></i></th></tr></thead>
|
||||
<thead><tr><th><i class="fa fa-th-list"></i></th><th>Name</th><th>Description</th><th>CPUs</th><th>Memory</th><th>vDisks</th><th>Graphics</th><th class="five">Autostart</th><th class="five" style="text-align:right;padding-right:24px"><a href="#" style="cursor:hand" onclick="resetSorting()" title="Reset sorting"><i class="fa fa-sort"></i></a></th></tr></thead>
|
||||
<tbody id="kvm_list"><tr><td colspan='9' style='text-align:center;padding:24px'><i class='fa fa-circle-o-notch fa-spin fa-3x fa-fw'></i></td></tr></tbody>
|
||||
</table>
|
||||
<input type="button" onclick="addVM()" id="btnAddVM" value="Add VM" style="display:none">
|
||||
@@ -136,6 +136,10 @@ function resize(bind) {
|
||||
}
|
||||
}
|
||||
<?endif;?>
|
||||
function resetSorting() {
|
||||
$('input[type=button]').prop('disabled',true);
|
||||
$.post('/plugins/dynamix.vm.manager/include/UserPrefs.php',{reset:true},function(){loadlist();});
|
||||
}
|
||||
function loadlist() {
|
||||
$.get('/plugins/dynamix.vm.manager/include/VMMachines.php',function(d) {
|
||||
var data = d.split(/\0/);
|
||||
|
||||
@@ -12,12 +12,17 @@
|
||||
*/
|
||||
?>
|
||||
<?
|
||||
$prefs = '/boot/config/plugins/dynamix.vm.manager';
|
||||
$names = explode(';',$_POST['names']);
|
||||
$index = explode(';',$_POST['index']);
|
||||
$save = []; $i = 0;
|
||||
$user_prefs = '/boot/config/plugins/dynamix.vm.manager/userprefs.cfg';
|
||||
|
||||
foreach ($names as $name) if ($name) $save[] = $index[$i++]."=\"".$name."\""; else $i++;
|
||||
if (!is_dir($prefs)) mkdir($prefs);
|
||||
file_put_contents("$prefs/userprefs.cfg", implode("\n",$save)."\n");
|
||||
if (isset($_POST['reset'])) {
|
||||
@unlink($user_prefs);
|
||||
} else {
|
||||
$names = explode(';',$_POST['names']);
|
||||
$index = explode(';',$_POST['index']);
|
||||
$save = []; $i = 0;
|
||||
|
||||
foreach ($names as $name) if ($name) $save[] = $index[$i++]."=\"".$name."\""; else $i++;
|
||||
if (!is_dir(dirname($user_prefs))) mkdir(dirname($user_prefs));
|
||||
file_put_contents($user_prefs, implode("\n",$save)."\n");
|
||||
}
|
||||
?>
|
||||
|
||||
@@ -16,18 +16,18 @@ $docroot = $docroot ?? $_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp';
|
||||
require_once "$docroot/webGui/include/Helpers.php";
|
||||
require_once "$docroot/plugins/dynamix.vm.manager/include/libvirt_helpers.php";
|
||||
|
||||
$cfg = '/boot/config/plugins/dynamix.vm.manager/userprefs.cfg';
|
||||
$user_prefs = '/boot/config/plugins/dynamix.vm.manager/userprefs.cfg';
|
||||
$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>';
|
||||
return;
|
||||
}
|
||||
if (file_exists($cfg)) {
|
||||
$prefs = parse_ini_file($cfg); $sort = [];
|
||||
if (file_exists($user_prefs)) {
|
||||
$prefs = parse_ini_file($user_prefs); $sort = [];
|
||||
foreach ($vms as $vm) $sort[] = array_search($vm,$prefs) ?? 999;
|
||||
array_multisort($sort,SORT_NUMERIC,$vms);
|
||||
} else {
|
||||
natsort($vms);
|
||||
natcasesort($vms);
|
||||
}
|
||||
$i = 0;
|
||||
$menu = [];
|
||||
@@ -89,7 +89,7 @@ foreach ($vms as $vm) {
|
||||
echo "<td title='$diskdesc'>$disks</td>";
|
||||
echo "<td>$graphics</td>";
|
||||
echo "<td><input class='autostart' type='checkbox' name='auto_{$vm}' title='Toggle VM auostart' uuid='$uuid' $auto></td>";
|
||||
echo "<td><a href='#' title='Move row up'><i class='fa fa-arrow-up up'></i></a> <a href='#' title='Move row down'><i class='fa fa-arrow-down down'></i></a></td></tr>";
|
||||
echo "<td style='text-align:right;padding-right:12px'><a href='#' title='Move row up'><i class='fa fa-arrow-up up'></i></a> <a href='#' title='Move row down'><i class='fa fa-arrow-down down'></i></a></td></tr>";
|
||||
|
||||
/* Disk device information */
|
||||
echo "<tr id='name".($i++)."' style='display:none'>";
|
||||
|
||||
@@ -15,9 +15,20 @@
|
||||
$docroot = $docroot ?? $_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp';
|
||||
require_once "$docroot/plugins/dynamix.vm.manager/include/libvirt_helpers.php";
|
||||
|
||||
$user_prefs = '/boot/config/plugins/dynamix.vm.manager/userprefs.cfg';
|
||||
|
||||
$act = $_POST['action'];
|
||||
$vms = $lv->get_domains();
|
||||
|
||||
if (file_exists($user_prefs)) {
|
||||
$prefs = parse_ini_file($user_prefs); $sort = [];
|
||||
foreach ($vms as $vm) $sort[] = array_search($vm,$prefs) ?? 999;
|
||||
array_multisort($sort,SORT_NUMERIC,$vms);
|
||||
} else {
|
||||
natcasesort($vms);
|
||||
}
|
||||
if ($act=='stop') $vms = array_reverse($vms);
|
||||
|
||||
foreach ($vms as $vm) {
|
||||
$res = $lv->get_domain_by_name($vm);
|
||||
$uuid = $lv->domain_get_uuid($res);
|
||||
|
||||
@@ -20,14 +20,22 @@ require_once "$docroot/plugins/dynamix.vm.manager/include/libvirt_helpers.php";
|
||||
$display = $_POST['display'];
|
||||
|
||||
if (pgrep('dockerd')!==false && ($display=='icons' || $display=='docker')) {
|
||||
$DockerClient = new DockerClient();
|
||||
$user_prefs = $dockerManPaths['user-prefs'];
|
||||
$DockerClient = new DockerClient();
|
||||
$DockerTemplates = new DockerTemplates();
|
||||
$containers = $DockerClient->getDockerContainers() ?: [];
|
||||
$Allinfo = $DockerTemplates->getAllInfo();
|
||||
$all_containers = $DockerClient->getDockerContainers();
|
||||
$all_info = $DockerTemplates->getAllInfo();
|
||||
$menu = [];
|
||||
foreach ($containers as $ct) {
|
||||
|
||||
if (file_exists($user_prefs)) {
|
||||
$prefs = parse_ini_file($user_prefs); $sort = [];
|
||||
foreach ($all_containers as $ct) $sort[] = array_search($ct['Name'],$prefs) ?? 999;
|
||||
array_multisort($sort,SORT_NUMERIC,$all_containers);
|
||||
}
|
||||
|
||||
foreach ($all_containers as $ct) {
|
||||
$name = $ct['Name'];
|
||||
$info = &$Allinfo[$name];
|
||||
$info = &$all_info[$name];
|
||||
$id = $ct['Id'];
|
||||
$imageID = $ct['ImageId'];
|
||||
$is_autostart = $info['autostart'] ? 'true':'false';
|
||||
@@ -50,14 +58,14 @@ if (pgrep('dockerd')!==false && ($display=='icons' || $display=='docker')) {
|
||||
}
|
||||
|
||||
if (pgrep('libvirtd')!==false && ($display=='icons' || $display=='vms')) {
|
||||
$txt = '/boot/config/plugins/dynamix.vm.manager/userprefs.txt';
|
||||
$user_prefs = '/boot/config/plugins/dynamix.vm.manager/userprefs.cfg';
|
||||
$vms = $lv->get_domains();
|
||||
if (file_exists($txt)) {
|
||||
$prefs = parse_ini_file($txt); $sort = [];
|
||||
foreach ($vms as $vm) $sort[] = $prefs[$vm] ?? 999;
|
||||
if (file_exists($user_prefs)) {
|
||||
$prefs = parse_ini_file($user_prefs); $sort = [];
|
||||
foreach ($vms as $vm) $sort[] = array_search($vm,$prefs) ?? 999;
|
||||
array_multisort($sort,SORT_NUMERIC,$vms);
|
||||
} else {
|
||||
natsort($vms);
|
||||
natcasesort($vms);
|
||||
}
|
||||
foreach ($vms as $vm) {
|
||||
$res = $lv->get_domain_by_name($vm);
|
||||
|
||||
Reference in New Issue
Block a user