Merge branch 'master' into refactor/web-component-updates

This commit is contained in:
Zack Spear
2023-11-07 16:18:42 -08:00
committed by GitHub
404 changed files with 3514 additions and 3212 deletions

77
.vscode/settings.json vendored
View File

@@ -4,5 +4,80 @@
},
"prettier.tabWidth": 4,
"editor.tabSize": 4,
"editor.indentSize": "tabSize"
"editor.indentSize": "tabSize",
"intelephense.stubs": [
"apache",
"bcmath",
"bz2",
"calendar",
"com_dotnet",
"Core",
"ctype",
"curl",
"date",
"dba",
"dom",
"enchant",
"exif",
"FFI",
"fileinfo",
"filter",
"fpm",
"ftp",
"gd",
"gettext",
"gmp",
"hash",
"iconv",
"imap",
"intl",
"json",
"ldap",
"libxml",
"mbstring",
"meta",
"mysqli",
"oci8",
"odbc",
"openssl",
"pcntl",
"pcre",
"PDO",
"pdo_ibm",
"pdo_mysql",
"pdo_pgsql",
"pdo_sqlite",
"pgsql",
"Phar",
"posix",
"pspell",
"random",
"readline",
"Reflection",
"session",
"shmop",
"SimpleXML",
"snmp",
"soap",
"sockets",
"sodium",
"SPL",
"sqlite3",
"standard",
"superglobals",
"sysvmsg",
"sysvsem",
"sysvshm",
"tidy",
"tokenizer",
"xml",
"xmlreader",
"xmlrpc",
"xmlwriter",
"xsl",
"Zend OPcache",
"zip",
"zlib",
"libvirt-php"
]
}

View File

@@ -1527,6 +1527,12 @@ The display settings below determine how items are displayed on screen. Use thes
You can experiment with these settings as desired, they only affect visual properties.
:end
:display_width_help:
**Boxed** is the legacy setting which constrains the content width to maximum 1920 pixels
**Unlimited** allows content to use all available width, which maybe useful on wide screens
:end
:display_font_size_help:
Changes the font size in the GUI. This is a per device setting.
:end
@@ -1581,6 +1587,10 @@ Make sure any newly entered values represent the selected temperature unit.
Stopping the VM Manager will first attempt to shutdown all running VMs. After 60 seconds, any remaining VM instances will be terminated.
:end
:vms_disable_help:
Stop VMs from Autostarting\Starting when VM Manager starts or open is run from the gui to start, error message will be seen.
:end
:vms_libvirt_volume_help:
This is the libvirt volume.
:end

View File

@@ -3,8 +3,8 @@ Title="UPS Details"
Tag="battery-3"
---
<?PHP
/* Copyright 2005-2022, Lime Technology
* Copyright 2012-2022, Bergware International.
/* Copyright 2005-2023, Lime Technology
* Copyright 2012-2023, Bergware International.
* Copyright 2015, Dan Landon.
*
* This program is free software; you can redistribute it and/or

View File

@@ -5,8 +5,8 @@ Icon="icon-ups"
Tag="battery-3"
---
<?PHP
/* Copyright 2005-2022, Lime Technology
* Copyright 2012-2022, Bergware International.
/* Copyright 2005-2023, Lime Technology
* Copyright 2012-2023, Bergware International.
* Copyright 2015, Dan Landon.
*
* This program is free software; you can redistribute it and/or
@@ -22,13 +22,6 @@ Tag="battery-3"
$sName = "dynamix.apcupsd";
$cfg = parse_plugin_cfg($sName);
?>
<style>
table.ups thead tr th{width:16.6%;padding-left:10px}
table.ups tbody tr td{padding-left:10px;font-weight:bold}
tr.ups{height:3rem;line-height:3rem}
i.ups{margin-right:8px}
</style>
<script>
function toggleCustomCable(form) {
var readonly = form.UPSCABLE.value != 'custom';

View File

@@ -12,7 +12,8 @@
*/
?>
<?
$docroot = $docroot ?? $_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp';
$docroot ??= ($_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp');
// add translations
$_SERVER['REQUEST_URI'] = 'settings';
require_once "$docroot/webGui/include/Translations.php";

View File

@@ -1,6 +1,6 @@
<?PHP
/* Copyright 2005-2018, Lime Technology
* Copyright 2012-2020, Bergware International.
/* Copyright 2005-2023, Lime Technology
* Copyright 2012-2023, Bergware International.
* Copyright 2015, Dan Landon.
*
* This program is free software; you can redistribute it and/or

View File

@@ -0,0 +1,4 @@
table.ups thead tr th{width:16.6%;padding-left:10px}
table.ups tbody tr td{padding-left:10px;font-weight:bold}
tr.ups{height:3rem;line-height:3rem}
i.ups{margin-right:8px}

View File

@@ -3,9 +3,9 @@ Cond="(pgrep('dockerd')!==false)"
Markdown="false"
---
<?PHP
/* Copyright 2005-2020, Lime Technology
* Copyright 2014-2020, Guilherme Jardim, Eric Schultz, Jon Panozzo.
* Copyright 2012-2020, Bergware International.
/* Copyright 2005-2023, Lime Technology
* Copyright 2012-2023, Bergware International.
* Copyright 2014-2021, Guilherme Jardim, Eric Schultz, Jon Panozzo.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2,

View File

@@ -5,7 +5,8 @@ Lock="true"
Cond="exec(\"grep -o '^DOCKER_ENABLED=.yes' /boot/config/docker.cfg 2>/dev/null\")"
---
<?PHP
/* Copyright 2005-2021, Lime Technology
/* Copyright 2005-2023, Lime Technology
* Copyright 2012-2023, Bergware International.
* Copyright 2014-2021, Guilherme Jardim, Eric Schultz, Jon Panozzo.
*
* This program is free software; you can redistribute it and/or

View File

@@ -7,8 +7,8 @@ Nchan="docker_load:stop"
---
<?PHP
/* Copyright 2005-2023, Lime Technology
* Copyright 2014-2023, Guilherme Jardim, Eric Schultz, Jon Panozzo.
* Copyright 2012-2023, Bergware International.
* Copyright 2014-2021, Guilherme Jardim, Eric Schultz, Jon Panozzo.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2,
@@ -29,20 +29,7 @@ $cpus = cpu_list();
<link type="text/css" rel="stylesheet" href="<?autov('/webGui/styles/jquery.ui.css')?>">
<link type="text/css" rel="stylesheet" href="<?autov('/webGui/styles/jquery.switchbutton.css')?>">
<link type="text/css" rel="stylesheet" href="<?autov("/plugins/dynamix.docker.manager/styles/style-$theme.css")?>">
<style>
.basic{display:block}
.advanced{display:none;white-space:nowrap}
.log{cursor:zoom-in}
.exec{cursor:pointer}
table#docker_containers{text-align:left}
th.five{width:5%}
th.nine{width:9%}
th.load{width:140px}
input.wait{width:24px;margin:0 4px;padding:0 5px;border:none;box-shadow:none;background-color:transparent}
table tbody td{line-height:normal}
i.mover{margin-right:8px;display:none}
#resetsort{margin-left:12px;display:inline-block;width:32px}
</style>
<table id="docker_containers" class="tablesorter shift">
<thead><tr><th><a id="resetsort" class="nohand" onclick="resetSorting()" title="_(Reset sorting)_"><i class="fa fa-th-list"></i></a>_(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="load advanced">_(CPU & Memory load)_</th><th class="nine">_(Autostart)_</th><th class="five">_(Uptime)_</th></tr></thead>
<tbody id="docker_list"><tr><td colspan='8'></td></tr></tbody>

View File

@@ -5,8 +5,8 @@ Tag="icon-docker"
---
<?PHP
/* Copyright 2005-2023, Lime Technology
* Copyright 2014-2023, Guilherme Jardim, Eric Schultz, Jon Panozzo.
* Copyright 2012-2023, Bergware International.
* Copyright 2014-2021, Guilherme Jardim, Eric Schultz, Jon Panozzo.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2,
@@ -106,31 +106,6 @@ $bgcolor = strstr('white,azure',$display['theme']) ? '#f2f2f2' : '#1c1c1c';
?>
<link type="text/css" rel="stylesheet" href="<?autov('/webGui/styles/jquery.filetree.css')?>">
<link type="text/css" rel="stylesheet" href="<?autov('/webGui/styles/jquery.switchbutton.css')?>">
<style>
.errortext{color:#EF3D47;display:none;margin-left:20px}
.fileTree{background:<?=$bgcolor?>;width:300px;max-height:150px;overflow-y:scroll;overflow-x:hidden;position:absolute;z-index:100;display:none}
.basic{display:inline-block}
.advanced{display:none}
select.mask{min-width:0;margin:0 10px 0 4px}
select.net{min-width:0;margin:0 4px 0 2px}
select option.hide{display:none}
input.ip4{width:100px;margin:0 4px 0 1px}
input.ip6{width:140px;margin:0 4px}
input.gw4{width:100px;margin:0 4px 0 1px}
input.gw6{width:160px;margin:0 4px}
input.pool6{width:40px;margin:0 4px 0 1px}
span.net{margin-left:4px;margin-right:2px}
span.ip4{display:inline-block;width:260px}
span.ip6{display:inline-block;width:310px}
span.gw4{display:inline-block;width:200px}
span.gw6{display:inline-block;width:270px}
span.nonexist{margin-left:20px}
<?if (strstr('white,azure',$display['theme'])):?>
span.disabled{color:#B0B0B0}
<?else:?>
span.disabled{color:#404040}
<?endif;?>
</style>
<span class="status vhshift"><input type="checkbox" class="advancedview"></span>
<form markdown="1" id="settingsForm" name="settingsForm" method="POST" action="/update.php" target="progressFrame" onsubmit="return prepareDocker(this)">
@@ -257,16 +232,14 @@ _(Template Authoring Mode)_:
:docker_authoring_mode_help:
<?if ($bridge):?>
_(Docker custom network type)_:
: <select name="DOCKER_NETWORK_TYPE">
<?=mk_option(_var($dockercfg,'DOCKER_NETWORK_TYPE'), '1', _('ipvlan'))?>
<?=mk_option(_var($dockercfg,'DOCKER_NETWORK_TYPE'), '', _('macvlan'))?>
<?=mk_option(_var($dockercfg,'DOCKER_NETWORK_TYPE'), '1', _('ipvlan'), $bridge?'':'disabled')?>
<?=mk_option(_var($dockercfg,'DOCKER_NETWORK_TYPE'), '', _('macvlan'), $bridge?'':'selected')?>
</select>&nbsp;_(Please read the Help carefully)_. _(Misconfiguration can cause problems)_.
:docker_custom_network_type_help:
<?endif;?>
_(Host access to custom networks)_:
: <select name="DOCKER_ALLOW_ACCESS">
<?=mk_option(_var($dockercfg,'DOCKER_ALLOW_ACCESS'), '', _('Disabled'))?>
@@ -465,13 +438,11 @@ _(Docker LOG rotation)_:
:docker_log_rotation_active_help:
<?if ($bridge):?>
_(Docker custom network type)_:
: <?=_var($dockercfg,'DOCKER_NETWORK_TYPE')=='1' ? _('ipvlan') : _('macvlan')?>
: <?=_var($dockercfg,'DOCKER_NETWORK_TYPE')!='1' || !$bridge ? _('macvlan') : _('ipvlan')?>
:docker_custom_network_type_help:
<?endif;?>
_(Host access to custom networks)_:
: <?=_var($dockercfg,'DOCKER_ALLOW_ACCESS')=='yes' ? _('Enabled') : _('Disabled')?>

View File

@@ -3,9 +3,9 @@ Cond="(pgrep('dockerd')!==false)"
Markdown="false"
---
<?PHP
/* Copyright 2005-2020, Lime Technology
* Copyright 2014-2020, Guilherme Jardim, Eric Schultz, Jon Panozzo.
* Copyright 2012-2020, Bergware International.
/* Copyright 2005-2023, Lime Technology
* Copyright 2012-2023, Bergware International.
* Copyright 2014-2021, Guilherme Jardim, Eric Schultz, Jon Panozzo.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2,

View File

@@ -1,7 +1,7 @@
<?PHP
/* Copyright 2005-2022, Lime Technology
* Copyright 2014-2022, Guilherme Jardim, Eric Schultz, Jon Panozzo.
* Copyright 2012-2022, Bergware International.
/* Copyright 2005-2023, Lime Technology
* Copyright 2012-2023, Bergware International.
* Copyright 2014-2021, Guilherme Jardim, Eric Schultz, Jon Panozzo.
*
* 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,7 +12,7 @@
*/
?>
<?
$docroot = $docroot ?? $_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp';
$docroot ??= ($_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp');
require_once "$docroot/plugins/dynamix.docker.manager/include/DockerClient.php";
$user_prefs = $dockerManPaths['user-prefs'];

View File

@@ -1,7 +1,7 @@
<?PHP
/* Copyright 2005-2023, Lime Technology
* Copyright 2015-2023, Guilherme Jardim, Eric Schultz, Jon Panozzo.
* Copyright 2012-2023, Bergware International.
* Copyright 2014-2021, Guilherme Jardim, Eric Schultz, Jon Panozzo.
*
* 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,10 +12,8 @@
*/
?>
<?
$docroot = $docroot ?? $_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp';
$docroot ??= ($_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp');
require_once "$docroot/plugins/dynamix.docker.manager/include/DockerClient.php";
libxml_use_internal_errors(true);
require_once "$docroot/webGui/include/Helpers.php";
extract(parse_plugin_cfg('dynamix',true));
@@ -277,18 +275,6 @@ $bgcolor = strstr('white,azure',$display['theme']) ? '#f2f2f2' : '#1c1c1c';
<link type="text/css" rel="stylesheet" href="<?autov("/webGui/styles/jquery.filetree.css")?>">
<link type="text/css" rel="stylesheet" href="<?autov("/plugins/dynamix.docker.manager/styles/style-{$display['theme']}.css")?>">
<style>
.noshow,.advanced{display:none}
.fileTree{width:240px;max-height:200px;overflow-y:scroll;overflow-x:hidden;position:absolute;display:none;background:<?=$bgcolor?>}
.required:after{content:" *";color:#E80000}
span.boxed{display:inline-block;line-height:normal;white-space:normal;width:56%}
span.cpu,label.checkbox{display:inline-block;width:32px}
span.ct{display:inline-block;width:230px}
span.net{display:inline-block;width:120px}
span.ip{display:inline-block;width:160px}
dl,dt,dd{line-height:normal!important}
</style>
<script src="<?autov('/webGui/javascript/jquery.switchbutton.js')?>"></script>
<script src="<?autov('/webGui/javascript/jquery.filetree.js')?>" charset="utf-8"></script>
<script src="<?autov('/plugins/dynamix.vm.manager/javascript/dynamix.vm.manager.js')?>"></script>
@@ -386,6 +372,13 @@ function getVal(el, name) {
}
}
function dialogStyle() {
$('.ui-dialog-titlebar-close').css({'display':'none'});
$('.ui-dialog-title').css({'text-align':'center','width':'100%','font-size':'1.8rem'});
$('.ui-dialog-content').css({'padding-top':'15px','vertical-align':'bottom'});
$('.ui-button-text').css({'padding':'0px 5px'});
}
function addConfigPopup() {
var title = "_(Add Configuration)_";
var popup = $("#dialogAddConfig");
@@ -403,11 +396,10 @@ function addConfigPopup() {
// Start Dialog section
popup.dialog({
title: title,
height: 'auto',
width: 900,
resizable: false,
width: 800,
modal: true,
show : {effect: 'fade' , duration: 250},
hide : {effect: 'fade' , duration: 250},
buttons: {
"_(Add)_": function() {
$(this).dialog("close");
@@ -439,11 +431,7 @@ function addConfigPopup() {
}
}
});
$(".ui-dialog .ui-dialog-titlebar").addClass('menu');
$('.ui-dialog .ui-dialog-titlebar-close').css({'display':'none'});
$(".ui-dialog .ui-dialog-title").css({'text-align':'center','width':'100%'});
$(".ui-dialog .ui-dialog-content").css({'padding-top':'15px','vertical-align':'bottom'});
$(".ui-button-text").css({'padding':'0px 5px'});
dialogStyle();
}
function editConfigPopup(num,disabled) {
@@ -477,11 +465,10 @@ function editConfigPopup(num,disabled) {
popup.find(".switch-button-background").css("margin-top", "6px");
popup.dialog({
title: title,
height: 'auto',
width: 900,
resizable: false,
width: 800,
modal: true,
show: {effect:'fade', duration: 250},
hide: {effect:'fade', duration: 250},
buttons: {
"_(Save)_": function() {
$(this).dialog("close");
@@ -522,11 +509,7 @@ function editConfigPopup(num,disabled) {
}
}
});
$(".ui-dialog .ui-dialog-titlebar").addClass('menu');
$('.ui-dialog .ui-dialog-titlebar-close').css({'display':'none'});
$(".ui-dialog .ui-dialog-title").css({'text-align':'center','width':'100%'});
$(".ui-dialog .ui-dialog-content").css({'padding-top':'15px','vertical-align':'bottom'});
$(".ui-button-text").css({'padding':'0px 5px'});
dialogStyle();
$('.desc_readmore').readmore({maxHeight:10});
}
@@ -1009,7 +992,7 @@ _(Password Mask)_:
<input type="hidden" name="confRequired[]" value="{7}">
<input type="hidden" name="confMask[]" value="{8}">
<span class="{11}">{0}:</span>
: <span class="boxed"><input type="text" name="confValue[]" default="{2}" value="{9}" autocomplete="off" spellcheck="false" {11}>{10}<br><span class='orange-text'>{12}: {1}</span><br><span class="orange-text">{4}</span><br>
: <span class="boxed"><input type="text" class="setting_input" name="confValue[]" default="{2}" value="{9}" autocomplete="off" spellcheck="false" {11}>{10}<br><span class='orange-text'>{12}: {1}</span><br><span class="orange-text">{4}</span><br></span>
</div>
<div markdown="1" id="templateAllocations" style="display:none">

View File

@@ -1,7 +1,7 @@
<?PHP
/* Copyright 2005-2023, Lime Technology
* Copyright 2014-2023, Guilherme Jardim, Eric Schultz, Jon Panozzo.
* Copyright 2012-2023, Bergware International.
* Copyright 2014-2021, Guilherme Jardim, Eric Schultz, Jon Panozzo.
*
* 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,10 +12,7 @@
*/
?>
<?
libxml_use_internal_errors(true); # Suppress any warnings from xml errors.
$docroot = $docroot ?? $_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp';
$docroot ??= ($_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp');
require_once "$docroot/plugins/dynamix.docker.manager/include/Helpers.php";
require_once "$docroot/webGui/include/Wrappers.php";
@@ -56,8 +53,8 @@ if (file_exists($docker_cfgfile) && exec("grep -Pom1 '_{$port}(_[0-9]+)?=' $dock
exec("sed -ri 's/_(BR0|BOND0|ETH0)(_[0-9]+)?=/_{$port}\\2=/' $docker_cfgfile");
}
$defaults = @parse_ini_file("$docroot/plugins/dynamix.docker.manager/default.cfg") ?: [];
$dockercfg = array_replace_recursive($defaults, @parse_ini_file($docker_cfgfile) ?: []);
$defaults = (array)@parse_ini_file("$docroot/plugins/dynamix.docker.manager/default.cfg");
$dockercfg = array_replace_recursive($defaults, (array)@parse_ini_file($docker_cfgfile));
function var_split($item, $i=0) {
return array_pad(explode(' ',$item),$i+1,'')[$i];
@@ -353,7 +350,6 @@ class DockerTemplates {
if (!$imgUrl) $imgUrl = $tmpIconUrl;
if (!$imgUrl || trim($imgUrl) == "/plugins/dynamix.docker.manager/images/question.png") return '';
$imageName = $contName ?: $name;
$iconRAM = sprintf('%s/%s-%s.png', $dockerManPaths['images-ram'], $contName, 'icon');
$icon = sprintf('%s/%s-%s.png', $dockerManPaths['images'], $contName, 'icon');
@@ -367,8 +363,8 @@ class DockerTemplates {
if (!is_file($icon) && is_file($iconRAM)) {
@copy($iconRAM,$icon);
}
if ( !is_file($iconRAM) ) {
exec("logger -t webGUI -- \"$imageName: Could not download icon $imgUrl\"");
if (!is_file($iconRAM)) {
exec("logger -t webGUI -- \"$contName: Could not download icon $imgUrl\"");
}
return (is_file($iconRAM)) ? str_replace($docroot, '', $iconRAM) : '';

View File

@@ -1,7 +1,7 @@
<?PHP
/* Copyright 2005-2023, Lime Technology
* Copyright 2014-2023, Guilherme Jardim, Eric Schultz, Jon Panozzo.
* Copyright 2012-2023, Bergware International.
* Copyright 2014-2021, Guilherme Jardim, Eric Schultz, Jon Panozzo.
*
* 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,8 +12,7 @@
*/
?>
<?
$docroot = $docroot ?? $_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp';
$docroot ??= ($_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp');
require_once "$docroot/webGui/include/Helpers.php";
require_once "$docroot/plugins/dynamix.docker.manager/include/DockerClient.php";
@@ -34,7 +33,7 @@ if (!$containers && !$images) {
}
if (file_exists($user_prefs)) {
$prefs = @parse_ini_file($user_prefs) ?: [];
$prefs = (array)@parse_ini_file($user_prefs);
$sort = [];
foreach ($containers as $ct) $sort[] = array_search($ct['Name'],$prefs);
array_multisort($sort,SORT_NUMERIC,$containers);
@@ -46,7 +45,7 @@ $allInfo = $DockerTemplates->getAllInfo();
$docker = [];
$null = '0.0.0.0';
$autostart = @file($autostart_file,FILE_IGNORE_NEW_LINES) ?: [];
$autostart = (array)@file($autostart_file,FILE_IGNORE_NEW_LINES);
$names = array_map('var_split',$autostart);
function my_lang_time($text) {
@@ -108,7 +107,7 @@ foreach ($containers as $ct) {
}
echo "<span class='outer'><span id='$id' $menu class='hand'>$image</span><span class='inner'><span class='appname $update'>$appname</span><br><i id='load-$id' class='fa fa-$shape $status $color'></i><span class='state'>"._($status)."</span></span></span>";
echo "<div class='advanced' style='margin-top:8px'>"._('Container ID').": $id<br>";
if ($ct['BaseImage']) echo "<i class='fa fa-cubes' style='margin-right:5px'></i>".htmlspecialchars(${ct['BaseImage']})."<br>";
if ($ct['BaseImage']) echo "<i class='fa fa-cubes' style='margin-right:5px'></i>".htmlspecialchars($ct['BaseImage'])."<br>";
echo _('By').": ";
$registry = $info['registry'];
[$author,$version] = my_explode(':',$ct['Image']);

View File

@@ -1,7 +1,7 @@
<?PHP
/* Copyright 2005-2022, Lime Technology
* Copyright 2014-2022, Guilherme Jardim, Eric Schultz, Jon Panozzo.
* Copyright 2012-2022, Bergware International.
/* Copyright 2005-2023, Lime Technology
* Copyright 2012-2023, Bergware International.
* Copyright 2014-2021, Guilherme Jardim, Eric Schultz, Jon Panozzo.
*
* 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,7 +12,7 @@
*/
?>
<?
$docroot = $docroot ?? $_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp';
$docroot ??= ($_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp');
require_once "$docroot/plugins/dynamix.docker.manager/include/DockerClient.php";
$ncsi = exec("wget --spider --no-check-certificate -nv -T10 -t1 https://www.msftncsi.com/ncsi.txt 2>&1|grep -o 'OK'")=='OK';

View File

@@ -1,7 +1,7 @@
<?PHP
/* Copyright 2005-2023, Lime Technology
* Copyright 2014-2023, Guilherme Jardim, Eric Schultz, Jon Panozzo.
* Copyright 2012-2023, Bergware International.
* Copyright 2014-2021, Guilherme Jardim, Eric Schultz, Jon Panozzo.
*
* 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,8 +12,7 @@
*/
?>
<?
$docroot = $docroot ?? $_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp';
$docroot ??= ($_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp');
require_once "$docroot/webGui/include/Secure.php";
require_once "$docroot/webGui/include/Wrappers.php";
require_once "$docroot/plugins/dynamix.docker.manager/include/DockerClient.php";

View File

@@ -1,7 +1,7 @@
<?PHP
/* Copyright 2005-2023, Lime Technology
* Copyright 2014-2023, Guilherme Jardim, Eric Schultz, Jon Panozzo.
* Copyright 2012-2023, Bergware International.
* Copyright 2014-2021, Guilherme Jardim, Eric Schultz, Jon Panozzo.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2,

View File

@@ -1,6 +1,7 @@
<?PHP
/* Copyright 2005-2018, Lime Technology
* Copyright 2012-2018, Bergware International.
/* Copyright 2005-2023, Lime Technology
* Copyright 2012-2023, Bergware International.
* Copyright 2014-2021, Guilherme Jardim, Eric Schultz, Jon Panozzo.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2,

View File

@@ -1,7 +1,7 @@
<?PHP
/* Copyright 2005-2021, Lime Technology
/* Copyright 2005-2023, Lime Technology
* Copyright 2012-2023, Bergware International.
* Copyright 2014-2021, Guilherme Jardim, Eric Schultz, Jon Panozzo.
* Copyright 2012-2021, 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,7 +12,7 @@
*/
?>
<?
$docroot = $docroot ?? $_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp';
$docroot ??= ($_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp');
require_once "$docroot/plugins/dynamix.docker.manager/include/DockerClient.php";
$autostart_file = $dockerManPaths['autostart-file'];
@@ -25,7 +25,7 @@ case 'autostart':
$container = urldecode(($_POST['container']));
$wait = $_POST['wait'];
$item = rtrim("$container $wait");
$autostart = @file($autostart_file, FILE_IGNORE_NEW_LINES) ?: [];
$autostart = (array)@file($autostart_file, FILE_IGNORE_NEW_LINES);
$key = array_search($item, $autostart);
if ($_POST['auto']=='true') {
if ($key===false) $autostart[] = $item;
@@ -48,7 +48,7 @@ case 'wait':
$container = urldecode(($_POST['container']));
$wait = $_POST['wait'];
$item = rtrim("$container $wait");
$autostart = file($autostart_file, FILE_IGNORE_NEW_LINES) ?: [];
$autostart = (array)@file($autostart_file, FILE_IGNORE_NEW_LINES);
$names = array_map('var_split', $autostart);
$autostart[array_search($container,$names)] = $item;
file_put_contents($autostart_file, implode("\n", $autostart)."\n");

View File

@@ -1,7 +1,7 @@
<?PHP
/* Copyright 2005-2018, Lime Technology
* Copyright 2015-2018, Derek Macias, Eric Schultz, Jon Panozzo.
* Copyright 2012-2018, Bergware International.
/* Copyright 2005-2023, Lime Technology
* Copyright 2012-2023, Bergware International.
* Copyright 2014-2021, Guilherme Jardim, Eric Schultz, Jon Panozzo.
*
* 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,7 +12,7 @@
*/
?>
<?
$docroot = $docroot ?? $_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp';
$docroot ??= ($_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp');
require_once "$docroot/plugins/dynamix.docker.manager/include/DockerClient.php";
$autostart_file = $dockerManPaths['autostart-file'];

View File

@@ -61,17 +61,15 @@ function popupWithIframe(title, cmd, reload, func) {
$('#iframe-popup').dialog({
autoOpen:true,
title:title,
height: 600,
width: 900,
draggable:true,
width: Math.min(Math.max(window.innerWidth/2,900),1600),
height: Math.max(window.innerHeight*3/5,600),
resizable:true,
modal:true,
show:{effect:'fade', duration:250},
hide:{effect:'fade', duration:250},
open:function(ev, ui) {
open:function(ev, ui){
$('#myIframe').attr('src', cmd);
},
close:function(event, ui) {
close:function(event, ui){
if (reload && !$('#myIframe').contents().find('#canvas').length) {
if (func) setTimeout(func+'()',0); else location = window.location.href;
} else {
@@ -79,13 +77,13 @@ function popupWithIframe(title, cmd, reload, func) {
}
}
});
$(".ui-dialog .ui-dialog-titlebar").addClass('menu');
$('.ui-dialog .ui-dialog-titlebar-close').text('X').prop('title',_('Close'));
$(".ui-dialog .ui-dialog-title").css({'text-align':'center','width':'100%'});
$(".ui-dialog .ui-dialog-content").css({'padding-top':'15px','vertical-align':'bottom'});
$('.ui-dialog-titlebar-close').css({'display':'none'});
$('.ui-dialog-title').css({'text-align':'center','width':'100%','font-size':'1.8rem'});
$('.ui-dialog-content').css({'padding-top':'15px','vertical-align':'bottom'});
$('.ui-button-text').css({'padding':'0px 5px'});
}
function execUpContainer(container) {
var title = _('Updating the container')+': '+container;
var title = _('Updating the container TEST')+': '+container;
var cmd = '/plugins/dynamix.docker.manager/include/CreateDocker.php?updateContainer=true&ct[]='+encodeURIComponent(container);
popupWithIframe(title, cmd, true, 'loadlist');
}

View File

@@ -12,8 +12,7 @@
*/
?>
<?
$docroot = $docroot ?? $_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp';
$docroot ??= ($_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp');
require_once "$docroot/webGui/include/Wrappers.php";
extract(parse_plugin_cfg('dynamix',true));
@@ -22,7 +21,7 @@ $_SERVER['REQUEST_URI'] = 'docker';
$login_locale = _var($display,'locale');
require_once "$docroot/webGui/include/Translations.php";
$unit = ['B','kB','MB','GB','TB','PB','EB','ZB','YB'];
$units = ['B','kB','MB','GB','TB','PB','EB','ZB','YB'];
$list = [];
function write(...$messages){
@@ -40,13 +39,13 @@ function write(...$messages){
curl_close($com);
}
function autoscale($value) {
global $unit;
$size = count($unit);
global $units;
$size = count($units);
$base = $value ? floor(log($value, 1000)) : 0;
if ($base>=$size) $base = $size-1;
$value /= pow(1000, $base);
$decimals = $base ? ($value>=100 ? 0 : ($value>=10 ? 1 : (round($value*100)%100===0 ? 0 : 2))) : 0;
return number_format($value, $decimals, '.', $value>9999 ? ',' : '').' '.$unit[$base];
return number_format($value, $decimals, '.', $value>9999 ? ',' : '').' '.$units[$base];
}
function align($text, $w=25) {
return $text.str_repeat('&nbsp;',$w-min(strlen($text),$w-1));
@@ -55,9 +54,9 @@ function gap($text) {
return preg_replace('/([kMGTPEZY]?B)$/'," $1",$text);
}
function byteval($data) {
global $unit;
global $units;
[$value,$base] = explode(' ',gap($data));
return $value*pow(1000,array_search($base,$unit));
return $value*pow(1000,array_search($base,$units));
}
exec("docker ps -sa --format='{{.Names}}|{{.Size}}'",$container);

View File

@@ -1,8 +1,8 @@
#!/usr/bin/php -q
<?PHP
/* Copyright 2005-2023, Lime Technology
* Copyright 2014-2023, Guilherme Jardim, Eric Schultz, Jon Panozzo.
* Copyright 2012-2023, Bergware International.
* Copyright 2014-2021, Guilherme Jardim, Eric Schultz, Jon Panozzo.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2,
@@ -13,8 +13,7 @@
*/
?>
<?
$docroot = $docroot ?? $_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp';
$docroot ??= ($_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp');
require_once "$docroot/webGui/include/Wrappers.php";
require_once "$docroot/plugins/dynamix.docker.manager/include/DockerClient.php";
extract(parse_plugin_cfg('dynamix', true));
@@ -45,7 +44,7 @@ if (!isset($check)) {
echo " Done.";
} else {
$notify = "$docroot/webGui/scripts/notify";
$var = @parse_ini_file("/var/local/emhttp/var.ini") ?: [];
$var = (array)@parse_ini_file("/var/local/emhttp/var.ini");
$server = strtoupper(_var($var,'NAME','tower'));
$output = _var($notify,'docker_notify');
$info = $DockerTemplates->getAllInfo(true);

View File

@@ -12,7 +12,7 @@
*/
?>
<?
$docroot = $docroot ?? $_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp';
$docroot ??= ($_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp');
require_once "$docroot/plugins/dynamix.docker.manager/include/DockerClient.php";
$DockerClient = new DockerClient();

View File

@@ -12,8 +12,7 @@
*/
?>
<?
$docroot = $docroot ?? $_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp';
$docroot ??= ($_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp');
require_once "$docroot/webGui/include/Wrappers.php";
extract(parse_plugin_cfg('dynamix',true));

View File

@@ -0,0 +1 @@
.fileTree{width:240px;max-height:200px;overflow-y:scroll;overflow-x:hidden;position:absolute;display:none;background:#f2f2f2}

View File

@@ -0,0 +1 @@
.fileTree{width:240px;max-height:200px;overflow-y:scroll;overflow-x:hidden;position:absolute;display:none;background:#1c1c1c}

View File

@@ -0,0 +1 @@
.fileTree{width:240px;max-height:200px;overflow-y:scroll;overflow-x:hidden;position:absolute;display:none;background:#1c1c1c}

View File

@@ -0,0 +1 @@
.fileTree{width:240px;max-height:200px;overflow-y:scroll;overflow-x:hidden;position:absolute;display:none;background:#f2f2f2}

View File

@@ -0,0 +1,9 @@
.noshow,.advanced{display:none}
.required:after{content:" *";color:#E80000}
span.boxed{display:inline-block;line-height:normal;white-space:normal;width:60%}
span.cpu,label.checkbox{display:inline-block;width:32px}
span.ct{display:inline-block;width:230px}
span.net{display:inline-block;width:120px}
span.ip{display:inline-block;width:160px}
dl,dt,dd{line-height:normal!important}
input.setting_input{margin-right:50px}

View File

@@ -0,0 +1,12 @@
.basic{display:block}
.advanced{display:none;white-space:nowrap}
.log{cursor:zoom-in}
.exec{cursor:pointer}
table#docker_containers{text-align:left}
th.five{width:5%}
th.nine{width:9%}
th.load{width:140px}
input.wait{width:24px;margin:0 4px;padding:0 5px;border:none;box-shadow:none;background-color:transparent}
table tbody td{line-height:normal}
i.mover{margin-right:8px;display:none}
#resetsort{margin-left:12px;display:inline-block;width:32px}

View File

@@ -0,0 +1,2 @@
.fileTree{background:#f2f2f2;width:300px;max-height:150px;overflow-y:scroll;overflow-x:hidden;position:absolute;z-index:100;display:none}
span.disabled{color:#B0B0B0}

View File

@@ -0,0 +1,2 @@
.fileTree{background:#1c1c1c;width:300px;max-height:150px;overflow-y:scroll;overflow-x:hidden;position:absolute;z-index:100;display:none}
span.disabled{color:#404040}

View File

@@ -0,0 +1,2 @@
.fileTree{background:#1c1c1c;width:300px;max-height:150px;overflow-y:scroll;overflow-x:hidden;position:absolute;z-index:100;display:none}
span.disabled{color:#404040}

View File

@@ -0,0 +1,2 @@
.fileTree{background:#f2f2f2;width:300px;max-height:150px;overflow-y:scroll;overflow-x:hidden;position:absolute;z-index:100;display:none}
span.disabled{color:#B0B0B0}

View File

@@ -0,0 +1,17 @@
.errortext{color:#EF3D47;display:none;margin-left:20px}
.basic{display:inline-block}
.advanced{display:none}
select.mask{min-width:0;margin:0 10px 0 4px}
select.net{min-width:0;margin:0 4px 0 2px}
select option.hide{display:none}
input.ip4{width:100px;margin:0 4px 0 1px}
input.ip6{width:140px;margin:0 4px}
input.gw4{width:100px;margin:0 4px 0 1px}
input.gw6{width:160px;margin:0 4px}
input.pool6{width:40px;margin:0 4px 0 1px}
span.net{margin-left:4px;margin-right:2px}
span.ip4{display:inline-block;width:260px}
span.ip6{display:inline-block;width:310px}
span.gw4{display:inline-block;width:200px}
span.gw6{display:inline-block;width:270px}
span.nonexist{margin-left:20px}

View File

@@ -0,0 +1 @@
.fileTree{width:240px;max-height:200px;overflow-y:scroll;overflow-x:hidden;position:absolute;display:none;background:#f2f2f2}

View File

@@ -0,0 +1 @@
.fileTree{width:240px;max-height:200px;overflow-y:scroll;overflow-x:hidden;position:absolute;display:none;background:#1c1c1c}

View File

@@ -0,0 +1 @@
.fileTree{width:240px;max-height:200px;overflow-y:scroll;overflow-x:hidden;position:absolute;display:none;background:#1c1c1c}

View File

@@ -0,0 +1 @@
.fileTree{width:240px;max-height:200px;overflow-y:scroll;overflow-x:hidden;position:absolute;display:none;background:#f2f2f2}

View File

@@ -0,0 +1,9 @@
.noshow,.advanced{display:none}
.required:after{content:" *";color:#E80000}
span.boxed{display:inline-block;line-height:normal;white-space:normal;width:60%}
span.cpu,label.checkbox{display:inline-block;width:32px}
span.ct{display:inline-block;width:230px}
span.net{display:inline-block;width:120px}
span.ip{display:inline-block;width:160px}
dl,dt,dd{line-height:normal!important}
input.setting_input{margin-right:50px}

View File

@@ -1,62 +1,14 @@
.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset button{
font-family:clear-sans;font-size:1.1rem;font-weight:bold;letter-spacing:2px;text-transform:uppercase;margin:10px 12px 10px 0;padding:9px 18px;text-decoration:none;white-space:nowrap;cursor:pointer;outline:none;border-radius:4px;border:0;color:#ff8c2f;background:-webkit-gradient(linear,left top,right top,from(#e22828),to(#ff8c2f)) 0 0 no-repeat,-webkit-gradient(linear,left top,right top,from(#e22828),to(#ff8c2f)) 0 100% no-repeat,-webkit-gradient(linear,left bottom,left top,from(#e22828),to(#e22828)) 0 100% no-repeat,-webkit-gradient(linear,left bottom,left top,from(#ff8c2f),to(#ff8c2f)) 100% 100% no-repeat;background:linear-gradient(90deg,#e22828 0,#ff8c2f) 0 0 no-repeat,linear-gradient(90deg,#e22828 0,#ff8c2f) 0 100% no-repeat,linear-gradient(0deg,#e22828 0,#e22828) 0 100% no-repeat,linear-gradient(0deg,#ff8c2f 0,#ff8c2f) 100% 100% no-repeat;background-size:100% 2px,100% 2px,2px 100%,2px 100%
}
.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset button:hover{
color:#f2f2f2;background:-webkit-gradient(linear,left top,right top,from(#e22828),to(#ff8c2f));background:linear-gradient(90deg,#e22828 0,#ff8c2f)
}
.ui-dropdownchecklist .ui-state-default{
background:#f2f2f2;
border:none;
box-shadow:none;
outline:none;
cursor:pointer;
height:2.2rem;
line-height:2.2rem;
}
.ui-dropdownchecklist-group{
font-weight:normal;
font-style:italic;
padding:1px 9px 1px 8px;
}
.ui-dropdownchecklist-selector{
border:1px solid #1c1c1c;
display:inline-block;
cursor:pointer;
padding:1px 9px 1px 8px;
}
.ui-dropdownchecklist-selector-wrapper{
vertical-align:middle;
font-size:0;
}
.ui-widget-header{
border:none;
background:#e3e3e3;
color:#1c1c1c;
font-weight:bold;
}
.ui-widget-content{
border:1px solid #1c1c1c;
background:#f2f2f2;
color:#1c1c1c;
.ui-state-active{
background:#e8e8e8;
}
.ui-dropdownchecklist-dropcontainer{
background:#f2f2f2;
border:1px solid #1c1c1c;
}
.ui-state-disabled{
color:#1c1c1c;border-color:#a2a2a2;background:#e8e8e8;opacity:0.5;
}
.ui-dropdownchecklist-indent{
padding-left:7px;
}
.ui-dropdownchecklist-text{
color:#1c1c1c;
font-size:1.3rem;
}
.ui-dropdownchecklist .ui-widget-content .ui-state-default{
background:#f2f2f2;
border:0px;
}
.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset button{font-family:clear-sans;font-size:1.1rem;font-weight:bold;letter-spacing:2px;text-transform:uppercase;margin:10px 12px 10px 0;padding:9px 18px;text-decoration:none;white-space:nowrap;cursor:pointer;outline:none;border-radius:4px;border:0;color:#ff8c2f;background:-webkit-gradient(linear,left top,right top,from(#e22828),to(#ff8c2f)) 0 0 no-repeat,-webkit-gradient(linear,left top,right top,from(#e22828),to(#ff8c2f)) 0 100% no-repeat,-webkit-gradient(linear,left bottom,left top,from(#e22828),to(#e22828)) 0 100% no-repeat,-webkit-gradient(linear,left bottom,left top,from(#ff8c2f),to(#ff8c2f)) 100% 100% no-repeat;background:linear-gradient(90deg,#e22828 0,#ff8c2f) 0 0 no-repeat,linear-gradient(90deg,#e22828 0,#ff8c2f) 0 100% no-repeat,linear-gradient(0deg,#e22828 0,#e22828) 0 100% no-repeat,linear-gradient(0deg,#ff8c2f 0,#ff8c2f) 100% 100% no-repeat;background-size:100% 2px,100% 2px,2px 100%,2px 100%}
.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset button:hover{color:#f2f2f2;background:-webkit-gradient(linear,left top,right top,from(#e22828),to(#ff8c2f));background:linear-gradient(90deg,#e22828 0,#ff8c2f)}
.ui-dropdownchecklist .ui-state-default{background:#f2f2f2;border:none;box-shadow:none;outline:none;cursor:pointer;height:2.2rem;line-height:2.2rem}
.ui-dropdownchecklist-group{font-weight:normal;font-style:italic;padding:1px 9px 1px 8px}
.ui-dropdownchecklist-selector{border:1px solid #1c1c1c;display:inline-block;cursor:pointer;padding:1px 9px 1px 8px}
.ui-dropdownchecklist-selector-wrapper{vertical-align:middle;font-size:0}
.ui-widget-header{border:none;background:#e3e3e3;color:#1c1c1c;font-weight:bold}
.ui-widget-content{border:1px solid #1c1c1c;background:#f2f2f2;color:#1c1c1c}
.ui-state-active{background:#e8e8e8}
.ui-dropdownchecklist-dropcontainer{background:#f2f2f2;border:1px solid #1c1c1c}
.ui-state-disabled{color:#1c1c1c;border-color:#a2a2a2;background:#e8e8e8;opacity:0.5}
.ui-dropdownchecklist-indent{padding-left:7px}
.ui-dropdownchecklist-text{color:#1c1c1c;font-size:1.3rem}
.ui-dropdownchecklist .ui-widget-content .ui-state-default{background:#f2f2f2;border:0px}

View File

@@ -1,62 +1,14 @@
.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset button{
font-family:clear-sans;font-size:1.1rem;font-weight:bold;letter-spacing:2px;text-transform:uppercase;margin:10px 12px 10px 0;padding:9px 18px;text-decoration:none;white-space:nowrap;cursor:pointer;outline:none;border-radius:4px;border:0;color:#ff8c2f;background:-webkit-gradient(linear,left top,right top,from(#e22828),to(#ff8c2f)) 0 0 no-repeat,-webkit-gradient(linear,left top,right top,from(#e22828),to(#ff8c2f)) 0 100% no-repeat,-webkit-gradient(linear,left bottom,left top,from(#e22828),to(#e22828)) 0 100% no-repeat,-webkit-gradient(linear,left bottom,left top,from(#ff8c2f),to(#ff8c2f)) 100% 100% no-repeat;background:linear-gradient(90deg,#e22828 0,#ff8c2f) 0 0 no-repeat,linear-gradient(90deg,#e22828 0,#ff8c2f) 0 100% no-repeat,linear-gradient(0deg,#e22828 0,#e22828) 0 100% no-repeat,linear-gradient(0deg,#ff8c2f 0,#ff8c2f) 100% 100% no-repeat;background-size:100% 2px,100% 2px,2px 100%,2px 100%
}
.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset button:hover{
color:#f2f2f2;background:-webkit-gradient(linear,left top,right top,from(#e22828),to(#ff8c2f));background:linear-gradient(90deg,#e22828 0,#ff8c2f)
}
.ui-dropdownchecklist .ui-state-default{
background:#1c1c1c;
border:none;
box-shadow:none;
outline:none;
cursor:pointer;
height:2.2rem;
line-height:2.2rem;
}
.ui-dropdownchecklist-group{
font-weight:normal;
font-style:italic;
padding:1px 9px 1px 8px;
}
.ui-dropdownchecklist-selector{
border:1px solid #e5e5e5;
display:inline-block;
cursor:pointer;
padding:1px 9px 1px 8px;
}
.ui-dropdownchecklist-selector-wrapper{
vertical-align:middle;
font-size:0;
}
.ui-widget-header{
border:none;
background:#2b2b2b;
color:#f2f2f2;
font-weight:bold;
}
.ui-widget-content{
border:1px solid #e5e5e5;
background:#1c1c1c;
color:#f2f2f2;
.ui-state-active{
background:#262626;
}
.ui-dropdownchecklist-dropcontainer{
background:#1c1c1c;
border:1px solid #e5e5e5;
}
.ui-state-disabled{
color:#f2f2f2;border-color:#6c6c6c;background:#262626;opacity:0.5;
}
.ui-dropdownchecklist-indent{
padding-left:7px;
}
.ui-dropdownchecklist-text{
color:#f2f2f2;
font-size:1.3rem;
}
.ui-dropdownchecklist .ui-widget-content .ui-state-default{
background:#1c1c1c;
border:0px;
}
.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset button{font-family:clear-sans;font-size:1.1rem;font-weight:bold;letter-spacing:2px;text-transform:uppercase;margin:10px 12px 10px 0;padding:9px 18px;text-decoration:none;white-space:nowrap;cursor:pointer;outline:none;border-radius:4px;border:0;color:#ff8c2f;background:-webkit-gradient(linear,left top,right top,from(#e22828),to(#ff8c2f)) 0 0 no-repeat,-webkit-gradient(linear,left top,right top,from(#e22828),to(#ff8c2f)) 0 100% no-repeat,-webkit-gradient(linear,left bottom,left top,from(#e22828),to(#e22828)) 0 100% no-repeat,-webkit-gradient(linear,left bottom,left top,from(#ff8c2f),to(#ff8c2f)) 100% 100% no-repeat;background:linear-gradient(90deg,#e22828 0,#ff8c2f) 0 0 no-repeat,linear-gradient(90deg,#e22828 0,#ff8c2f) 0 100% no-repeat,linear-gradient(0deg,#e22828 0,#e22828) 0 100% no-repeat,linear-gradient(0deg,#ff8c2f 0,#ff8c2f) 100% 100% no-repeat;background-size:100% 2px,100% 2px,2px 100%,2px 100%}
.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset button:hover{color:#f2f2f2;background:-webkit-gradient(linear,left top,right top,from(#e22828),to(#ff8c2f));background:linear-gradient(90deg,#e22828 0,#ff8c2f)}
.ui-dropdownchecklist .ui-state-default{background:#1c1c1c;border:none;box-shadow:none;outline:none;cursor:pointer;height:2.2rem;line-height:2.2rem}
.ui-dropdownchecklist-group{font-weight:normal;font-style:italic;padding:1px 9px 1px 8px}
.ui-dropdownchecklist-selector{border:1px solid #e5e5e5;display:inline-block;cursor:pointer;padding:1px 9px 1px 8px}
.ui-dropdownchecklist-selector-wrapper{vertical-align:middle;font-size:0}
.ui-widget-header{border:none;background:#2b2b2b;color:#f2f2f2;font-weight:bold}
.ui-widget-content{border:1px solid #e5e5e5;background:#1c1c1c;color:#f2f2f2}
.ui-state-active{background:#262626}
.ui-dropdownchecklist-dropcontainer{background:#1c1c1c;border:1px solid #e5e5e5}
.ui-state-disabled{color:#f2f2f2;border-color:#6c6c6c;background:#262626;opacity:0.5}
.ui-dropdownchecklist-indent{padding-left:7px}
.ui-dropdownchecklist-text{color:#f2f2f2;font-size:1.3rem}
.ui-dropdownchecklist .ui-widget-content .ui-state-default{background:#1c1c1c;border:0px}

View File

@@ -1,62 +1,14 @@
.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset button{
font-family:clear-sans;font-size:1.1rem;font-weight:bold;letter-spacing:2px;text-transform:uppercase;margin:10px 12px 10px 0;padding:9px 18px;text-decoration:none;white-space:nowrap;cursor:pointer;outline:none;border-radius:4px;border:0;color:#ff8c2f;background:-webkit-gradient(linear,left top,right top,from(#e22828),to(#ff8c2f)) 0 0 no-repeat,-webkit-gradient(linear,left top,right top,from(#e22828),to(#ff8c2f)) 0 100% no-repeat,-webkit-gradient(linear,left bottom,left top,from(#e22828),to(#e22828)) 0 100% no-repeat,-webkit-gradient(linear,left bottom,left top,from(#ff8c2f),to(#ff8c2f)) 100% 100% no-repeat;background:linear-gradient(90deg,#e22828 0,#ff8c2f) 0 0 no-repeat,linear-gradient(90deg,#e22828 0,#ff8c2f) 0 100% no-repeat,linear-gradient(0deg,#e22828 0,#e22828) 0 100% no-repeat,linear-gradient(0deg,#ff8c2f 0,#ff8c2f) 100% 100% no-repeat;background-size:100% 2px,100% 2px,2px 100%,2px 100%
}
.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset button:hover{
color:#f2f2f2;background:-webkit-gradient(linear,left top,right top,from(#e22828),to(#ff8c2f));background:linear-gradient(90deg,#e22828 0,#ff8c2f)
}
.ui-dropdownchecklist .ui-state-default{
background:#1c1c1c;
border:none;
box-shadow:none;
outline:none;
cursor:pointer;
height:2.2rem;
line-height:2.2rem;
}
.ui-dropdownchecklist-group{
font-weight:normal;
font-style:italic;
padding:1px 9px 1px 8px;
}
.ui-dropdownchecklist-selector{
border:1px solid #e5e5e5;
display:inline-block;
cursor:pointer;
padding:1px 9px 1px 8px;
}
.ui-dropdownchecklist-selector-wrapper{
vertical-align:middle;
font-size:0;
}
.ui-widget-header{
border:none;
background:#2b2b2b;
color:#f2f2f2;
font-weight:bold;
}
.ui-widget-content{
border:1px solid #e5e5e5;
background:#1c1c1c;
color:#f2f2f2;
.ui-state-active{
background:#262626;
}
.ui-dropdownchecklist-dropcontainer{
background:#1c1c1c;
border:1px solid #e5e5e5;
}
.ui-state-disabled{
color:#f2f2f2;border-color:#6c6c6c;background:#262626;opacity:0.5;
}
.ui-dropdownchecklist-indent{
padding-left:7px;
}
.ui-dropdownchecklist-text{
color:#f2f2f2;
font-size:1.3rem;
}
.ui-dropdownchecklist .ui-widget-content .ui-state-default{
background:#1c1c1c;
border:0px;
}
.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset button{font-family:clear-sans;font-size:1.1rem;font-weight:bold;letter-spacing:2px;text-transform:uppercase;margin:10px 12px 10px 0;padding:9px 18px;text-decoration:none;white-space:nowrap;cursor:pointer;outline:none;border-radius:4px;border:0;color:#ff8c2f;background:-webkit-gradient(linear,left top,right top,from(#e22828),to(#ff8c2f)) 0 0 no-repeat,-webkit-gradient(linear,left top,right top,from(#e22828),to(#ff8c2f)) 0 100% no-repeat,-webkit-gradient(linear,left bottom,left top,from(#e22828),to(#e22828)) 0 100% no-repeat,-webkit-gradient(linear,left bottom,left top,from(#ff8c2f),to(#ff8c2f)) 100% 100% no-repeat;background:linear-gradient(90deg,#e22828 0,#ff8c2f) 0 0 no-repeat,linear-gradient(90deg,#e22828 0,#ff8c2f) 0 100% no-repeat,linear-gradient(0deg,#e22828 0,#e22828) 0 100% no-repeat,linear-gradient(0deg,#ff8c2f 0,#ff8c2f) 100% 100% no-repeat;background-size:100% 2px,100% 2px,2px 100%,2px 100%}
.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset button:hover{color:#f2f2f2;background:-webkit-gradient(linear,left top,right top,from(#e22828),to(#ff8c2f));background:linear-gradient(90deg,#e22828 0,#ff8c2f)}
.ui-dropdownchecklist .ui-state-default{background:#1c1c1c;border:none;box-shadow:none;outline:none;cursor:pointer;height:2.2rem;line-height:2.2rem}
.ui-dropdownchecklist-group{font-weight:normal;font-style:italic;padding:1px 9px 1px 8px}
.ui-dropdownchecklist-selector{border:1px solid #e5e5e5;display:inline-block;cursor:pointer;padding:1px 9px 1px 8px}
.ui-dropdownchecklist-selector-wrapper{vertical-align:middle;font-size:0}
.ui-widget-header{border:none;background:#2b2b2b;color:#f2f2f2;font-weight:bold}
.ui-widget-content{border:1px solid #e5e5e5;background:#1c1c1c;color:#f2f2f2}
.ui-state-active{background:#262626}
.ui-dropdownchecklist-dropcontainer{background:#1c1c1c;border:1px solid #e5e5e5}
.ui-state-disabled{color:#f2f2f2;border-color:#6c6c6c;background:#262626;opacity:0.5}
.ui-dropdownchecklist-indent{padding-left:7px}
.ui-dropdownchecklist-text{color:#f2f2f2;font-size:1.3rem}
.ui-dropdownchecklist .ui-widget-content .ui-state-default{background:#1c1c1c;border:0px}

View File

@@ -1,62 +1,14 @@
.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset button{
font-family:clear-sans;font-size:1.1rem;font-weight:bold;letter-spacing:2px;text-transform:uppercase;margin:10px 12px 10px 0;padding:9px 18px;text-decoration:none;white-space:nowrap;cursor:pointer;outline:none;border-radius:4px;border:0;color:#ff8c2f;background:-webkit-gradient(linear,left top,right top,from(#e22828),to(#ff8c2f)) 0 0 no-repeat,-webkit-gradient(linear,left top,right top,from(#e22828),to(#ff8c2f)) 0 100% no-repeat,-webkit-gradient(linear,left bottom,left top,from(#e22828),to(#e22828)) 0 100% no-repeat,-webkit-gradient(linear,left bottom,left top,from(#ff8c2f),to(#ff8c2f)) 100% 100% no-repeat;background:linear-gradient(90deg,#e22828 0,#ff8c2f) 0 0 no-repeat,linear-gradient(90deg,#e22828 0,#ff8c2f) 0 100% no-repeat,linear-gradient(0deg,#e22828 0,#e22828) 0 100% no-repeat,linear-gradient(0deg,#ff8c2f 0,#ff8c2f) 100% 100% no-repeat;background-size:100% 2px,100% 2px,2px 100%,2px 100%
}
.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset button:hover{
color:#f2f2f2;background:-webkit-gradient(linear,left top,right top,from(#e22828),to(#ff8c2f));background:linear-gradient(90deg,#e22828 0,#ff8c2f)
}
.ui-dropdownchecklist .ui-state-default{
background:#f2f2f2;
border:none;
box-shadow:none;
outline:none;
cursor:pointer;
height:2.2rem;
line-height:2.2rem;
}
.ui-dropdownchecklist-group{
font-weight:normal;
font-style:italic;
padding:1px 9px 1px 8px;
}
.ui-dropdownchecklist-selector{
border:1px solid #1c1c1c;
display:inline-block;
cursor:pointer;
padding:1px 9px 1px 8px;
}
.ui-dropdownchecklist-selector-wrapper{
vertical-align:middle;
font-size:0;
}
.ui-widget-header{
border:none;
background:#e3e3e3;
color:#1c1c1c;
font-weight:bold;
}
.ui-widget-content{
border:1px solid #1c1c1c;
background:#f2f2f2;
color:#1c1c1c;
.ui-state-active{
background:#e8e8e8;
}
.ui-dropdownchecklist-dropcontainer{
background:#f2f2f2;
border:1px solid #1c1c1c;
}
.ui-state-disabled{
color:#1c1c1c;border-color:#a2a2a2;background:#e8e8e8;opacity:0.5;
}
.ui-dropdownchecklist-indent{
padding-left:7px;
}
.ui-dropdownchecklist-text{
color:#1c1c1c;
font-size:1.3rem;
}
.ui-dropdownchecklist .ui-widget-content .ui-state-default{
background:#f2f2f2;
border:0px;
}
.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset button{font-family:clear-sans;font-size:1.1rem;font-weight:bold;letter-spacing:2px;text-transform:uppercase;margin:10px 12px 10px 0;padding:9px 18px;text-decoration:none;white-space:nowrap;cursor:pointer;outline:none;border-radius:4px;border:0;color:#ff8c2f;background:-webkit-gradient(linear,left top,right top,from(#e22828),to(#ff8c2f)) 0 0 no-repeat,-webkit-gradient(linear,left top,right top,from(#e22828),to(#ff8c2f)) 0 100% no-repeat,-webkit-gradient(linear,left bottom,left top,from(#e22828),to(#e22828)) 0 100% no-repeat,-webkit-gradient(linear,left bottom,left top,from(#ff8c2f),to(#ff8c2f)) 100% 100% no-repeat;background:linear-gradient(90deg,#e22828 0,#ff8c2f) 0 0 no-repeat,linear-gradient(90deg,#e22828 0,#ff8c2f) 0 100% no-repeat,linear-gradient(0deg,#e22828 0,#e22828) 0 100% no-repeat,linear-gradient(0deg,#ff8c2f 0,#ff8c2f) 100% 100% no-repeat;background-size:100% 2px,100% 2px,2px 100%,2px 100%}
.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset button:hover{color:#f2f2f2;background:-webkit-gradient(linear,left top,right top,from(#e22828),to(#ff8c2f));background:linear-gradient(90deg,#e22828 0,#ff8c2f)}
.ui-dropdownchecklist .ui-state-default{background:#f2f2f2;border:none;box-shadow:none;outline:none;cursor:pointer;height:2.2rem;line-height:2.2rem}
.ui-dropdownchecklist-group{font-weight:normal;font-style:italic;padding:1px 9px 1px 8px}
.ui-dropdownchecklist-selector{border:1px solid #1c1c1c;display:inline-block;cursor:pointer;padding:1px 9px 1px 8px}
.ui-dropdownchecklist-selector-wrapper{vertical-align:middle;font-size:0}
.ui-widget-header{border:none;background:#e3e3e3;color:#1c1c1c;font-weight:bold}
.ui-widget-content{border:1px solid #1c1c1c;background:#f2f2f2;color:#1c1c1c}
.ui-state-active{background:#e8e8e8}
.ui-dropdownchecklist-dropcontainer{background:#f2f2f2;border:1px solid #1c1c1c}
.ui-state-disabled{color:#1c1c1c;border-color:#a2a2a2;background:#e8e8e8;opacity:0.5}
.ui-dropdownchecklist-indent{padding-left:7px}
.ui-dropdownchecklist-text{color:#1c1c1c;font-size:1.3rem}
.ui-dropdownchecklist .ui-widget-content .ui-state-default{background:#f2f2f2;border:0px}

View File

@@ -1,5 +1,5 @@
<?php
$docroot = $docroot ?? $_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp';
<?PHP
$docroot ??= ($_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp');
$var = (array)parse_ini_file('state/var.ini');
require_once "$docroot/webGui/include/Wrappers.php";

View File

@@ -1,5 +1,5 @@
<?php
$docroot = $docroot ?? $_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp';
<?PHP
$docroot ??= ($_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp');
require_once("$docroot/plugins/dynamix.my.servers/include/state.php");
require_once("$docroot/plugins/dynamix.my.servers/include/translations.php");

View File

@@ -1,91 +0,0 @@
#!/usr/bin/php
<?PHP
/* Copyright 2005-2021, Lime Technology
* Copyright 2012-2021, 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.
*/
function update($url, $payload) {
$ch = curl_init($url);
curl_setopt($ch,CURLOPT_POST, true);
curl_setopt($ch,CURLOPT_POSTFIELDS, $payload);
curl_setopt($ch,CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($ch);
curl_close($ch);
}
$dyn_cfg = '/boot/config/plugins/dynamix/dynamix.cfg';
$mys_cfg = '/boot/config/plugins/dynamix.my.servers/myservers.cfg';
if (file_exists($dyn_cfg) && !file_exists($mys_cfg)) {
$orig = @parse_ini_file($dyn_cfg,true);
$var = @(array)parse_ini_file('/usr/local/emhttp/state/var.ini',true);
$url = "http://localhost:".$var['PORT']."/update.php";
// write [remote] section to myservers.cfg
if(!empty($orig['remote'])) {
$fields_mys_remote = [
'csrf_token' => $var['csrf_token'],
'#file' => $mys_cfg,
'#section' => 'remote'
];
foreach($orig['remote'] as $key => $value) {
$fields_mys_remote[$key] = $value;
}
update($url, http_build_query($fields_mys_remote));
}
/*
// write [wizard] section to myservers.cfg
if(!empty($orig['wizard'])) {
$fields_mys_wizard = [
'csrf_token' => $var['csrf_token'],
'#file' => $mys_cfg,
'#section' => 'wizard'
];
foreach($orig['wizard'] as $key => $value) {
$fields_mys_wizard[$key] = $value;
}
update($url, http_build_query($fields_mys_wizard));
}
*/
// remove [remote] section from dynamix.cfg
if(!empty($orig['remote'])) {
$fields_dyn_remote = [
'csrf_token' => $var['csrf_token'],
'#file' => $dyn_cfg,
'#section' => 'remote',
'#cleanup' => 'true'
];
foreach($orig['remote'] as $key => $value) {
$fields_dyn_remote[$key] = '';
}
update($url, http_build_query($fields_dyn_remote));
}
// remove [wizard] section from dynamix.cfg
if(!empty($orig['wizard'])) {
$fields_dyn_wizard = [
'csrf_token' => $var['csrf_token'],
'#file' => $dyn_cfg,
'#section' => 'wizard',
'#cleanup' => 'true'
];
foreach($orig['wizard'] as $key => $value) {
$fields_dyn_wizard[$key] = '';
}
update($url, http_build_query($fields_dyn_wizard));
}
// remove [remote] and [wizard] section headings from dyn_cfg file
$oldtext = file_get_contents($dyn_cfg);
$newtext = preg_replace ('/\[(remote|wizard)\]\n/', '', $oldtext);
if (strcmp($oldtext, $newtext) !== 0) {
file_put_contents($dyn_cfg, $newtext);
}
}
if (!file_exists($mys_cfg)) touch($mys_cfg);
?>

View File

@@ -0,0 +1,4 @@
span.thanks{padding-left:12px;color:#6FA239;font-weight:bold;}
span.thanks.red{color:#F0000C;}
div.device{padding:0 12px;font-weight:normal;font-style:italic;}
div.remark{padding:0 12px;text-align:justify;}

View File

@@ -13,14 +13,6 @@ Link='nav-user'
* all copies or substantial portions of the Software.
*/
?>
<style>
/* Additional CSS for when user supplies element */
.ca_element_notice{padding-right:20px;width:100%;height:40px;line-height:40px;color:#e68a00;background:#feefb3;border-bottom:#e68a00 1px solid;text-align:center;font-size:1.4rem;z-index:900;}
a.ca_PluginUpdateInstall{cursor:pointer;}
span.ca_PluginUpdateDismiss{float:right;margin-right:20px;cursor:pointer;}
span.bannerInfo {cursor:pointer;text-decoration:none;margin:0 12px 0 6px;}
span.bannerInfo::before {content:"\f05a";font-family:fontAwesome;color:#e68a00;}
</style>
<script>
const ca_args = {};

View File

@@ -3,8 +3,8 @@ Title="Install Plugin"
Tag="download"
---
<?PHP
/* Copyright 2005-2022, Lime Technology
* Copyright 2012-2022, Bergware International.
/* 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,

View File

@@ -6,8 +6,8 @@ Tabs="true"
Code="e944"
---
<?PHP
/* Copyright 2005-2022, Lime Technology
* Copyright 2012-2022, Bergware International.
/* 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,
@@ -25,10 +25,6 @@ if (!exec("pgrep -f $docroot/plugins/dynamix.plugin.manager/scripts/plugin")) {
$check = $notify['version'] ? 0 : 1;
?>
<link type="text/css" rel="stylesheet" href="<?autov('/webGui/styles/jquery.filetree.css')?>">
<style>
#plugin_tree{width:33%;height:200px;overflow-y:scroll}
table tbody td{line-height:normal}
</style>
<script src="<?autov('/webGui/javascript/jquery.filetree.js')?>" charset="utf-8"></script>
<script>

View File

@@ -4,8 +4,8 @@ Tag="puzzle-piece"
Cond="glob('/boot/config/plugins-error/*.plg')"
---
<?PHP
/* Copyright 2005-2021, Lime Technology
* Copyright 2012-2021, Bergware International.
/* 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,

View File

@@ -4,8 +4,8 @@ Tag="puzzle-piece"
Cond="glob('/boot/config/plugins-stale/*.plg')"
---
<?PHP
/* Copyright 2005-2021, Lime Technology
* Copyright 2012-2021, Bergware International.
/* 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,

View File

@@ -11,8 +11,7 @@
*/
?>
<?
$docroot = $docroot ?? $_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp';
$docroot ??= ($_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp');
require_once "$docroot/webGui/include/Wrappers.php";
require_once "$docroot/webGui/include/Secure.php";

View File

@@ -11,8 +11,7 @@
*/
?>
<?
$docroot = $docroot ?? $_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp';
$docroot ??= ($_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp');
require_once "$docroot/webGui/include/Wrappers.php";
extract(parse_plugin_cfg('dynamix',true));

View File

@@ -11,8 +11,7 @@
*/
?>
<?
$docroot = $docroot ?? $_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp';
$docroot ??= ($_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp');
require_once "$docroot/webGui/include/Helpers.php";
require_once "$docroot/plugins/dynamix.plugin.manager/include/PluginHelpers.php";

View File

@@ -12,7 +12,7 @@
*/
?>
<?
$docroot = $docroot ?? $_SERVER['DOCUMENT_ROOT'] ?: "/usr/local/emhttp";
$docroot ??= ($_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp');
require_once "$docroot/plugins/dynamix.plugin.manager/include/PluginHelpers.php";
function readJson($file) {

View File

@@ -12,7 +12,7 @@
*/
?>
<?
$docroot = $docroot ?? $_SERVER['DOCUMENT_ROOT'] ?: "/usr/local/emhttp";
$docroot ??= ($_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp');
require_once "$docroot/plugins/dynamix.plugin.manager/include/PluginHelpers.php";
$type = $argv[1]??''; // plugin or language

View File

@@ -10,12 +10,13 @@
* all copies or substantial portions of the Software.
*/
$docroot = $docroot ?? $_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp';
$docroot ??= ($_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp');
require_once "$docroot/plugins/dynamix.plugin.manager/include/PluginHelpers.php";
require_once "$docroot/plugins/dynamix/include/Secure.php";
//add translations
$_SERVER['REQUEST_URI'] = "plugins";
require_once "$docroot/plugins/dynamix/include/Translations.php";
require_once "$docroot/plugins/dynamix.plugin.manager/include/PluginHelpers.php";
require_once "$docroot/plugins/dynamix/include/Secure.php";
function download_url($url, $path = "") {
$ch = curl_init();
@@ -39,21 +40,17 @@ switch ($_POST['action']) {
case 'checkPlugin':
$options = $_POST['options'] ?? '';
$plugin = $options['plugin'] ?? '';
$name = unbundle($options['name'] ?? $plugin);
$file = "/boot/config/plugins/$plugin";
$file = realpath($file)==$file ? $file : "";
if ( ! $plugin || ! file_exists($file) ) {
echo json_encode(["updateAvailable"=>false]);
break;
}
exec("mkdir -p /tmp/plugins");
@unlink("/tmp/plugins/$plugin");
$url = plugin("pluginURL","/boot/config/plugins/$plugin");
download_url($url,"/tmp/plugins/$plugin");
$changes = plugin("changes","/tmp/plugins/$plugin");
$alerts = plugin("alert","/tmp/plugins/$plugin");
$version = plugin("version","/tmp/plugins/$plugin");
@@ -69,7 +66,6 @@ switch ($_POST['action']) {
} else {
@unlink('/tmp/plugins/my_alerts.txt');
}
$update = false;
if ( strcmp($version,$installedVersion) > 0 ) {
$unraid = parse_ini_file("/etc/unraid-version");
@@ -77,17 +73,14 @@ switch ($_POST['action']) {
}
$updateMessage = sprintf(_("%s: An update is available."),$name);
$linkMessage = sprintf(_("Click here to install version %s"),$version);
echo json_encode(["updateAvailable"=>$update, "version"=>$version, "min"=>$min, "alert"=>$alerts, "changes"=>$changes, "installedVersion"=>$installedVersion, "updateMessage"=>$updateMessage, "linkMessage"=>$linkMessage]);
break;
case 'addRebootNotice':
$message = htmlspecialchars(trim($_POST['message']));
if ( ! $message ) break;
$existing = @file("/tmp/reboot_notifications",FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES) ?: [];
if (!$message) break;
$existing = (array)@file("/tmp/reboot_notifications",FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
$existing[] = $message;
file_put_contents("/tmp/reboot_notifications",implode("\n",array_unique($existing)));
break;

View File

@@ -12,8 +12,7 @@
*/
?>
<?
$docroot = $docroot ?? $_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp';
$docroot ??= ($_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp');
require_once "$docroot/webGui/include/Wrappers.php";
extract(parse_plugin_cfg('dynamix',true));

View File

@@ -12,8 +12,7 @@
*/
?>
<?
$docroot = $docroot ?? $_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp';
$docroot ??= ($_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp');
require_once "$docroot/webGui/include/Wrappers.php";
require_once "$docroot/plugins/dynamix.plugin.manager/include/PluginHelpers.php";
extract(parse_plugin_cfg('dynamix', true));
@@ -23,7 +22,7 @@ $_SERVER['REQUEST_URI'] = "scripts";
$login_locale = _var($display,'locale');
require_once "$docroot/webGui/include/Translations.php";
$var = @parse_ini_file('/var/local/emhttp/var.ini') ?: [];
$var = (array)@parse_ini_file('/var/local/emhttp/var.ini');
function apos($text) {
// So that "&apos;" doesn't show up in email

View File

@@ -1,6 +1,6 @@
#!/usr/bin/php -q
<?PHP
// Copyright 2005-2022, Lime Technology
// Copyright 2005-2023, Lime Technology
// License: GPLv2 only
//
// Program updates made by Bergware International (April 2020)

View File

@@ -12,11 +12,9 @@
*/
?>
<?
$docroot = $docroot ?? $_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp';
$docroot ??= ($_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp');
require_once "$docroot/webGui/include/Wrappers.php";
require_once "$docroot/plugins/dynamix.plugin.manager/include/PluginHelpers.php";
extract(parse_plugin_cfg('dynamix',true));
// Multi-language support
@@ -24,7 +22,7 @@ $_SERVER['REQUEST_URI'] = "scripts";
$login_locale = _var($display,'locale');
require_once "$docroot/webGui/include/Translations.php";
$var = @parse_ini_file('/var/local/emhttp/var.ini') ?: [];
$var = (array)@parse_ini_file('/var/local/emhttp/var.ini');
function apos($text) {
// So that "&apos;" doesn't show up in email

View File

@@ -12,8 +12,7 @@
*/
?>
<?
$docroot = $docroot ?? $_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp';
$docroot ??= ($_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp');
require_once "$docroot/webGui/include/Wrappers.php";
extract(parse_plugin_cfg('dynamix',true));

View File

@@ -12,8 +12,7 @@
*/
?>
<?
$docroot = $docroot ?? $_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp';
$docroot ??= ($_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp');
require_once "$docroot/webGui/include/Wrappers.php";
require_once "$docroot/plugins/dynamix.plugin.manager/include/PluginHelpers.php";
@@ -24,7 +23,7 @@ if (!function_exists('_')) {
extract(parse_plugin_cfg('dynamix', true));
$var = @parse_ini_file('/var/local/emhttp/var.ini') ?: [];
$var = (array)@parse_ini_file('/var/local/emhttp/var.ini');
$script = "$docroot/webGui/scripts/notify";
$server = strtoupper(_var($var,'NAME','server'));
$output = _var($notify,'plugin');

View File

@@ -0,0 +1,5 @@
.ca_element_notice{padding-right:20px;width:100%;height:40px;line-height:40px;color:#e68a00;background:#feefb3;border-bottom:#e68a00 1px solid;text-align:center;font-size:1.4rem;z-index:900}
a.ca_PluginUpdateInstall{cursor:pointer}
span.ca_PluginUpdateDismiss{float:right;margin-right:20px;cursor:pointer}
span.bannerInfo {cursor:pointer;text-decoration:none;margin:0 12px 0 6px}
span.bannerInfo::before {content:"\f05a";font-family:fontAwesome;color:#e68a00}

View File

@@ -0,0 +1,2 @@
#plugin_tree{width:33%;height:200px;overflow-y:scroll}
table tbody td{line-height:normal}

View File

@@ -0,0 +1 @@
span.vhshift{margin-top:13px!important}

View File

@@ -0,0 +1 @@
span.vhshift{margin-top:13px!important}

View File

@@ -0,0 +1,9 @@
ul,li{margin:0;padding-top:0;padding-bottom:0}
pre.pre{margin:30px 0}
pre>p{margin:0;padding:0}
pre#swaltext{height:600px!important}
@media (max-width:960px){pre#swaltext{height:400px!important}}
@media (max-width:960px){.sweet-alert.nchan{height:600px;width:900px;margin-left:-470px}}
@media (max-height:768px){pre#swaltext{height:400px!important}}
@media (max-height:768px){.sweet-alert.nchan{height:600px;width:900px;margin-left:-470px}}
input[value="_(Install)_"],input[value="_(Update)_"],input[value="_(Restore)_"]{margin:0}

View File

@@ -4,9 +4,9 @@ Cond="(pgrep('libvirtd')!==false)"
Markdown="false"
---
<?PHP
/* Copyright 2005-2020, Lime Technology
* Copyright 2015-2020, Derek Macias, Eric Schultz, Jon Panozzo.
* Copyright 2012-2020, Bergware International.
/* Copyright 2005-2023, Lime Technology
* Copyright 2012-2023, Bergware International.
* Copyright 2015-2021, Derek Macias, Eric Schultz, Jon Panozzo.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2,

View File

@@ -4,9 +4,9 @@ Cond="(pgrep('libvirtd')!==false)"
Markdown="false"
---
<?PHP
/* Copyright 2005-2020, Lime Technology
* Copyright 2015-2020, Derek Macias, Eric Schultz, Jon Panozzo.
* Copyright 2012-2020, Bergware International.
/* Copyright 2005-2023, Lime Technology
* Copyright 2012-2023, Bergware International.
* Copyright 2015-2021, Derek Macias, Eric Schultz, Jon Panozzo.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2,

View File

@@ -6,8 +6,8 @@ Markdown="false"
---
<?PHP
/* Copyright 2005-2023, Lime Technology
* Copyright 2015-2023, Derek Macias, Eric Schultz, Jon Panozzo.
* Copyright 2012-2023, Bergware International.
* Copyright 2015-2021, Derek Macias, Eric Schultz, Jon Panozzo.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2,
@@ -18,7 +18,7 @@ Markdown="false"
*/
?>
<?
$docroot = $docroot ?? $_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp';
$docroot ??= ($_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp');
require_once "$docroot/plugins/dynamix.vm.manager/include/libvirt_helpers.php";
$cpus = cpu_list();
@@ -112,36 +112,6 @@ if (empty($vms)) {
<link type="text/css" rel="stylesheet" href="<?autov("/webGui/styles/jquery.filetree.css")?>">
<link type="text/css" rel="stylesheet" href="<?autov("/webGui/styles/jquery.ui.css")?>">
<link type="text/css" rel="stylesheet" href="<?autov("/plugins/dynamix.docker.manager/styles/style-$theme.css")?>">
<style>
th.th1{width:25%}
th.th2{width:15%}
th.th3{width:80px}
div.four{font-size:1.1rem;width:260px}
div.four label{float:left;display:table-cell;width:25%}
div.four label:nth-child(4n+4){float:none;clear:both}
div.four label.cpu1{width:32%}
div.four label.cpu2{width:26%}
div.template,div#dialogWindow,input#upload{display:none}
div.template,div#dialogWindow2,input#upload{display:none}
table.domdisk thead tr th:nth-child(1){width:56%!important}
table.domdisk thead tr th:nth-child(n+2){width:8%!important}
table.domdisk thead tr th:nth-child(1){padding-left:72px}
table.domdisk tbody tr td:nth-child(1){padding-left:72px}
table.domdisk tbody tr:nth-child(even){background-color:transparent!important}
table.domdisk tbody tr:nth-child(4n-1){background-color:transparent!important}
i.mover{margin-right:8px;display:none}
#resetsort{margin-left:12px;display:inline-block;width:32px}
.fileTree{background:<?=$bgcolor?>;width:500px;max-height:320px;overflow-y:scroll;overflow-x:hidden;position:absolute;z-index:100;display:none}
.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset button[disabled]{cursor:default;color:#808080;background:-webkit-gradient(linear,left top,right top,from(#404040),to(#808080)) 0 0 no-repeat,-webkit-gradient(linear,left top,right top,from(#404040),to(#808080)) 0 100% no-repeat,-webkit-gradient(linear,left bottom,left top,from(#404040),to(#404040)) 0 100% no-repeat,-webkit-gradient(linear,left bottom,left top,from(#808080),to(#808080)) 100% 100% no-repeat;background:linear-gradient(90deg,#404040 0,#808080) 0 0 no-repeat,linear-gradient(90deg,#404040 0,#808080) 0 100% no-repeat,linear-gradient(0deg,#404040 0,#404040) 0 100% no-repeat,linear-gradient(0deg,#808080 0,#808080) 100% 100% no-repeat;background-size:100% 2px,100% 2px,2px 100%,2px 100%}
.dropdown-menu{z-index:10001}
</style>
<table id="kvm_table" class="tablesorter four shift">
<thead><tr><th class="th1"><a id="resetsort" class="nohand" onclick="resetSorting()" title="Reset sorting"><i class="fa fa-th-list"></i></a>_(Name)_</th><th class="th2">_(Description)_</th><th>_(CPUs)_</th><th>_(Memory)_</th><th>_(vDisks / vCDs)_</th><th>_(Graphics)_</th><th class="th3">_(Autostart)_</th></tr></thead>
<tbody id="kvm_list"><tr><td colspan='8'></td></tr></tbody>
</table>
<input type="button" onclick="addVM()" id="btnAddVM" value="_(Add VM)_" style="display:none">
<input type="button" onclick="startAll()" value="_(Start All)_" style="display:none">
<input type="button" onclick="stopAll()" value="_(Stop All)_" style="display:none">
<script src="<?autov('/webGui/javascript/jquery.switchbutton.js')?>"></script>
<script src="<?autov('/plugins/dynamix.vm.manager/javascript/dynamix.vm.manager.js')?>"></script>
@@ -166,45 +136,36 @@ function changemedia(uuid,dev,bus,file) {
if (file === "--select") getisoimage(uuid,dev,bus,file);
if (file === "--eject") ajaxVMDispatch({action:"change-media", uuid:uuid , cdrom:"" , dev:dev , bus:bus , file:file}, "loadlist");
}
function dialogStyle() {
$('.ui-dialog-titlebar-close').css({'display':'none'});
$('.ui-dialog-title').css({'text-align':'center','width':'100%','font-size':'1.8rem'});
$('.ui-dialog-content').css({'padding-top':'15px','vertical-align':'bottom'});
$('.ui-button-text').css({'padding':'0px 5px'});
}
function getisoimageboth(uuid,dev,bus,file,dev2,bus2,file2){
var root = <?= '"'.$domain_cfg["MEDIADIR"].'"';?>;
var match= ".iso";
var box = $("#dialogWindow");
box.html($("#templateISOboth").html());
box.find('#target').attr('data-pickroot',root).attr('data-picktop',root).attr('data-pickmatch',match).attr('value', file).fileTreeAttach(null,null,function(path){
var bits = path.substr(1).split('/');
var auto = bits.length>3 ? '' : share;
box.find('#target').val(path+auto).change();
});
box.find('#target2').attr('data-pickroot',root).attr('data-picktop',root).attr('data-pickmatch',match).attr('value', file2).fileTreeAttach(null,null,function(path){
var bits = path.substr(1).split('/');
var auto = bits.length>3 ? '' : share;
box.find('#target2').val(path+auto).change();
});
var height = 100;
box.find('#target').attr('value',file).fileTreeAttach(null,null,function(path){
box.find('#target').val(path).change();
});
box.find('#target2').attr('value',file2).fileTreeAttach(null,null,function(path){
box.find('#target2').val(path).change();
});
box.dialog({
title: "Select ISOs for CDROMs",
title: "_(Select ISOs for CDROMs)_",
height: 530,
width: 900,
resizable: false,
width: 600,
height: 300,
modal: true,
show: {effect:'fade', duration:250},
hide: {effect:'fade', duration:250},
buttons: {
"_(Update)_": function(){
var target = box.find('#target');
if (target.length) {
target = target.val();
} else target = '';
if (target.length) target = target.val(); else target = '';
var target2 = box.find('#target2');
if (target2.length) {
target2 = target2.val();
} else target2 = '';
if (target2.length) target2 = target2.val(); else target2 = '';
box.find('#target').prop('disabled',true);
box.find('#target2').prop('disabled',true);
ajaxVMDispatch({action:"change-media-both", uuid:uuid , cdrom:"" , dev:dev , bus:bus , file:target, dev2:dev2 , bus2:bus2 , file2:target2}, "loadlist");
ajaxVMDispatch({action:"change-media-both", uuid:uuid, cdrom:"", dev:dev, bus:bus, file:target, dev2:dev2, bus2:bus2, file2:target2}, "loadlist");
box.dialog('close');
},
"_(Cancel)_": function(){
@@ -215,34 +176,23 @@ function getisoimageboth(uuid,dev,bus,file,dev2,bus2,file2){
dialogStyle();
}
function getisoimage(uuid,dev,bus,file){
var root = <?= '"'.$domain_cfg["MEDIADIR"].'"';?>;
var match= ".iso";
var box = $("#dialogWindow");
box.html($("#templateISO").html());
box.find('#target').attr('data-pickroot',root).attr('data-picktop',root).attr('data-pickmatch',match).fileTreeAttach(null,null,function(path){
var bits = path.substr(1).split('/');
var auto = bits.length>3 ? '' : share;
box.find('#target').val(path+auto).change();
});
var height = 100;
box.find('#target').attr('value',file).fileTreeAttach(null,null,function(path){
box.find('#target').val(path).change();
});
box.dialog({
title: "Select ISO",
title: "_(Select ISO)_",
height: 530,
width: 900,
resizable: false,
width: 600,
height: 300,
modal: true,
show: {effect:'fade', duration:250},
hide: {effect:'fade', duration:250},
buttons: {
"_(Insert)_": function(){
var target = box.find('#target');
if (target.length) {
target = target.val();
if (!target ) {errorTarget(); return;}
} else target = '';
if (target.length) target = target.val(); else target = '';
box.find('#target').prop('disabled',true);
ajaxVMDispatch({action:"change-media", uuid:uuid , cdrom:"" , dev:dev , bus:bus , file:target}, "loadlist");
ajaxVMDispatch({action:"change-media", uuid:uuid, cdrom:"", dev:dev, bus:bus, file:target}, "loadlist");
box.dialog('close');
},
"_(Cancel)_": function(){
@@ -253,44 +203,32 @@ function getisoimage(uuid,dev,bus,file){
dialogStyle();
}
function VMClone(uuid, name){
//var root = <?= '"'.$domain_cfg["MEDIADIR"].'"';?>;
var match= ".iso";
var box = $("#dialogWindow");
var height = 200;
box.html($("#templateClone").html());
box.find('#VMBeingCloned').html(name).change() ;
box.find('#target').val(name + "_clone") ;
document.getElementById("Free").checked = true ;
document.getElementById("Overwrite").checked = true ;
var Cancel = _("Cancel") ;
box.find('#VMBeingCloned').html(name).change();
box.find('#target').val(name + "_clone");
document.getElementById("Free").checked = true;
document.getElementById("Overwrite").checked = true;
box.dialog({
title: "VM Clone",
resizable: false,
title: "_(VM Clone)_",
height: 'auto',
width: 600,
height: 500,
resizable: false,
modal: true,
show: {effect:'fade', duration:250},
hide: {effect:'fade', duration:250},
buttons: {
"_(Clone)_" : function(){
"_(Clone)_": function(){
var target = box.find('#target');
if (target.length) {
target = target.val();
//if (!target ) {errorTarget(); return;}
//if (!target) {errorTarget(); return;}
} else target = '';
var clone = box.find("#target").prop('value') ;
x = box.find('#Start').prop('checked') ;
if (x) start = 'yes' ; else start = 'no' ;
x = box.find('#Edit').prop('checked') ;
if (x) edit = 'yes' ; else edit = 'no' ;
x = box.find('#Overwrite').prop('checked') ;
if (x) overwrite = 'yes' ; else overwrite = 'no' ;
x = box.find('#Free').prop('checked') ;
if (x) free = 'yes' ; else free = 'no' ;
scripturl = "VMClone.php " + encodeURIComponent("/usr/local/emhttp/plugins/dynamix.vm.manager/include/VMClone.php&" + $.param({action:"clone" , name:name ,clone:clone, overwrite:overwrite , edit:edit, start,start, free:free})) ;
openVMAction((scripturl),"VM Clone", "dynamix.vm.manager", "loadlist") ;
var clone = box.find("#target").prop('value');
var start = box.find('#Start').prop('checked') ? 'yes' : 'no';
var edit = box.find('#Edit').prop('checked') ? 'yes' : 'no';
var overwrite = box.find('#Overwrite').prop('checked') ? 'yes' : 'no';
var free = box.find('#Free').prop('checked') ? 'yes' : 'no';
scripturl = "VMClone.php " + encodeURIComponent("/usr/local/emhttp/plugins/dynamix.vm.manager/include/VMClone.php&" + $.param({action:"clone", name:name, clone:clone, overwrite:overwrite, edit:edit, start:start, free:free}));
openVMAction((scripturl),"VM Clone", "dynamix.vm.manager", "loadlist");
box.dialog('close');
},
"_(Cancel)_": function(){
@@ -300,44 +238,30 @@ function VMClone(uuid, name){
});
dialogStyle();
}
function selectsnapshot(uuid, name ,snaps, opt, getlist,state){
var root = <?= '"'.$domain_cfg["MEDIADIR"].'"';?>;
var match= ".iso";
var box = $("#dialogWindow2");
var box = $("#dialogWindow");
box.html($("#templatesnapshot"+opt).html());
var height = 200;
const Capopt = opt.charAt(0).toUpperCase() + opt.slice(1) ;
var optiontext = Capopt + " Snapshot" ;
box.find('#VMName').html(name) ;
box.find('#targetsnap').val(snaps) ;
box.find('#targetsnapl').html(snaps) ;
const capopt = opt.charAt(0).toUpperCase() + opt.slice(1);
var optiontext = capopt + " _(Snapshot)_";
box.find('#VMName').html(name);
box.find('#targetsnap').val(snaps);
box.find('#targetsnapl').html(snaps);
if (getlist) {
var only = 1 ;
if (opt == "remove") only = 0;
$.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) ;
}
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');
}
document.getElementById("targetsnaprmv").checked = true ;
document.getElementById("targetsnaprmvmeta").checked = true ;
document.getElementById("targetsnapkeep").checked = true ;
document.getElementById("targetsnapfspc").checked = true ;
document.getElementById("targetsnaprmv").checked = true;
document.getElementById("targetsnaprmvmeta").checked = true;
document.getElementById("targetsnapkeep").checked = true;
document.getElementById("targetsnapfspc").checked = true;
box.dialog({
title: "_("+optiontext+ ")_",
resizable: false,
title: optiontext,
height: 'auto',
width: 600,
height: 500,
resizable: false,
modal: true,
show: {effect:'fade', duration:250},
hide: {effect:'fade', duration:250},
buttons: {
"_(Proceed)_": function(){
var target = box.find('#targetsnap');
@@ -345,26 +269,22 @@ function selectsnapshot(uuid, name ,snaps, opt, getlist,state){
target = target.val();
if (!target ) {errorTarget(); return;}
} else target = '';
var remove = 'yes'
var keep = 'yes'
var removemeta = 'yes'
var remove = 'yes'
var keep = 'yes'
var removemeta = 'yes'
var free = 'yes'
var desc = ''
box.find('#targetsnap').prop('disabled',true);
if (opt == "revert") {
var x = box.find('#targetsnaprmv').prop('checked') ;
if (x) remove = 'yes' ; else remove = 'no' ;
x = box.find('#targetsnaprmvmeta').prop('checked') ;
if (x) removemeta = 'yes' ; else removemeta = 'no' ;
x = box.find('#targetsnapkeep').prop('checked') ;
if (x) keep = 'yes' ; else keep = 'no' ;
remove = box.find('#targetsnaprmv').prop('checked') ? 'yes' : 'no';
removemeta = box.find('#targetsnaprmvmeta').prop('checked') ? 'yes' : 'no';
keep = box.find('#targetsnapkeep').prop('checked') ? 'yes' : 'no';
}
if (opt == "create") {
var x = box.find('#targetsnapfspc').prop('checked') ;
if (x) free = 'yes' ; else free = 'no' ;
var desc = box.find("#targetsnapdesc").prop('value') ;
if (opt == "create") {
free = box.find('#targetsnapfspc').prop('checked') ? 'yes' : 'no';
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} , "loadlist");
ajaxVMDispatch({action:"snap-" + opt +'-external', uuid:uuid, snapshotname:target, remove:remove, free:free, removemeta:removemeta, keep:keep, desc:desc}, "loadlist");
box.dialog('close');
},
"_(Cancel)_": function(){
@@ -374,86 +294,72 @@ function selectsnapshot(uuid, name ,snaps, opt, getlist,state){
});
dialogStyle();
}
function selectblock(uuid, name ,snaps, opt, getlist,state){
var root = <?= '"'.$domain_cfg["MEDIADIR"].'"';?>;
var match= ".iso";
var box = $("#dialogWindow2");
function selectblock(uuid, name, snaps, opt, getlist, state){
var box = $("#dialogWindow");
box.html($("#templateblock").html());
var height = 200;
const Capopt = opt.charAt(0).toUpperCase() + opt.slice(1) ;
var optiontext = Capopt + " Block Devices" ;
box.find('#VMName').html(name) ;
box.find('#targetsnap').val(snaps) ;
box.find('#targetsnapl').html(snaps) ;
getlist = true ;
const capopt = opt.charAt(0).toUpperCase() + opt.slice(1);
var optiontext = capopt + " _(Block Devices)_";
box.find('#VMName').html(name);
box.find('#targetsnap').val(snaps);
box.find('#targetsnapl').html(snaps);
getlist = true;
if (getlist) {
var only = 1 ;
var only = 1;
if (opt == "remove") only = 0;
$.post("/plugins/dynamix.vm.manager/include/VMajax.php", {action:"snap-list", uuid:uuid }, function(data) {
if (data.html) {
var targetbase = document.getElementById("targetblockbase") ;
htmlstrbase = "<select class='targetblockbase' name='targetblockbase' id='targetblockbase'><option value='--base'>--base</option>" + data.html + "</select>"
htmlstrtop = "<select class='targetblocktop' name='targetblocktop' id='targetblocktop'><option value='--top'>--top</option>" + data.html + "</select>"
$("select.targetblockbase").replaceWith(htmlstrbase) ;
$("select.targetblocktop").replaceWith(htmlstrtop) ;
}
$.post("/plugins/dynamix.vm.manager/include/VMajax.php", {action:"snap-list", uuid:uuid}, function(data){
if (data.html) {
var targetbase = document.getElementById("targetblockbase");
htmlstrbase = "<select class='targetblockbase' name='targetblockbase' id='targetblockbase'><option value='--base'>--base</option>" + data.html + "</select>"
htmlstrtop = "<select class='targetblocktop' name='targetblocktop' id='targetblocktop'><option value='--top'>--top</option>" + data.html + "</select>"
$("select.targetblockbase").replaceWith(htmlstrbase);
$("select.targetblocktop").replaceWith(htmlstrtop);
}
},'json');
}
document.getElementById("targetsnaprmv").checked = true ;
document.getElementById("targetsnaprmvmeta").checked = true ;
document.getElementById("targetsnapkeep").checked = true ;
document.getElementById("targetsnapfspc").checked = true ;
if (opt== "pull") {
$('.toprow').hide();
$('.targetpivotrow').hide();
$('.targetdeleterow').hide();
} else {
$('.toprow').show();
$('.targetpivotrow').show();
$('.targetdeleterow').show();
}
document.getElementById("targetsnaprmv").checked = true;
document.getElementById("targetsnaprmvmeta").checked = true;
document.getElementById("targetsnapkeep").checked = true;
document.getElementById("targetsnapfspc").checked = true;
if (opt == "pull") {
$('.toprow').hide();
$('.targetpivotrow').hide();
$('.targetdeleterow').hide();
} else {
$('.toprow').show();
$('.targetpivotrow').show();
$('.targetdeleterow').show();
}
box.dialog({
title: "_("+optiontext+ ")_",
resizable: false,
title: optiontext,
height: 'auto',
width: 600,
height: 500,
resizable: false,
modal: true,
show: {effect:'fade', duration:250},
hide: {effect:'fade', duration:250},
buttons: {
_("Action")_: function(){
"_(Action)_": function(){
var target = box.find('#targetsnap');
if (target.length) {
target = target.val();
if (!target ) {errorTarget(); return;}
} else target = '';
var remove = 'yes'
var keep = 'yes'
var removemeta = 'yes'
var remove = 'yes'
var keep = 'yes'
var removemeta = 'yes'
var free = 'yes'
var delete_file = 'yes'
var pivot = 'yes'
var desc = ''
box.find('#targetsnap').prop('disabled',true);
if (opt == "create") {
var x = box.find('#targetsnapfspc').prop('checked') ;
if (x) free = 'yes' ; else free = 'no' ;
var desc = box.find("#targetsnapdesc").prop('value') ;
free = box.find('#targetsnapfspc').prop('checked') ? 'yes' : 'no';
var desc = box.find("#targetsnapdesc").prop('value');
}
var targetbase = box.find("#targetblockbase").prop('value') ;
var targettop = box.find("#targetblocktop").prop('value') ;
x = box.find('#targetpivot').prop('checked') ;
if (x) pivot = 'yes' ; else pivot = 'no' ;
x = box.find('#targetdelete').prop('checked') ;
if (x) delete_file = 'yes' ; else delete_file = 'no' ;
Ajaxurl = "VMAjaxCall.php " + encodeURIComponent("/usr/local/emhttp/plugins/dynamix.vm.manager/include/VMajax.php&" + $.param({action:opt , name:name ,targetbase:targetbase, targettop:targettop , snapshotname:target , remove:remove, targetpivot:pivot ,removemeta:removemeta ,targetdelete:delete_file})) ;
openVMAction((Ajaxurl),"Block Commit", "dynamix.vm.manager", "loadlist") ;
var targetbase = box.find("#targetblockbase").prop('value');
var targettop = box.find("#targetblocktop").prop('value');
pivot = box.find('#targetpivot').prop('checked') ? 'yes' : 'no';
delete_file = box.find('#targetdelete').prop('checked') ? 'yes' : 'no';
Ajaxurl = "VMAjaxCall.php " + encodeURIComponent("/usr/local/emhttp/plugins/dynamix.vm.manager/include/VMajax.php&" + $.param({action:opt, name:name, targetbase:targetbase, targettop:targettop, snapshotname:target, remove:remove, targetpivot:pivot, removemeta:removemeta, targetdelete:delete_file}));
openVMAction((Ajaxurl),"Block Commit", "dynamix.vm.manager", "loadlist");
box.dialog('close');
},
"_(Cancel)_": function(){
@@ -463,13 +369,6 @@ function selectblock(uuid, name ,snaps, opt, getlist,state){
});
dialogStyle();
}
function dialogStyle() {
$('.ui-dialog-titlebar-close').css({'background':'transparent','border':'none','font-size':'1.8rem','margin-top':'-14px','margin-right':'-18px'}).html('<i class="fa fa-times"></i>').prop('title');
$('.ui-dialog-title').css({'text-align':'center','width':'100%','font-size':'1.8rem'});
$('.ui-dialog-content').css({'padding-top':'15px','vertical-align':'bottom'});
$('.ui-button-text').css({'padding':'0px 5px'});
}
var sortableHelper = function(e,ui){
var child = ui.next();
if (child.is(':visible')) child.addClass('unhide').hide();
@@ -561,123 +460,75 @@ $(function() {
});
</script>
<table id="kvm_table" class="tablesorter four shift">
<thead><tr><th class="th1"><a id="resetsort" class="nohand" onclick="resetSorting()" title="Reset sorting"><i class="fa fa-th-list"></i></a>_(Name)_</th><th class="th2">_(Description)_</th><th>_(CPUs)_</th><th>_(Memory)_</th><th>_(vDisks / vCDs)_</th><th>_(Graphics)_</th><th>_(IP Address)_</th><th class="th3">_(Autostart)_</th></tr></thead>
<tbody id="kvm_list"><tr><td colspan='8'></td></tr></tbody>
</table>
<input type="button" onclick="addVM()" id="btnAddVM" value="_(Add VM)_" style="display:none">
<input type="button" onclick="startAll()" value="_(Start All)_" style="display:none">
<input type="button" onclick="stopAll()" value="_(Stop All)_" style="display:none">
<div id="dialogWindow"></div>
<div markdown="1" id="templateISO" class="template">
_(ISO Image)_:
: <input type="text" id="target" autocomplete="off" spellcheck="false" value="" data-pickcloseonfile="true" data-pickfolders="true" data-pickfilter="" data-pickmatch="" data-pickroot="" data-picktop="">
<div id="templateISO" class="template">
<dl>
<dt>_(ISO Image)_:</dt>
<dd><input type="text" id="target" autocomplete="off" spellcheck="false" value="" data-pickcloseonfile="true" data-pickfolders="true" data-pickfilter="iso"></dd>
</dl>
</div>
<div markdown="1" id="templateISOboth" class="template">
_(CD1 ISO Image)_:
: <input type="text" id="target" autocomplete="off" spellcheck="false" value="" data-pickcloseonfile="true" data-pickfolders="true" data-pickfilter="" data-pickmatch="" data-pickroot="" data-picktop=""><br>
_(CD2 ISO Image)_:
: <input type="text" id="target2" autocomplete="off" spellcheck="false" value="" data-pickcloseonfile="true" data-pickfolders="true" data-pickfilter="" data-pickmatch="" data-pickroot="" data-picktop="">
<div id="templateISOboth" class="template">
<dl>
<dt>_(CD1 ISO Image)_:</dt>
<dd><input type="text" id="target" autocomplete="off" spellcheck="false" value="" data-pickcloseonfile="true" data-pickfolders="true" data-pickfilter="iso"></dd>
<dt>_(CD2 ISO Image)_:</dt>
<dd><input type="text" id="target2" autocomplete="off" spellcheck="false" value="" data-pickcloseonfile="true" data-pickfolders="true" data-pickfilter="iso"></dd>
</dl>
</div>
<div id="dialogWindow2"></div>
<div markdown="1" id="templatesnapshotcreate" class="template">
<table id='snapshot'>
<br><br>
<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>
<div id="templatesnapshotcreate" class="template">
<table id='snapshot' class='snapshot'>
<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>
</table>
</div>
<div markdown="1" id="templatesnapshotrevert" class="template">
_(VM Name)_:
<label id="VMName"></label>
<br>
_(Snapshot Name)_:
<input type="text" id="targetsnap" hidden>
<label id="targetsnapl"></label><br>
_(Remove Images)_:
<input type="checkbox" id="targetsnaprmv" checked >
_(Remove Meta)_:
<input type="checkbox" id="targetsnaprmvmeta" checked>
<!--_(Keep snapshot)_:-->
<input type="checkbox" id="targetsnapkeep" hidden><br>
<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>
_(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>
<label id="targetsnapimages"></label><br>
<div id="templatesnapshotremove" class="template">
<h3>!! _(Warning removing Snapshots can break the chain)_ !!</h3>
<div markdown="1" id="templatesnapshotremove" class="template" post>
_(!! Warning removing Snapshots can break the chain !!)_<br><br>
_(VM Name)_: <label id="VMName"></label><br>
_(Snapshot Name)_: <input type="text" id="targetsnap" hidden><label id="targetsnapl"></label><label id="targetsnapimages"></label>
</div>
_(VM Name)_:
<label id="VMName"></label>
<br>
_(Snapshot Name)_:
<input type="text" id="targetsnap" hidden>
<label id="targetsnapl"></label><br>
<label id="targetsnapimages"></label><br>
<div markdown="1" id="templateblock" class="template">
_(VM Name)_:
<label id="VMName"></label>
<br>
_(Snapshot Name)_:
<input type="text" id="targetsnap" hidden>
<label id="targetsnapl"></label><br>
<br><br><br><br>
<table id='block'>
<tr><td>_(Base Image)_:</td><td>
<select class="targetblockbase" s>
</select></td></tr>
<tr name="toprow" class="toprow" ><td>_(Top Image )_:</td><td>
<select class="targetblocktop" name="targetblocktop" id="targetblocktop">
</select></td><td>
<tr name="targetpivotrow" class="targetpivotrow" ><td>_(Pivot)_:</td><td>
<input type="checkbox" id="targetpivot" checked></td></tr>
<tr name="targetdeleterow" class="targetdeleterow" ><td>_(Delete)_:</td><td>
<input type="checkbox" id="targetdelete" checked></td></tr>
<div id="templateblock" class="template">
_(VM Name)_: <label id="VMName"></label><br>
_(Snapshot Name)_: <input type="text" id="targetsnap" hidden><label id="targetsnapl"></label><br><br>
<table id='block' class='snapshot'>
<tr><td>_(Base Image)_:</td><td><select class="targetblockbase"></select></td></tr>
<tr name="toprow" class="toprow" ><td>_(Top Image )_:</td><td><select class="targetblocktop" name="targetblocktop" id="targetblocktop"></select></td><td></tr>
<tr name="targetpivotrow" class="targetpivotrow" ><td>_(Pivot)_:</td><td><input type="checkbox" id="targetpivot" checked></td></tr>
<tr name="targetdeleterow" class="targetdeleterow" ><td>_(Delete)_:</td><td><input type="checkbox" id="targetdelete" checked></td></tr>
</table>
<input type="checkbox" id="targetsnapkeep" hidden><br>
<label id="targetsnapimages"></label><br>
</div>
<div id="dialogWindow"></div>
<div markdown="1" id="templateClone" class="template">
<html <?=$display['rtl']?>lang="<?=strtok($locale,'_')?:'en'?>">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="format-detection" content="telephone=no">
<meta name="viewport" content="width=1600">
<meta name="robots" content="noindex, nofollow">
<meta name="referrer" content="same-origin">
<link type="text/css" rel="stylesheet" href="<?autov("/webGui/styles/default-fonts.css")?>">
</head>
<body>
<br>
<table>
<tr><td>_(VM Being Cloned)_:</td>
<td><span id="VMBeingCloned"></span></td></tr>
<tr><td>_(New VM)_:</td>
<td><input type="text" id="target" autocomplete="off" spellcheck="false" value="" onclick="this.select()" ></td></tr>
<tr><td>_(Overwrite)_:</td>
<td><input type="checkbox" id="Overwrite" value="" ></td></tr>
<tr hidden><td>_(Start Cloned VM)_:</td>
<td><input type="checkbox" id="Start" value="" ></td></tr>
<tr hidden><td>_(Edit VM after clone)_:</td>
<td><input type="checkbox" id="Edit" value="" ></td></tr>
<tr><td>_(Check Free Space)_:</td>
<td><input type="checkbox" id="Free" value="" ></td></tr>
<div id="templateClone" class="template">
<table class='snapshot'>
<tr><td>_(VM Being Cloned)_:</td><td><span id="VMBeingCloned"></span></td></tr>
<tr><td>_(New VM)_:</td><td><input type="text" id="target" autocomplete="off" spellcheck="false" value="" onclick="this.select()" ></td></tr>
<tr><td>_(Overwrite)_:</td><td><input type="checkbox" id="Overwrite" value="" ></td></tr>
<tr hidden><td>_(Start Cloned VM)_:</td><td><input type="checkbox" id="Start" value="" ></td></tr>
<tr hidden><td>_(Edit VM after clone)_:</td><td><input type="checkbox" id="Edit" value="" ></td></tr>
<tr><td>_(Check Free Space)_:</td><td><input type="checkbox" id="Free" value="" ></td></tr>
</table>
</body>
</html>
</div>
</div>
</div>

View File

@@ -5,8 +5,8 @@ Tag="columns"
---
<?PHP
/* Copyright 2005-2023, Lime Technology
* Copyright 2015-2023, Derek Macias, Eric Schultz, Jon Panozzo.
* Copyright 2012-2023, Bergware International.
* Copyright 2015-2021, Derek Macias, Eric Schultz, Jon Panozzo.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2,
@@ -51,7 +51,7 @@ function detect(&$syslinux, $key) {
return $value;
}
$syslinux = file('/boot/syslinux/syslinux.cfg',FILE_IGNORE_NEW_LINES+FILE_SKIP_EMPTY_LINES);
$arrValidNetworks = getValidNetworks();
$arrValidNetworks = getValidNetworks();
$pcie_acs_override = detect($syslinux, 'pcie_acs_override');
$vfio_allow_unsafe = detect($syslinux, 'allow_unsafe_interrupts');
$bgcolor = strstr('white,azure',$display['theme']) ? '#f2f2f2' : '#1c1c1c';
@@ -61,21 +61,6 @@ $libvirt_log = file_exists("/var/log/libvirt/libvirtd.log");
?>
<link type="text/css" rel="stylesheet" href="<?autov('/webGui/styles/jquery.filetree.css')?>">
<link type="text/css" rel="stylesheet" href="<?autov('/webGui/styles/jquery.switchbutton.css')?>">
<style>
body{-webkit-overflow-scrolling:touch}
.errortext{color:#EF3D47;display:none}
.fileTree{background:<?=$bgcolor?>;width:300px;max-height:150px;overflow-y:scroll;overflow-x:hidden;position:absolute;z-index:100;display:none}
.basic{display:block}
.advanced{display:none}
#winvirtio{display:none}
#download_status{margin-left:5px;color:#777;display:none}
#download_button{cursor:pointer;margin-left:-2px;color:#08C;display:none;transform:translate(0px,2px)}
#download_button.fa-spin{cursor:default;color:#777}
#download_button span{font-family:clear-sans}
#download_button.fa-spin span{font-family:clear-sans;display:none}
#remove_button{cursor:pointer;margin-left:-2px;color:#EF3D47;display:none;transform:translate(0px,2px)}
#remove_button span{font-family:clear-sans}
</style>
<?if ($hardware):?>
<span class="status vhshift"><input type="checkbox" class="advancedview"></span>
@@ -99,6 +84,14 @@ _(Enable VMs)_:
:vms_enable_help:
_(Disable Autostart/Start option for VMs)_:
: <select id="DISABLE" name="DISABLE">
<?= mk_option(htmlspecialchars($domain_cfg['DISABLE']), 'no', _('No'))?>
<?= mk_option(htmlspecialchars($domain_cfg['DISABLE']), 'yes', _('Yes'))?>
</select>
:vms_disable_help:
<?if ($hardware):?>
<div class="advanced" markdown="1">
<?if ($libvirt_up):?>
@@ -233,7 +226,7 @@ _(VFIO allow unsafe interrupts)_:
_(btrfs filesystem show)_:
: <?="<pre id='btrfs-scrub'>".shell_exec("btrfs filesystem show /etc/libvirt")."</pre>"?>
<form markdown="1" method="POST" action="/update.php" target="progressFrame" onsubmit="prepareFS(this,'btrfs-scrub-vm','/etc/libvirt'>">
<form markdown="1" method="POST" action="/update.php" target="progressFrame" onsubmit="prepareFS(this,'btrfs-scrub-vm','/etc/libvirt')>">
<?exec("$docroot/webGui/scripts/btrfs_scrub status /etc/libvirt", $scrub_status, $retval);?>
_(btrfs scrub status)_:
: <?="<pre>".implode("\n", $scrub_status)."</pre>"?>

View File

@@ -4,8 +4,9 @@ Cond="(pgrep('libvirtd')!==false)"
Markdown="false"
---
<?PHP
/* Copyright 2005-2020, Lime Technology
* Copyright 2015-2020, Derek Macias, Eric Schultz, Jon Panozzo.
/* Copyright 2005-2023, Lime Technology
* Copyright 2012-2023, Bergware International.
* Copyright 2015-2021, Derek Macias, Eric Schultz, Jon Panozzo.
*
* 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,14 +16,8 @@ Markdown="false"
* all copies or substantial portions of the Software.
*/
?>
<style type="text/css">
.vmheader{padding:10px;font-size:1.4rem;text-align:left;color:#888}
.vmtemplate{display:inline-block;width:80px;height:90px;margin-bottom:15px;margin-left:10px;text-align:center;vertical-align:top}
.vmtemplate img{width:48px;height:48px}
.vmtemplate p{text-align:center;margin-top:8px;line-height:12px}
</style>
<?
$docroot = $docroot ?? $_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp';
$docroot ??= ($_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp');
require_once "$docroot/plugins/dynamix.vm.manager/include/libvirt_helpers.php";
foreach($arrAllTemplates as $strName => $arrTemplate):

View File

@@ -5,8 +5,9 @@ Lock="true"
Cond="exec(\"grep -o '^SERVICE=.enable' /boot/config/domain.cfg 2>/dev/null\")"
---
<?PHP
/* Copyright 2005-2020, Lime Technology
* Copyright 2015-2020, Derek Macias, Eric Schultz, Jon Panozzo.
/* Copyright 2005-2023, Lime Technology
* Copyright 2012-2023, Bergware International.
* Copyright 2015-2021, Derek Macias, Eric Schultz, Jon Panozzo.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2,

View File

@@ -1,7 +1,7 @@
<?PHP
/* Copyright 2005-2021, Lime Technology
/* Copyright 2005-2023, Lime Technology
* Copyright 2012-2023, Bergware International.
* Copyright 2015-2021, Derek Macias, Eric Schultz, Jon Panozzo.
* Copyright 2012-2021, 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,14 +12,14 @@
*/
?>
<?
$docroot = $docroot ?? $_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp';
$docroot ??= ($_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp');
require_once "$docroot/plugins/dynamix/include/Helpers.php";
require_once "$docroot/plugins/dynamix.vm.manager/include/libvirt_helpers.php";
// add translations
$_SERVER['REQUEST_URI'] = 'vms';
require_once "$docroot/webGui/include/Translations.php";
require_once "$docroot/plugins/dynamix/include/Helpers.php";
require_once "$docroot/plugins/dynamix.vm.manager/include/libvirt_helpers.php";
// get Fedora download archive
$fedora = '/var/tmp/fedora-virtio-isos';
$archive = 'https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/archive-virtio';

View File

@@ -1,7 +1,7 @@
<?PHP
/* Copyright 2005-2020, Lime Technology
* Copyright 2015-2020, Derek Macias, Eric Schultz, Jon Panozzo.
* Copyright 2012-2020, Bergware International.
/* Copyright 2005-2023, Lime Technology
* Copyright 2012-2023, Bergware International.
* Copyright 2015-2021, Derek Macias, Eric Schultz, Jon Panozzo.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2,

View File

@@ -1,7 +1,7 @@
<?PHP
/* Copyright 2005-2023, Lime Technology
* Copyright 2015-2023, Derek Macias, Eric Schultz, Jon Panozzo.
* Copyright 2012-2023, Bergware International.
* Copyright 2015-2021, Derek Macias, Eric Schultz, Jon Panozzo.
*
* 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,13 +12,13 @@
*/
?>
<?
$docroot = $docroot ?? $_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp';
$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";
// add translations
$_SERVER['REQUEST_URI'] = 'vms';
require_once "$docroot/webGui/include/Translations.php";
require_once "$docroot/webGui/include/Helpers.php";
require_once "$docroot/plugins/dynamix.vm.manager/include/libvirt_helpers.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 ;
@@ -28,7 +28,7 @@ if (empty($vms)) {
return;
}
if (file_exists($user_prefs)) {
$prefs = @parse_ini_file($user_prefs) ?: [];
$prefs = (array)@parse_ini_file($user_prefs);
$sort = [];
foreach ($vms as $vm) $sort[] = array_search($vm,$prefs);
array_multisort($sort,SORT_NUMERIC,$vms);
@@ -75,27 +75,31 @@ foreach ($vms as $vm) {
$autoport = $lv->domain_get_vmrc_autoport($res);
$vmrcurl = '';
$graphics = '';
$virtual = false ;
if ($vmrcport > 0) {
$wsport = $lv->domain_get_ws_port($res);
$vmrcprotocol = $lv->domain_get_vmrc_protocol($res);
$vmrcurl = autov('/plugins/dynamix.vm.manager/'.$vmrcprotocol.'.html',true).'&autoconnect=true&host='._var($_SERVER,'HTTP_HOST');
if ($vmrcprotocol == "spice") $vmrcurl .= '&vmname='. urlencode($vm) .'&port=/wsproxy/'.$vmrcport.'/'; else $vmrcurl .= '&port=&path=/wsproxy/'.$wsport.'/';
$graphics = strtoupper($vmrcprotocol).":".$vmrcport;
$graphics = strtoupper($vmrcprotocol).":".$vmrcport."\n";
$virtual = true ;
} elseif ($vmrcport == -1 || $autoport) {
$vmrcprotocol = $lv->domain_get_vmrc_protocol($res);
if ($autoport == "yes") $auto = "auto"; else $auto="manual";
$graphics = strtoupper($vmrcprotocol).':'._($auto);
} elseif (!empty($arrConfig['gpu'])) {
$graphics = strtoupper($vmrcprotocol).':'._($auto)."\n";
$virtual = true ;
}
if (!empty($arrConfig['gpu'])) {
$arrValidGPUDevices = getValidGPUDevices();
foreach ($arrConfig['gpu'] as $arrGPU) {
foreach ($arrValidGPUDevices as $arrDev) {
if ($arrGPU['id'] == $arrDev['id']) {
if (count(array_filter($arrValidGPUDevices, function($v) use ($arrDev) { return $v['name'] == $arrDev['name']; })) > 1) {
$graphics .= $arrDev['name'].' ('.$arrDev['id'].')'."\n";
$vmrcprotocol = "VGA";
if (!$virtual) $vmrcprotocol = "VGA";
} else {
$graphics .= $arrDev['name']."\n";
$vmrcprotocol = "VGA";
if (!$virtual) $vmrcprotocol = "VGA";
}
}
}
@@ -126,10 +130,9 @@ foreach ($vms as $vm) {
}
/* VM information */
if ($snapshots != null) $snapshotstr = _("(Snapshots :").count($snapshots).')' ; else $snapshotstr = _("(Snapshots :None)") ;
$cdbus = $cdbus2 = $cdfile = $cdfile2 = "" ;
$cdromcount = 0 ;
if ($snapshots != null) $snapshotstr = _("(Snapshots :").count($snapshots).')'; else $snapshotstr = _("(Snapshots :None)");
$cdbus = $cdbus2 = $cdfile = $cdfile2 = "";
$cdromcount = 0;
foreach ($cdroms as $arrCD) {
$disk = $arrCD['file'] ?? $arrCD['partition'];
$dev = $arrCD['device'];
@@ -137,30 +140,67 @@ foreach ($vms as $vm) {
if ($dev == "hda") {
$cdbus = $arrValidDiskBuses[$arrCD['bus']] ?? 'VirtIO';
$cdfile = $arrCD['file'] ?? $arrCD['partition'];
if ($cdfile != "") $cdromcount++ ;
if ($cdfile != "") $cdromcount++;
}
if ($dev == "hdb") {
$cdbus2 = $arrValidDiskBuses[$arrCD['bus']] ?? 'VirtIO';
$cdfile2 = $arrCD['file'] ?? $arrCD['partition'];
if ($cdfile2 != "") $cdromcount++ ;
if ($cdfile2 != "") $cdromcount++;
}
}
$ipliststr = $iptablestr = "" ;
$gastate = getgastate($res);
if ($gastate == "connected") {
$ip = $lv->domain_interface_addresses($res, 1);
if ($ip != false) {
$duplicates = []; // hide duplicate interface names
foreach ($ip as $arrIP) {
$ipname = $arrIP["name"];
if (preg_match('/^(lo|Loopback)/',$ipname)) continue; // omit loopback interface
$iphdwadr = $arrIP["hwaddr"] == "" ? _("N/A") : $arrIP["hwaddr"];
$iplist = $arrIP["addrs"];
foreach ($iplist as $arraddr) {
$ipaddrval = $arraddr["addr"];
if (preg_match('/^f[c-f]/',$ipaddrval)) continue; // omit ipv6 private addresses
$iptype = $arraddr["type"] ? "ipv6" : "ipv4";
$ipprefix = $arraddr["prefix"];
$ipnamemac = "$ipname ($iphdwadr)";
if (!in_array($ipnamemac,$duplicates)) $duplicates[] = $ipnamemac; else $ipnamemac = "";
$ipliststr .= "<tr><td>$ipnamemac</td><td></td><td></td><td>$iptype</td><td>$ipaddrval</td><td>$ipprefix</td></tr>";
$iptablestr .= "$ipaddrval/$ipprefix\n" ;
}
}
}
} else {
if ($gastate == "disconnected") {
$ipliststr .= "<tr><td>"._('Guest agent not installed')."</td><td></td><td></td><td></td></tr>";
$iptablestr = _('Requires guest agent installed');
} else {
$ipliststr = "<tr><td>"._('Guest not running')."</td><td></td><td></td><td></td><td></td></tr>";
$iptablestr = _('Requires guest running');
}
}
$iptablestr = str_replace("\n", "<br>", trim($iptablestr));
$changemedia = "getisoimageboth(\"{$uuid}\",\"hda\",\"{$cdbus}\",\"{$cdfile}\",\"hdb\",\"{$cdbus2}\",\"{$cdfile2}\")";
$cdstr = $cdromcount." / 2<a class='hand' title='$title' href='#' onclick='$changemedia'> <i class='fa fa-bullseye' ></i></a>";
$title = _('Select ISO image');
$cdstr = $cdromcount." / 2<a class='hand' title='$title' href='#' onclick='$changemedia'><i class='fa fa-circle-o'></i></a>";
echo "<tr parent-id='$i' class='sortable'><td class='vm-name' style='width:220px;padding:8px'><i class='fa fa-arrows-v mover orange-text'></i>";
echo "<span class='outer'><span id='vm-$uuid' $menu class='hand'>$image</span><span class='inner'><a href='#' onclick='return toggle_id(\"name-$i\")' title='click for more VM info'>$vm</a><br><i class='fa fa-$shape $status $color'></i><span class='state'>"._($status)." $snapshotstcount</span></span></span></td>";
echo "<td>$desc</td>";
echo "<td><a class='vcpu-$uuid' style='cursor:pointer'>$vcpu</a></td>";
echo "<td>$mem</td>";
echo "<td title='$diskdesc'><span class='state' >$disks&nbsp;&nbsp;&nbsp;&nbsp;$cdstr<br>$snapshotstr</span></td>";
echo "<td>$graphics</td>";
echo "<td><span class='vmgraphics'>$graphics</td>";
echo "<td><span class='vmgraphics'>$iptablestr</td>";
echo "<td><input class='autostart' type='checkbox' name='auto_{$vm}' title=\""._('Toggle VM autostart')."\" uuid='$uuid' $autostart></td></tr>";
/* Disk device information */
echo "<tr child-id='$i' id='name-$i".(in_array('name-'.$i++,$show) ? "'>" : "' style='display:none'>");
echo "<td colspan='8' style='margin:0;padding:0'>";
echo "<table class='tablesorter domdisk'>";
echo "<thead class='child'><tr><th><i class='fa fa-hdd-o'></i> <b>"._('Disk devices')."</b></th><th>"._('Serial')."</b></th><th>"._('Bus')."</th><th>"._('Capacity')."</th><th>"._('Allocation')."</th><th>Boot Order</th</tr></thead>";
echo "<thead class='child'><tr><th><i class='fa fa-hdd-o'></i> <b>",_('Disk devices'),"</b></th><th>",_('Serial'),"</b></th><th>",_('Bus'),"</th><th>",_('Capacity'),"</th><th>",_('Allocation'),"</th><th>Boot Order</th</tr></thead>";
echo "<tbody class='child'>";
/* Display VM disks */
@@ -172,7 +212,7 @@ foreach ($vms as $vm) {
$bus = $arrValidDiskBuses[$arrDisk['bus']] ?? 'VirtIO';
$boot= $arrDisk["boot order"];
$serial = $arrDisk["serial"];
if ($boot < 1) $boot="Not set";
if ($boot < 1) $boot = _('Not set');
echo "<tr><td>$disk</td><td>$serial</td><td>$bus</td>";
if ($state == 'shutoff') {
echo "<td title='Click to increase Disk Size'>";
@@ -196,85 +236,56 @@ foreach ($vms as $vm) {
$capacity = $lv->format_size($arrCD['capacity'], 0);
$allocation = $lv->format_size($arrCD['allocation'], 0);
$disk = $arrCD['file'] ?? $arrCD['partition'] ?? "" ;
$dev = $arrCD['device'];
$bus = $arrValidDiskBuses[$arrCD['bus']] ?? 'VirtIO';
$boot= $arrCD["boot order"] ?? "" ;
if ($boot < 1) $boot="Not set";
$dev = $arrCD['device'];
$bus = $arrValidDiskBuses[$arrCD['bus']] ?? 'VirtIO';
$boot = $arrCD["boot order"] ?? "" ;
if ($boot < 1) $boot = _('Not set');
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' aria-hidden=true></i></a></td><td></td><td>$bus</td><td>$capacity</td><td>$allocation</td><td>$boot</td></tr>";
$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>";
} else {
$title = _("Insert CD").".";
$title = _('Insert CD');
$changemedia = "changemedia(\"{$uuid}\",\"{$dev}\",\"{$bus}\",\"--select\")";
$disk = _("No CD image inserted in to drive");
echo "<tr><td>$disk<a title='$title' href='#' onclick='$changemedia'> <i class='fa fa-bullseye' aria-hidden=true></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-circle-o'></i></a></td><td></td><td>$bus</td><td>$capacity</td><td>$allocation</td><td>$boot</td></tr>";
}
}
echo "</tbody>";
/* Display VM IP Addresses "execute":"guest-network-get-interfaces" --pretty */
echo "<thead class='child'><tr><th><i class='fa fa-sitemap'></i> <b>"._('Interfaces')."</b></th><th></th><th></th><th>"._('Type')."</th><th>"._('IP Address')."</th><th>"._('Prefix')."</th></tr></thead>";
echo "<thead class='child'><tr><th><i class='fa fa-sitemap'></i> <b>",_('Interfaces')."</b></th><th></th><th></th><th>",_('Type')."</th><th>",_('IP Address'),"</th><th>",_('Prefix'),"</th></tr></thead>";
echo "<tbody class='child'>";
$gastate = getgastate($res);
if ($gastate == "connected") {
$ip = $lv->domain_interface_addresses($res, 1);
if ($ip != false) {
$duplicates = []; // hide duplicate interface names
foreach ($ip as $arrIP) {
$ipname = $arrIP["name"];
if (preg_match('/^(lo|Loopback)/',$ipname)) continue; // omit loopback interface
$iphdwadr = $arrIP["hwaddr"] == "" ? _("N/A") : $arrIP["hwaddr"];
$iplist = $arrIP["addrs"];
foreach ($iplist as $arraddr) {
$ipaddrval = $arraddr["addr"];
if (preg_match('/^f[c-f]/',$ipaddrval)) continue; // omit ipv6 private addresses
$iptype = $arraddr["type"] ? "ipv6" : "ipv4";
$ipprefix = $arraddr["prefix"];
$ipnamemac = "$ipname ($iphdwadr)";
if (!in_array($ipnamemac,$duplicates)) $duplicates[] = $ipnamemac; else $ipnamemac = "";
echo "<tr><td>$ipnamemac</td><td></td><td></td><td>$iptype</td><td>$ipaddrval</td><td>$ipprefix</td></tr>";
}
}
}
}
else {
if ($gastate == "disconnected") echo "<tr><td>"._('Guest agent not installed')."</td><td></td><td></td><td></td></tr>";
else echo "<tr><td>"._('Guest not running')."</td><td></td><td></td><td></td><td></td></tr>";
}
echo $ipliststr ;
echo "</tbody>";
/* Display VM Snapshots */
if ($snapshots != null) {
$j=0 ;
$steps = array() ;
foreach($snapshots as $snap) {
$j = 0;
$steps = array();
foreach ($snapshots as $snap) {
if ($snap['parent'] == "" || $snap['parent'] == "Base") $j++;
$steps[$j] .= $snap['name'].';' ;
}
echo "<thead class='child' child-id='$i'><tr><th><i class='fa fa-clone'></i> <b>"._('Snapshots')."</b></th><th></th><th>"._('Date/Time')."</th><th>"._('Type')."</th><th>"._('Parent')."</th><th>"._('Memory')."</th></tr></thead>";
echo "<tbody class='child'child-id='$i'>";
foreach($steps as $stepsline)
{
$snapshotlist = explode(";",$stepsline) ;
$tab = "&nbsp;&nbsp;&nbsp;&nbsp;" ;
foreach($snapshotlist as $snapshotitem) {
if ($snapshotitem == "") continue ;
$snapshot = $snapshots[$snapshotitem] ;
$snapshotstate = _(ucfirst($snapshot["state"])) ;
$snapshotdesc = $snapshot["desc"] ;
$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')\"", addslashes($vm),addslashes($uuid),addslashes($template),$state,$snapshot["name"],$vmpreview);
echo "<tr><td><span id='vmsnap-$uuid' $snapmenu class='hand'>$tab|__&nbsp;&nbsp;<i class='fa fa-clone'></i></span>&nbsp;".$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 .="&nbsp;&nbsp;&nbsp;&nbsp;" ;
$steps[$j] .= $snap['name'].';';
}
echo "<thead class='child' child-id='$i'><tr><th><i class='fa fa-clone'></i> <b>",_('Snapshots'),"</b></th><th></th><th>",_('Date/Time'),"</th><th>",_('Type'),"</th><th>",_('Parent'),"</th><th>",_('Memory'),"</th></tr></thead>";
echo "<tbody class='child'child-id='$i'>";
foreach ($steps as $stepsline) {
$snapshotlist = explode(";",$stepsline);
$tab = "&nbsp;&nbsp;&nbsp;&nbsp;";
foreach ($snapshotlist as $snapshotitem) {
if ($snapshotitem == "") continue;
$snapshot = $snapshots[$snapshotitem] ;
$snapshotstate = _(ucfirst($snapshot["state"]));
$snapshotdesc = $snapshot["desc"];
$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')\"", addslashes($vm),addslashes($uuid),addslashes($template),$state,$snapshot["name"],$vmpreview);
echo "<tr><td><span id='vmsnap-$uuid' $snapmenu class='hand'>$tab|__&nbsp;&nbsp;<i class='fa fa-clone'></i></span>&nbsp;",$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 .="&nbsp;&nbsp;&nbsp;&nbsp;";
}
echo "</tbody>";
}
}
}
echo "</table>";
}
echo "\0".implode($kvm);
?>

View File

@@ -1,7 +1,7 @@
<?PHP
/* Copyright 2005-2020, Lime Technology
* Copyright 2015-2020, Derek Macias, Eric Schultz, Jon Panozzo.
* Copyright 2012-2020, Bergware International.
/* Copyright 2005-2023, Lime Technology
* Copyright 2012-2023, Bergware International.
* Copyright 2015-2021, Derek Macias, Eric Schultz, Jon Panozzo.
*
* 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,7 +12,7 @@
*/
?>
<?
$docroot = $docroot ?? $_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp';
$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';

View File

@@ -1,7 +1,7 @@
<?PHP
/* Copyright 2005-2023, Lime Technology
* Copyright 2015-2023, Derek Macias, Eric Schultz, Jon Panozzo.
* Copyright 2012-2023, Bergware International.
* Copyright 2015-2021, Derek Macias, Eric Schultz, Jon Panozzo.
*
* 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,13 +12,13 @@
*/
?>
<?
$docroot = $docroot ?? $_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp';
$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";
// add translations
$_SERVER['REQUEST_URI'] = 'vms';
require_once "$docroot/webGui/include/Translations.php";
require_once "$docroot/webGui/include/Helpers.php";
require_once "$docroot/plugins/dynamix.vm.manager/include/libvirt_helpers.php";
function requireLibvirt() {
global $lv;

View File

@@ -1,6 +1,7 @@
<?PHP
/* Copyright 2005-2023, Lime Technology
* Copyright 2015-2023, Derek Macias, Eric Schultz, Jon Panozzo.
* Copyright 2012-2023, Bergware International.
* Copyright 2015-2021, Derek Macias, Eric Schultz, Jon Panozzo.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2,
@@ -11,14 +12,15 @@
*/
?>
<?
$docroot = $docroot ?? $_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp';
$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";
// add translations
if (substr($_SERVER['REQUEST_URI'],0,4) != '/VMs') {
$_SERVER['REQUEST_URI'] = 'vms';
require_once "$docroot/webGui/include/Translations.php";
}
require_once "$docroot/webGui/include/Helpers.php";
require_once "$docroot/plugins/dynamix.vm.manager/include/libvirt_helpers.php";
switch ($display['theme']) {
case 'gray' : $bgcolor = '#121510'; $border = '#606e7f'; $top = -44; break;
@@ -88,55 +90,6 @@ if (isset($_GET['uuid'])) {
<link type="text/css" rel="stylesheet" href="<?autov('/webGui/styles/jquery.filetree.css')?>">
<link type="text/css" rel="stylesheet" href="<?autov('/webGui/styles/jquery.switchbutton.css')?>">
<style>
body{-webkit-overflow-scrolling:touch}
.fileTree{background:<?=$bgcolor?>;width:300px;max-height:150px;overflow-y:scroll;overflow-x:hidden;position:relative;z-index:100;display:none}
#vmform table{margin-top:0}
#vmform div.title + table{margin-top:0}
#vmform table tr{vertical-align:top;line-height:40px}
#vmform table tr td:nth-child(odd){width:300px;text-align:right;padding-right:10px}
#vmform table tr td:nth-child(even){width:110px}
#vmform table tr td:first-child{padding-right:30px}
#vmform table tr td:last-child{width:inherit}
#vmform .multiple{position:relative}
#vmform .sectionbutton{position:absolute;left:2px;cursor:pointer;opacity:0.4;font-size:1.4rem;line-height:17px;z-index:10;transition-property:opacity,left;transition-duration:0.1s;transition-timing-function:linear}
#vmform .sectionbutton.remove{top:0;opacity:0.3}
#vmform .sectionbutton.add{bottom:0}
#vmform .sectionbutton:hover{opacity:1.0}
#vmform .sectiontab{position:absolute;top:2px;bottom:2px;left:0;width:6px;border-radius:3px;background-color:#DDDDDD;transition-property:background,width;transition-duration:0.1s;transition-timing-function:linear}
#vmform .multiple:hover .sectionbutton{opacity:0.7;left:4px}
#vmform .multiple:hover .sectionbutton.remove{opacity:0.6}
#vmform .multiple:hover .sectiontab{background-color:#CCCCCC;width:8px}
#vmform table.multiple{margin:10px 0;background:<?=$bgcolor?>;background-size:800px 100%;background-position:-800px;background-repeat:no-repeat;background-clip:content-box;transition:background 0.3s linear}
#vmform table.multiple:hover{background-position:0 0;}
#vmform table.multiple td{padding:5px 0}
span.advancedview_panel{display:none;line-height:16px;margin-top:1px}
.basic{display:none}
.advanced{/*Empty placeholder*/}
.switch-button-label.off{color:inherit}
#template_img{cursor:pointer}
#template_img:hover{opacity:0.5}
#template_img:hover i{opacity:1.0}
.template_img_chooser_inner{display:inline-block;width:80px;margin-bottom:15px;margin-right:10px;text-align:center;}
.template_img_chooser_inner img{width:48px;height:48px}
.template_img_chooser_inner p{text-align:center;line-height:8px;}
#template_img_chooser{width:560px;height:300px;overflow-y:scroll;position:relative}
#template_img_chooser div:hover{background-color:#eee;cursor:pointer;}
#template_img_chooser_outer{position:absolute;display:none;border-radius:5px;border:1px solid <?=$border?>;background:<?=$bgcolor?>;z-index:10}
#form_content{display:none}
#vmform .four{overflow:hidden}
#vmform .four label{float:left;display:table-cell;width:15%;}
#vmform .four label:nth-child(4n+4){}
#vmform .four label.cpu1{width:28%;height:16px;line-height:16px}
#vmform .four label.cpu2{width:3%;height:16px;line-height:16px}
#vmform .mac_generate{cursor:pointer;margin-left:-5px;color:#08C;font-size:1.3rem;transform:translate(0px, 2px)}
#vmform .disk{display:none}
#vmform .disk_preview{display:inline-block;color:#BBB;transform:translate(0px, 1px)}
span#dropbox{border:1px solid <?=$border?>;background:<?=$bgcolor?>;padding:28px 12px;line-height:72px;margin-right:16px;}
i.fa-plus-circle,i.fa-minus-circle{margin-left:8px}
input[type=checkbox]{margin-left:0}
</style>
<span class="status advancedview_panel" style="margin-top:<?=$top?>px"><input type="checkbox" class="advancedview"></span>
<div class="domain">
<form id="vmform" method="POST">

View File

@@ -1,5 +1,5 @@
<?PHP
/* Copyright 2005-2021, Lime Technology
/* Copyright 2005-2023, Lime Technology
* Copyright 2015-2021, Derek Macias, Eric Schultz, Jon Panozzo.
*
* This program is free software; you can redistribute it and/or
@@ -281,6 +281,7 @@
$pciboot = $config['pciboot'];
$audios = $config['audio'];
$template = $config['template'];
$clocks = $config['clock'];
$type = $domain['type'];
$name = $domain['name'];
@@ -369,6 +370,7 @@
$cpumode = '';
$cpucache = '';
$cpufeatures = '';
$cpumigrate = '';
if (!empty($domain['cpumode']) && $domain['cpumode'] == 'host-passthrough') {
$cpumode .= "mode='host-passthrough'";
$cpucache = "<cache mode='passthrough'/>";
@@ -389,9 +391,11 @@
$intCores = $vcpus / $intCPUThreadsPerCore;
$intThreads = $intCPUThreadsPerCore;
}
if (!empty($domain['cpumigrate'])) $cpumigrate = " migratable='".$domain['cpumigrate']."'" ;
}
$cpustr = "<cpu $cpumode>
$cpustr = "<cpu $cpumode $cpumigrate>
<topology sockets='1' cores='{$intCores}' threads='{$intThreads}'/>
$cpucache
$cpufeatures
@@ -439,10 +443,14 @@
break;
}
/*
if ($os_type == "windows") $hypervclock = "<timer name='hypervclock' present='yes'/>" ; else $hypervclock = "" ;
$clock = "<clock offset='" . $domain['clock'] . "'>
<timer name='rtc' tickpolicy='catchup'/>
<timer name='pit' tickpolicy='delay'/>
<timer name='hpet' present='no'/>
$hypervclock
</clock>";
$hyperv = '';
@@ -459,6 +467,42 @@
<timer name='hpet' present='no'/>
</clock>";
}
*/
$clock = "<clock offset='" . $domain['clock'] . "'>" ;
foreach ($clocks as $clockname => $clockvalues) {
switch ($clockname){
case "rtc":
if ($clockvalues['present'] == "yes") $clock .= "<timer name='rtc' tickpolicy='{$clockvalues['tickpolicy']}'/>";
break ;
case "pit":
if ($clockvalues['present'] == "yes") $clock .= "<timer name='pit' tickpolicy='{$clockvalues['tickpolicy']}'/>";
break ;
case "hpet":
$clock .= "<timer name='hpet' present='{$clockvalues['present']}'/>" ;
break ;
case "hypervclock":
$clock .= "<timer name='hypervclock' present='{$clockvalues['present']}'/>" ;
break ;
}
}
$hyperv = "" ;
if ($domain['hyperv'] == 1 && $os_type == "windows") {
$hyperv = "<hyperv>
<relaxed state='on'/>
<vapic state='on'/>
<spinlocks state='on' retries='8191'/>
<vendor_id state='on' value='none'/>
";
if ($clocks['hypervclock']['present'] == "yes")
$hyperv .= "<vpindex state='on'/><synic state='on'/><stimer state='on'/>" ;
$hyperv .="</hyperv>";
#$clock = "<clock offset='" . $domain['clock'] . "'>
# <timer name='hypervclock' present='yes'/>
# <timer name='hpet' present='no'/>";
}
$clock .= "</clock>" ;
$usbstr = '';
if (!empty($usb)) {
@@ -732,6 +776,7 @@
$pcidevs='';
$gpudevs_used=[];
$multidevices = [] ; #Load?
$vmrc='';
$channelscopypaste = '';
if (!empty($gpus)) {
@@ -834,6 +879,15 @@
$strRomFile = "<rom file='".$gpu['rom']."'/>";
}
if ($gpu['multi'] == "on"){
$newgpu_bus = dechex(hexdec($gpu_bus) + 0x20) ;
if ($machine_type == "pc") $newgpu_slot = "0x01" ; else $newgpu_slot = "0x00" ;
$strSpecialAddress = "<address type='pci' domain='0x0000' bus='0x$newgpu_bus' slot='$newgpu_slot' function='0x".$gpu_function."' multifunction='on' />" ;
$multidevices[$gpu_bus] = "0x$gpu_bus" ;
}
$pcidevs .= "<hostdev mode='subsystem' type='pci' managed='yes'".$strXVGA.">
<driver name='vfio'/>
<source>
@@ -846,8 +900,8 @@
$gpudevs_used[] = $gpu['id'];
}
}
$audiodevs_used=[];
$strSpecialAddressAudio = "" ;
if (!empty($audios)) {
foreach ($audios as $i => $audio) {
// Skip duplicate audio devices
@@ -856,12 +910,20 @@
}
[$audio_bus, $audio_slot, $audio_function] = my_explode(":", str_replace('.', ':', $audio['id']), 3);
if ($audio_function != 0) {
if (isset($multidevices[$audio_bus])) {
$newaudio_bus = dechex(hexdec($audio_bus) + 0x20) ;
if ($machine_type == "pc") $newaudio_slot = "0x01" ; else $newaudio_slot = "0x00" ;
$strSpecialAddressAudio = "<address type='pci' domain='0x0000' bus='0x$newaudio_bus' slot='$newaudio_slot' function='0x".$audio_function."' />" ;
}
}
$pcidevs .= "<hostdev mode='subsystem' type='pci' managed='yes'>
<driver name='vfio'/>
<source>
<address domain='0x0000' bus='0x".$audio_bus."' slot='0x".$audio_slot."' function='0x".$audio_function."'/>
</source>
$strSpecialAddressAudio
</hostdev>";
$audiodevs_used[] = $audio['id'];
@@ -869,6 +931,7 @@
}
$pcidevs_used=[];
$strSpecialAddressOther = "" ;
if (!empty($pcis)) {
foreach ($pcis as $i => $pci_id) {
// Skip duplicate other pci devices
@@ -877,12 +940,22 @@
}
if ($vmclone) [$pci_bus, $pci_slot, $pci_function] = my_explode(":", str_replace('.', ':', $pci_id['id']), 3);
else [$pci_bus, $pci_slot, $pci_function] = my_explode(":", str_replace('.', ':', $pci_id), 3);
if ($pci_function != 0) {
if (isset($multidevices[$pci_bus])) {
$newpci_bus = dechex(hexdec($pci_bus) + 0x20) ;
if ($machine_type == "pc") $newpci_slot = "0x01" ; else $newpci_slot = "0x00" ;
$strSpecialAddressOther = "<address type='pci' domain='0x0000' bus='0x$newpci_bus' slot='$newpci_slot' function='0x".$pci_function."' />" ;
}
}
$pcidevs .= "<hostdev mode='subsystem' type='pci' managed='yes'>
<driver name='vfio'/>
<source>
<address domain='0x0000' bus='0x" . $pci_bus . "' slot='0x" . $pci_slot . "' function='0x" . $pci_function . "'/>
</source>" ;
</source>
$strSpecialAddressOther " ;
if (!empty($pciboot[$pci_id]) && !$vmclone) {
$pcidevs .= "<boot order='".$pciboot[$pci_id]."'/>" ;
}
@@ -952,6 +1025,12 @@
}
function appendqemucmdline($xml,$cmdline) {
$newxml = $xml ;
if ($cmdline != null) $newxml = str_replace("</domain>",$cmdline."\n</domain>",$xml) ;
return $newxml ;
}
function domain_new($config) {
// attempt to create all disk images if needed
@@ -975,6 +1054,8 @@
// generate xml for this domain
$strXML = $this->config_to_xml($config);
$qemucmdline = $config['qemucmdline'];
$strXML = $this->appendqemucmdline($strXML,$qemucmdline) ;
// Start the VM now if requested
@@ -1405,7 +1486,7 @@
}
//create a storage volume and add file extension
function volume_create($name, $capacity, $allocation, $format) {
/*function volume_create($name, $capacity, $allocation, $format) {
$capacity = $this->parse_size($capacity);
$allocation = $this->parse_size($allocation);
($format != 'raw' ) ? $ext = $format : $ext = 'img';
@@ -1422,7 +1503,7 @@
$tmp = libvirt_storagevolume_create_xml($pool, $xml);
return ($tmp) ? $tmp : $this->_set_last_error();
}
}*/
function get_hypervisor_name() {
$tmp = libvirt_connect_get_information($this->conn);
@@ -1666,7 +1747,7 @@
if (strpos($xml,'<qemu:commandline>')) {
$tmp = explode("\n", $xml);
for ($i = 0; $i < sizeof($tmp); $i++)
if (strpos('.'.$tmp[$i], "<domain type='kvm'"))
if (strpos('.'.$tmp[$i], "<domain type='kvm'") || strpos('.'.$tmp[$i], '<domain type="kvm"'))
$tmp[$i] = "<domain type='kvm' xmlns:qemu='http://libvirt.org/schemas/domain/qemu/1.0'>";
$xml = join("\n", $tmp);
}
@@ -2077,6 +2158,17 @@
return $var;
}
function domain_get_cpu_migrate($domain) {
$tmp = $this->get_xpath($domain, '//domain/cpu/@migratable', false);
if (!$tmp)
return 'no';
$var = $tmp[0];
unset($tmp);
return $var;
}
function domain_get_vcpu($domain) {
$tmp = $this->get_xpath($domain, '//domain/vcpu', false);
$var = $tmp[0];
@@ -2226,16 +2318,20 @@
$objNodes = $xpath->query('//domain/devices/hostdev[@type="pci"]');
if ($objNodes->length > 0) {
foreach ($objNodes as $objNode) {
$dom = $xpath->query('source/address/@domain', $objNode)->Item(0)->value;
$bus = $xpath->query('source/address/@bus', $objNode)->Item(0)->value;
$slot = $xpath->query('source/address/@slot', $objNode)->Item(0)->value;
$func = $xpath->query('source/address/@function', $objNode)->Item(0)->value;
$dom = $xpath->query('source/address/@domain', $objNode)->Item(0)->nodeValue;
$bus = $xpath->query('source/address/@bus', $objNode)->Item(0)->nodeValue;
$slot = $xpath->query('source/address/@slot', $objNode)->Item(0)->nodeValue;
$func = $xpath->query('source/address/@function', $objNode)->Item(0)->nodeValue;
$rom = $xpath->query('rom/@file', $objNode);
$rom = ($rom->length > 0 ? $rom->Item(0)->value : '');
$boot =$xpath->query('boot/@order', $objNode)->Item(0)->value;
$rom = ($rom->length > 0 ? $rom->Item(0)->nodeValue : '');
$boot =$xpath->query('boot/@order', $objNode)->Item(0)->nodeValue;
$devid = str_replace('0x', '', 'pci_'.$dom.'_'.$bus.'_'.$slot.'_'.$func);
$tmp2 = $this->get_node_device_information($devid);
$guest["multi"] = $xpath->query('address/@multifunction', $objNode)->Item(0)->nodeValue ? "on" : "off" ;
$guest["dom"] = $xpath->query('address/@domain', $objNode)->Item(0)->nodeValue;
$guest["bus"] = $xpath->query('address/@bus', $objNode)->Item(0)->nodeValue;
$guest["slot"] = $xpath->query('address/@slot', $objNode)->Item(0)->nodeValue;
$guest["func"] = $xpath->query('address/@function', $objNode)->Item(0)->nodeValue;
$devs[] = [
'domain' => $dom,
'bus' => $bus,
@@ -2247,7 +2343,8 @@
'product' => $tmp2['product_name'],
'product_id' => $tmp2['product_id'],
'boot' => $boot,
'rom' => $rom
'rom' => $rom,
'guest' => $guest
];
}
}
@@ -2602,7 +2699,7 @@
}
//change disk capacity
function disk_set_cap($disk, $cap) {
/*function disk_set_cap($disk, $cap) {
$xml = $this->domain_get_xml($domain);
$tmp = explode("\n", $xml);
for ($i = 0; $i < sizeof($tmp); $i++)
@@ -2612,7 +2709,7 @@
$xml = join("\n", $tmp);
return $this->domain_define($xml);
}
}*/
//change domain boot device
function domain_set_boot_device($domain, $bootdev) {

View File

@@ -1,7 +1,7 @@
<?PHP
/* Copyright 2005-2021, Lime Technology
/* Copyright 2005-2023, Lime Technology
* Copyright 2012-2023, Bergware International.
* Copyright 2015-2021, Derek Macias, Eric Schultz, Jon Panozzo.
* Copyright 2012-2021, 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,
@@ -42,7 +42,8 @@
* Usage:
* $xml = Array2XML::createXML('root_node_name', $php_array);
* echo $xml->saveXML();
*/
**/
class Array2XML {
private static $xml = null;
private static $encoding = 'UTF-8';
@@ -160,8 +161,7 @@ private static $encoding = 'UTF-8';
}
}
$docroot = $docroot ?? $_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp';
$docroot ??= ($_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp');
require_once "$docroot/plugins/dynamix.vm.manager/include/libvirt.php";
require_once "$docroot/webGui/include/Custom.php";
@@ -650,6 +650,64 @@ private static $encoding = 'UTF-8';
]
];}
$arrDefaultClocks = [
"windows" => [
"hpet" => [
"present" => "no",
"tickpolicy" => "delay"
],
"hypervclock" => [
"present" => "yes",
"tickpolicy" => "delay"
],
"pit" => [
"present" => "yes",
"tickpolicy" => "delay"
],
"rtc" => [
"present" => "yes",
"tickpolicy" => "catchup"
]
],
"hyperv" => [
"hpet" => [
"present" => "no",
"tickpolicy" => "delay"
],
"hypervclock" => [
"present" => "yes",
"tickpolicy" => "delay"
],
"pit" => [
"present" => "no",
"tickpolicy" => "delay"
],
"rtc" => [
"present" => "no",
"tickpolicy" => "catchup"
]
] ,
"other" => [
"hpet" => [
"present" => "no",
"tickpolicy" => "delay"
],
"hypervclock" => [
"present" => "no",
"tickpolicy" => "delay"
],
"pit" => [
"present" => "yes",
"tickpolicy" => "delay"
],
"rtc" => [
"present" => "yes",
"tickpolicy" => "catchup"
]
]
] ;
// Read configuration file (guaranteed to exist)
$domain_cfgfile = "/boot/config/domain.cfg";
$domain_cfg = parse_ini_file($domain_cfgfile);
@@ -756,13 +814,13 @@ private static $encoding = 'UTF-8';
$arrWhitelistGPUClassIDregex = '/^(0001|03)/';
$arrWhitelistAudioClassIDregex = '/^(0403)/';
# "System peripheral [0880]" "Global unichip corp. [1ac1]" "Coral Edge Tpu [089a]" -pff "Global unichip corp. [1ac1]" "Coral Edge Tpu [089a]"
# "System peripheral [0880]" "Global unichip corp. [1ac1]" "Coral Edge Tpu [089a]" -pff "Global unichip corp. [1ac1]" "Coral Edge Tpu [089a]"
# typeid productid
# file is csv typeid:productid
#
if (is_file("/boot/config/VMPCIOverride.cfg")) {
$arrWhiteListOverride = str_getcsv(file_get_contents("/boot/config/VMPCIOverride.cfg")) ;
}
}
$arrWhiteListOverride[] = "0880:089a" ;
$arrValidPCIDevices = [];
@@ -779,7 +837,7 @@ private static $encoding = 'UTF-8';
$boolBlacklisted = true;
}
$overrideCheck = "${arrMatch['typeid']}:${arrMatch['productid']}" ;
$overrideCheck = "{$arrMatch['typeid']}:{$arrMatch['productid']}" ;
if (in_array($overrideCheck,$arrWhiteListOverride) ) $boolBlacklisted = false;
$strClass = 'other';
@@ -1094,7 +1152,7 @@ private static $encoding = 'UTF-8';
$arrValidNetworks['bridges'] = array_values($arrBridges);
// This breaks VMSettings.page if libvirt is not running
if ($libvirt_running == "yes") {
/* if ($libvirt_running == "yes") {
$arrVirtual = $lv->libvirt_get_net_list($lv->get_connection());
if (($key = array_search('default', $arrVirtual)) !== false) {
@@ -1104,7 +1162,7 @@ private static $encoding = 'UTF-8';
array_unshift($arrVirtual, 'default');
$arrValidNetworks['libvirt'] = array_values($arrVirtual);
}
}*/
return $arrValidNetworks;
}
@@ -1166,25 +1224,26 @@ private static $encoding = 'UTF-8';
'wsport' => $lv->domain_get_ws_port($res),
'autoport' => $autoport,
'copypaste' => $getcopypaste,
'guest' => ['multi' => 'off' ],
];
}
foreach ($arrHostDevs as $arrHostDev) {
$arrFoundGPUDevices = array_filter($arrValidGPUDevices, function($arrDev) use ($arrHostDev) {return ($arrDev['id'] == $arrHostDev['id']);});
if (!empty($arrFoundGPUDevices)) {
$arrGPUDevices[] = ['id' => $arrHostDev['id'], 'rom' => $arrHostDev['rom']];
$arrGPUDevices[] = ['id' => $arrHostDev['id'], 'rom' => $arrHostDev['rom'], 'guest' => $arrHostDev['guest']];
continue;
}
$arrFoundAudioDevices = array_filter($arrValidAudioDevices, function($arrDev) use ($arrHostDev) {return ($arrDev['id'] == $arrHostDev['id']);});
if (!empty($arrFoundAudioDevices)) {
$arrAudioDevices[] = ['id' => $arrHostDev['id']];
$arrAudioDevices[] = ['id' => $arrHostDev['id'], 'guest' => $arrHostDev['guest']];
continue;
}
$arrFoundOtherDevices = array_filter($arrValidOtherDevices, function($arrDev) use ($arrHostDev) {return ($arrDev['id'] == $arrHostDev['id']);});
if (!empty($arrFoundOtherDevices)) {
$arrOtherDevices[] = ['id' => $arrHostDev['id'],'boot' => $arrHostDev['boot']];
$arrOtherDevices[] = ['id' => $arrHostDev['id'],'boot' => $arrHostDev['boot'], 'guest' => $arrHostDev['guest']];
continue;
}
}
@@ -1275,6 +1334,7 @@ private static $encoding = 'UTF-8';
'maxmem' => $lv->domain_get_memory($res),
'password' => '', //TODO?
'cpumode' => $lv->domain_get_cpu_type($res),
'cpumigrate' => $lv->domain_get_cpu_migrate($res),
'vcpus' => $dom['nrVirtCpu'],
'vcpu' => $lv->domain_get_vcpu_pins($res),
'hyperv' => ($lv->domain_get_feature($res, 'hyperv') ? 1 : 0),
@@ -1298,7 +1358,9 @@ private static $encoding = 'UTF-8';
'pci' => $arrOtherDevices,
'nic' => $arrNICs,
'usb' => $arrUSBDevs,
'shares' => $lv->domain_get_mount_filesystems($res)
'shares' => $lv->domain_get_mount_filesystems($res),
'qemucmdline' => getQEMUCmdLine($strDOMXML),
'clocks' => getClocks($strDOMXML)
];
}
@@ -1347,7 +1409,7 @@ private static $encoding = 'UTF-8';
foreach ($old['devices']['disk'] as $k => $d) if ($source==$d['source']['@attributes']['file']) $new['devices']['disk'][$key]['driver']['@attributes'] = $d['driver']['@attributes'];
}
// settings not in the GUI, but maybe customized
unset($new['clock']);
unset($old['clock']);
// preserve vnc/spice port settings
// unset($new['devices']['graphics']['@attributes']['port'],$new['devices']['graphics']['@attributes']['autoport']);
if (!$new['devices']['graphics']) unset($old['devices']['graphics']);
@@ -1446,6 +1508,49 @@ private static $encoding = 'UTF-8';
return json_encode($memorybacking); ;
}
function getClocks($xml) {
$clocks = new SimpleXMLElement($xml);
$clocks = json_decode(json_encode($clocks->clock),true) ;
$arrClocks = [
"hpet" => [
"present" => "no",
"tickpolicy" => "delay"
],
"hypervclock" => [
"present" => "no",
"tickpolicy" => "delay"
],
"pit" => [
"present" => "no",
"tickpolicy" => "delay"
],
"rtc" => [
"present" => "no",
"tickpolicy" => "delay"
]
] ;
foreach ($clocks['timer'] as $timer) {
$name = $timer["@attributes"]["name"] ;
$tickpolicy = $timer["@attributes"]["tickpolicy"] ;
$present = $timer["@attributes"]["present"] ;
if (isset($present)) $arrClocks[$name]['present'] = $present ;
if (isset($tickpolicy)) { $arrClocks[$name]['tickpolicy'] = $tickpolicy ; $arrClocks[$name]['present'] = 'yes' ; }
}
return json_encode($arrClocks) ;
}
function getQEMUCmdLine($xml) {
$x = strpos($xml,"<qemu:commandline>", 0) ;
if ($x === false) return null ;
$y = strpos($xml,"</qemu:commandline>", 0) ;
$z=$y ;
while ($y!=false) {
$y = strpos($xml,"<qemu:commandline>", $z +19) ;
if ($y != false) $z =$y ;
}
return substr($xml,$x, ($z + 19) -$x) ;
}
function getchannels($res) {
global $lv ;
$xml = $lv->domain_get_xml($res) ;
@@ -1497,7 +1602,7 @@ private static $encoding = 'UTF-8';
*/
$uuid = $lv->domain_get_uuid($clone) ;
write("addLog\0".htmlspecialchars(_("Checking if clone exists")));
if ($uuid) { $arrResponse = ['error' => _("Clone VM name already inuse")]; return false ;}
if ($uuid) { $arrResponse = ['error' => _("Clone VM name already inuse")]; return false ;}
#VM must be shutdown.
$res = $lv->get_domain_by_name($vm);
$dom = $lv->domain_get_info($res);
@@ -1515,22 +1620,20 @@ private static $encoding = 'UTF-8';
foreach($disks as $disk) {
$file = $disk["file"] ;
$pathinfo = pathinfo($file) ;
$filenew = $pathinfo["dirname"].'/'.$pathinfo["filename"].'.'.$name.'qcow2' ;
$capacity = $capacity + $disk["capacity"] ;
}
$dirpath = $pathinfo["dirname"] ;
#Check free space.
write("addLog\0".htmlspecialchars("Checking for free space"));
$dirfree = disk_free_space($pathinfo["dirname"]) ;
$sourcedir = trim(shell_exec("getfattr --absolute-names --only-values -n system.LOCATION ".escapeshellarg($pathinfo["dirname"])." 2>/dev/null"));
$sourcedir = trim(shell_exec("getfattr --absolute-names --only-values -n system.LOCATION ".escapeshellarg($pathinfo["dirname"])." 2>/dev/null"));
$repdir = str_replace('/mnt/user/', "/mnt/$sourcedir/", $pathinfo["dirname"]);
$repdirfree = disk_free_space($repdir) ;
$reflink = true ;
$capacity *= 1 ;
if ($free == "yes" && $repdirfree < $capacity) { $reflink = false ;}
if ($free == "yes" && $dirfree < $capacity) { write("addLog\0".htmlspecialchars(_("Insufficent storage for clone"))); return false ;}
if ($free == "yes" && $dirfree < $capacity) { write("addLog\0".htmlspecialchars(_("Insufficent storage for clone"))); return false ;}
#Clone XML
$uuid = $lv->domain_get_uuid($vm) ;
@@ -1568,22 +1671,21 @@ private static $encoding = 'UTF-8';
chgrp($clonedir, 'users');
}
write("addLog\0".htmlspecialchars("Checking for image files"));
if ($file_exists && $overwrite != "yes") { write("addLog\0".htmlspecialchars(_("New image file names exist and Overwrite is not allowed"))); return( false) ; }
if ($file_exists && $overwrite != "yes") { write("addLog\0".htmlspecialchars(_("New image file names exist and Overwrite is not allowed"))); return( false) ; }
#Create duplicate files.
foreach($file_clone as $diskid => $disk) {
$target = $disk['target'] ;
$source = $disk['source'] ;
if ($target == $source) { write("addLog\0".htmlspecialchars(_("New image file is same as old"))); return( false) ; }
$sourcerealdisk = trim(shell_exec("getfattr --absolute-names --only-values -n system.LOCATION ".escapeshellarg($source)." 2>/dev/null"));
$source = $disk['source'] ;
if ($target == $source) { write("addLog\0".htmlspecialchars(_("New image file is same as old"))); return( false) ; }
$sourcerealdisk = trim(shell_exec("getfattr --absolute-names --only-values -n system.LOCATION ".escapeshellarg($source)." 2>/dev/null"));
$reptgt = str_replace('/mnt/user/', "/mnt/$sourcerealdisk/", $target);
$repsrc = str_replace('/mnt/user/', "/mnt/$sourcerealdisk/", $source);
#var_dump($repsrc,$reptgt) ;
$cmdstr = "cp --reflink=always '$repsrc' '$reptgt'" ;
if ($reflink == true) { $refcmd = $cmdstr ; } else {$refcmd = false; }
$cmdstr = "rsync -ahPIXS --out-format=%f --info=flist0,misc0,stats0,name1,progress2 '$source' '$target'" ;
$error = execCommand_nchan($cmdstr,$path,$refcmd) ;
$error = execCommand_nchan_clone($cmdstr,$target,$refcmd) ;
if (!$error) { write("addLog\0".htmlspecialchars("Image copied failed.")); return( false) ; }
}
@@ -1594,23 +1696,23 @@ private static $encoding = 'UTF-8';
file_put_contents("/tmp/clonexml" ,$xml) ;
$rtn = $lv->domain_define($xml) ;
return($rtn) ;
}
function compare_creationtime($a, $b) {
return strnatcmp($a['creationtime'], $b['creationtime']);
}
}
function compare_creationtimelt($a, $b) {
return $a['creationtime'] < $b['creationtime'];
}
}
function getvmsnapshots($vm) {
$snaps=array() ;
$dbpath = "/etc/libvirt/qemu/snapshot/$vm" ;
$snaps_json = file_get_contents($dbpath."/snapshots.db") ;
$snaps = json_decode($snaps_json,true) ;
$snaps = json_decode($snaps_json,true) ;
if (is_array($snaps)) uasort($snaps,'compare_creationtime') ;
return $snaps ;
}
@@ -1620,7 +1722,7 @@ private static $encoding = 'UTF-8';
$dbpath = "/etc/libvirt/qemu/snapshot/$vm" ;
if (!is_dir($dbpath)) mkdir($dbpath) ;
$snaps_json = file_get_contents($dbpath."/snapshots.db") ;
$snaps = json_decode($snaps_json,true) ;
$snaps = json_decode($snaps_json,true) ;
$snapshot_res=$lv->domain_snapshot_lookup_by_name($vm,$name) ;
$snapshot_xml=$lv->domain_snapshot_get_xml($snapshot_res) ;
$a = simplexml_load_string($snapshot_xml) ;
@@ -1637,14 +1739,14 @@ private static $encoding = 'UTF-8';
$disks =$lv->get_disk_stats($vm) ;
foreach($disks as $disk) {
$file = $disk["file"] ;
$output = "" ;
$output = array() ;
exec("qemu-img info --backing-chain -U '$file' | grep image:",$output) ;
foreach($output as $key => $line) {
$line=str_replace("image: ","",$line) ;
$output[$key] = $line ;
$output[$key] = $line ;
}
$snaps[$vmsnap]['backing'][$disk["device"]] = $output ;
$snaps[$vmsnap]['backing'][$disk["device"]] = $output ;
$rev = "r".$disk["device"] ;
$reversed = array_reverse($output) ;
$snaps[$vmsnap]['backing'][$rev] = $reversed ;
@@ -1657,7 +1759,7 @@ private static $encoding = 'UTF-8';
if (array_key_exists(0 , $b["disks"]["disk"])) $snaps[$vmsnap]["disks"]= $b["disks"]["disk"]; else $snaps[$vmsnap]["disks"][0]= $b["disks"]["disk"];
$value = json_encode($snaps,JSON_PRETTY_PRINT) ;
file_put_contents($dbpath."/snapshots.db",$value) ;
}
@@ -1667,20 +1769,20 @@ private static $encoding = 'UTF-8';
$dbpath = "/etc/libvirt/qemu/snapshot/$vm" ;
if (!is_dir($dbpath)) mkdir($dbpath) ;
$snaps_json = file_get_contents($dbpath."/snapshots.db") ;
$snaps = json_decode($snaps_json,true) ;
$snaps = json_decode($snaps_json,true) ;
foreach($snaps as $vmsnap=>$snap)
$disks =$lv->get_disk_stats($vm) ;
foreach($disks as $disk) {
$file = $disk["file"] ;
$output = "" ;
$output = array() ;
exec("qemu-img info --backing-chain -U '$file' | grep image:",$output) ;
foreach($output as $key => $line) {
$line=str_replace("image: ","",$line) ;
$output[$key] = $line ;
$output[$key] = $line ;
}
$snaps[$vmsnap]['backing'][$disk["device"]] = $output ;
$snaps[$vmsnap]['backing'][$disk["device"]] = $output ;
$rev = "r".$disk["device"] ;
$reversed = array_reverse($output) ;
$snaps[$vmsnap]['backing'][$rev] = $reversed ;
@@ -1690,21 +1792,21 @@ private static $encoding = 'UTF-8';
$snaps[$vmsnap]["parent"]= $parendfileinfo["extension"];
$snaps[$vmsnap]["parent"] = str_replace("qcow2",'',$snaps[$vmsnap]["parent"]) ;
if (isset($parentfind[1]) && !isset($parentfind[2])) $snaps[$vmsnap]["parent"]="Base" ;
$value = json_encode($snaps,JSON_PRETTY_PRINT) ;
$res = $lv->get_domain_by_name($vm);
if (!empty($lv->domain_get_ovmf($res))) $nvram = $lv->nvram_create_snapshot($lv->domain_get_uuid($vm),$name) ;
#if (!empty($lv->domain_get_ovmf($res))) $nvram = $lv->nvram_create_snapshot($lv->domain_get_uuid($vm),$name) ;
#Remove any NVRAMs that are no longer valid.
# Get uuid
$vmuuid = $lv->domain_get_uuid($vm) ;
#Get list of files
#$filepath = "/etc/libvirt/qemu/nvram/'.$uuid*" ; #$snapshotname"
$filepath = "/etc/libvirt/qemu/nvram/$vmuuid*" ; #$snapshotname"
#Get list of files
#$filepath = "/etc/libvirt/qemu/nvram/'.$uuid*" ; #$snapshotname"
$filepath = "/etc/libvirt/qemu/nvram/$vmuuid*" ; #$snapshotname"
$nvram_files=glob($filepath) ;
foreach($nvram_files as $key => $nvram_file) {
if ($nvram_file == "/etc/libvirt/qemu/nvram/$vmuuid"."_VARS-pure-efi.fd" || $nvram_file == "/etc/libvirt/qemu/nvram/$vmuuid"."_VARS-pure-efi-tpm.fd" ) unset($nvram_files[$key]) ;
if ($nvram_file == "/etc/libvirt/qemu/nvram/$vmuuid"."_VARS-pure-efi.fd" || $nvram_file == "/etc/libvirt/qemu/nvram/$vmuuid"."_VARS-pure-efi-tpm.fd" ) unset($nvram_files[$key]) ;
foreach ($snaps as $snapshotname => $snap) {
$tpmfilename = "/etc/libvirt/qemu/nvram/".$vmuuid.$snapshotname."_VARS-pure-efi-tpm.fd" ;
$nontpmfilename = "/etc/libvirt/qemu/nvram/".$vmuuid.$snapshotname."_VARS-pure-efi.fd" ;
@@ -1714,7 +1816,7 @@ private static $encoding = 'UTF-8';
}
foreach ($nvram_files as $nvram_file) unlink($nvram_file) ;
file_put_contents($dbpath."/snapshots.db",$value) ;
}
@@ -1722,7 +1824,7 @@ private static $encoding = 'UTF-8';
global $lv ;
$dbpath = "/etc/libvirt/qemu/snapshot/$vm" ;
$snaps_json = file_get_contents($dbpath."/snapshots.db") ;
$snaps = json_decode($snaps_json,true) ;
$snaps = json_decode($snaps_json,true) ;
unset($snaps[$name]) ;
$value = json_encode($snaps,JSON_PRETTY_PRINT) ;
file_put_contents($dbpath."/snapshots.db",$value) ;
@@ -1732,19 +1834,19 @@ private static $encoding = 'UTF-8';
function vm_snapshot($vm,$snapshotname, $snapshotdesc, $free = "yes", $memorysnap = "yes") {
global $lv ;
#Get State
$res = $lv->get_domain_by_name($vm);
$dom = $lv->domain_get_info($res);
$state = $lv->domain_state_translate($dom['state']);
#Get disks for --diskspec
#Get disks for --diskspec
$disks =$lv->get_disk_stats($vm) ;
$diskspec = "" ;
$capacity = 0 ;
if ($snapshotname == "--generate") $name= "S" . date("YmdHis") ; else $name=$snapshotname ;
if ($snapshotdesc != "") $snapshotdesc = " --description '$snapshotdesc'" ;
foreach($disks as $disk) {
$file = $disk["file"] ;
$pathinfo = pathinfo($file) ;
@@ -1756,38 +1858,38 @@ private static $encoding = 'UTF-8';
#get memory
$mem = $lv->domain_get_memory_stats($vm) ;
$memory = $mem[6] ;
if ($memorysnap = "yes") $memspec = ' --memspec "'.$pathinfo["dirname"].'/memory'.$name.'.mem",snapshot=external' ; else $memspec = "" ;
$cmdstr = "virsh snapshot-create-as '$vm' --name '$name' $snapshotdesc --atomic" ;
if ($state == "running") {
$cmdstr .= " --live ".$memspec.$diskspec ;
$capacity = $capacity + $memory ;
} else {
$cmdstr .= " --disk-only ".$diskspec ;
$cmdstr .= " --disk-only ".$diskspec ;
}
#Check free space.
$dirfree = disk_free_space($pathinfo["dirname"]) ;
$capacity *= 1 ;
if ($free == "yes" && $dirfree < $capacity) { $arrResponse = ['error' => _("Insufficent Storage for Snapshot")]; return $arrResponse ;}
if ($free == "yes" && $dirfree < $capacity) { $arrResponse = ['error' => _("Insufficent Storage for Snapshot")]; return $arrResponse ;}
#Copy nvram
if (!empty($lv->domain_get_ovmf($res))) $nvram = $lv->nvram_create_snapshot($lv->domain_get_uuid($vm),$name) ;
$xmlfile = $pathinfo["dirname"]."/".$name.".running" ;
file_put_contents("/tmp/xmltst", "$xmlfile" ) ;
if ($state == "running") exec("virsh dumpxml '$vm' > ".escapeshellarg($xmlfile),$outxml,$rtnxml) ;
$output= [] ;
$test = false ;
if ($test) exec($cmdstr." --print-xml 2>&1",$output,$return) ; else exec($cmdstr." 2>&1",$output,$return) ;
if (strpos(" ".$output[0],"error") ) {
if (strpos(" ".$output[0],"error") ) {
$arrResponse = ['error' => substr($output[0],6) ] ;
} else {
$arrResponse = ['success' => true] ;
@@ -1805,8 +1907,8 @@ private static $encoding = 'UTF-8';
$disks =$lv->get_disk_stats($vm) ;
switch ($snapslist[$snap]['state']) {
case "shutoff":
case "running":
case "shutoff":
case "running":
#VM must be shutdown.
$res = $lv->get_domain_by_name($vm);
$dom = $lv->domain_get_info($res);
@@ -1819,7 +1921,7 @@ private static $encoding = 'UTF-8';
$xmlobj = custom::createArray('domain',$strXML) ;
# Process disks and update path.
$disks=($snapslist[$snap]['disks']) ;
$disks=($snapslist[$snap]['disks']) ;
foreach ($disks as $disk) {
$diskname = $disk["@attributes"]["name"] ;
if ($diskname == "hda" || $diskname == "hdb") continue ;
@@ -1861,7 +1963,7 @@ private static $encoding = 'UTF-8';
$item++ ;
}
}
uasort($snapslist,'compare_creationtimelt') ;
foreach($snapslist as $s) {
$name = $s['name'] ;
@@ -1879,13 +1981,13 @@ private static $encoding = 'UTF-8';
# Restore Memory.
$makerun = true ;
if ($makerun == true) exec("virsh restore ".escapeshellarg($memoryfile)) ;
#exec("virsh restore $memoryfile") ;
}
if ($makerun == true) exec("virsh restore ".escapeshellarg($memoryfile)) ;
#exec("virsh restore $memoryfile") ;
}
#Delete Metadata only.
if ($actionmeta == "yes") {
if ($actionmeta == "yes") {
$ret = delete_snapshots_database("$vm","$name") ;
}
}
if (is_file($memoryfile) && $action == "yes") unlink($memoryfile) ;
if (is_file($xmlfile) && $action == "yes") unlink($xmlfile) ;
if ($s['name'] == $snap) break ;
@@ -1893,11 +1995,11 @@ private static $encoding = 'UTF-8';
#if VM was started restart.
if ($state == 'running' && $snapslist[$snap]['state'] != "running") {
$arrResponse = $lv->domain_start($vm) ;
}
}
if (!empty($lv->domain_get_ovmf($res))) $nvram = $lv->nvram_revert_snapshot($lv->domain_get_uuid($vm),$name) ;
break ;
}
$arrResponse = ['success' => true] ;
return($arrResponse) ;
@@ -1907,28 +2009,29 @@ private static $encoding = 'UTF-8';
global $lv ;
$snapslist= getvmsnapshots($vm) ;
$data = "<br><br>Images and metadata to remove if tickbox checked.<br>" ;
$capacity = 0 ;
$diskspec = "" ;
$disks =$lv->get_disk_stats($vm) ;
foreach($disks as $disk) {
$file = $disk["file"] ;
$output = "" ;
$output = array() ;
exec("qemu-img info --backing-chain -U '$file' | grep image:",$output) ;
foreach($output as $key => $line) {
$line=str_replace("image: ","",$line) ;
$output[$key] = $line ;
$output[$key] = $line ;
}
$snaps[$vm][$disk["device"]] = $output ;
$snaps[$vm][$disk["device"]] = $output ;
$rev = "r".$disk["device"] ;
$reversed = array_reverse($output) ;
$snaps[$vm][$rev] = $reversed ;
$pathinfo = pathinfo($file) ;
$filenew = $pathinfo["dirname"].'/'.$pathinfo["filename"].'.'.$name.'qcow2' ;
$diskspec .= " --diskspec ".$disk["device"].",snapshot=external,file=".$filenew ;
#$filenew = $pathinfo["dirname"].'/'.$pathinfo["filename"].'.'.$name.'qcow2' ;
#$diskspec .= " --diskspec ".$disk["device"].",snapshot=external,file=".$filenew ;
$capacity = $capacity + $disk["capacity"] ;
}
$snapdisks= $snapslist[$snap]['disks'] ;
foreach ($snapdisks as $diskkey => $snapdisk) {
$diskname = $snapdisk["@attributes"]["name"] ;
if ($diskname == "hda" || $diskname == "hdb") continue ;
@@ -1941,7 +2044,7 @@ private static $encoding = 'UTF-8';
{
if (!isset($snaps[$vm]["r".$diskname][$item])) break ;
$newpath = $snaps[$vm]["r".$diskname][$item] ;
if (is_file($path)) $data .= "$newpath<br>" ;
if (is_file($path)) $data .= "$newpath<br>" ;
$item++ ;
}
@@ -1959,7 +2062,7 @@ private static $encoding = 'UTF-8';
}
return($data) ;
}
function vm_snapremove($vm, $snap) {
global $lv ;
@@ -1970,14 +2073,14 @@ private static $encoding = 'UTF-8';
$disks =$lv->get_disk_stats($vm) ;
foreach($disks as $disk) {
$file = $disk["file"] ;
$output = "" ;
$output = array() ;
exec("qemu-img info --backing-chain -U $file | grep image:",$output) ;
foreach($output as $key => $line) {
$line=str_replace("image: ","",$line) ;
$output[$key] = $line ;
$output[$key] = $line ;
}
$snaps[$vm][$disk["device"]] = $output ;
$snaps[$vm][$disk["device"]] = $output ;
$rev = "r".$disk["device"] ;
$reversed = array_reverse($output) ;
$snaps[$vm][$rev] = $reversed ;
@@ -1989,7 +2092,7 @@ private static $encoding = 'UTF-8';
$xmlobj = custom::createArray('domain',$strXML) ;
# Process disks.
$disks=($snapslist[$snap]['disks']) ;
$disks=($snapslist[$snap]['disks']) ;
foreach ($disks as $disk) {
$diskname = $disk["@attributes"]["name"] ;
if ($diskname == "hda" || $diskname == "hdb") continue ;
@@ -2000,30 +2103,30 @@ private static $encoding = 'UTF-8';
return ($data) ;
}
}
$disks=($snapslist[$snap]['disks']) ;
foreach ($disks as $disk) {
$diskname = $disk["@attributes"]["name"] ;
if ($diskname == "hda" || $diskname == "hdb") continue ;
$path = $disk["source"]["@attributes"]["file"] ;
if (is_file($path)) {
if(!unlink("$path")) {
if(!unlink("$path")) {
$data = ["error" => "Unable to remove image file $path"] ;
return ($data) ;
}
}
}
}
# Delete NVRAM
# Delete NVRAM
if (!empty($lv->domain_get_ovmf($res))) $nvram = $lv->nvram_delete_snapshot($lv->domain_get_uuid($vm),$snap) ;
$ret = delete_snapshots_database("$vm","$snap") ;
if(!$ret)
$data = ["error" => "Unable to remove snap metadata $snap"] ;
else
$data = ["success => 'true"] ;
return($data) ;
}
@@ -2060,7 +2163,7 @@ OPTIONS
blockcommit Debian --path /mnt/user/domains/Debian/vdisk1.S20230513120410qcow2 --verbose --pivot --delete
*/
# Error if VM Not running.
$snapslist= getvmsnapshots($vm) ;
$disks =$lv->get_disk_stats($vm) ;
@@ -2070,7 +2173,7 @@ OPTIONS
if ($pivot == "yes") $cmdstr .= " --pivot " ;
if ($action == "yes") $cmdstr .= " --delete " ;
# Process disks and update path.
$snapdisks=($snapslist[$snap]['disks']) ;
$snapdisks=($snapslist[$snap]['disks']) ;
if ($base != "--base" && $base != "") {
#get file name from snapshot.
$snapdisks=($snapslist[$base]['disks']) ;
@@ -2095,15 +2198,15 @@ OPTIONS
}
$error = execCommand_nchan($cmdstr,$path) ;
if (!$error) {
$arrResponse = ['error' => substr($output[0],6) ] ;
if (!$error) {
$arrResponse = ['error' => "Process Failed"] ;
return($arrResponse) ;
} else {
$arrResponse = ['success' => true] ;
}
}
# Delete NVRAM
# Delete NVRAM
#if (!empty($lv->domain_get_ovmf($res))) $nvram = $lv->nvram_delete_snapshot($lv->domain_get_uuid($vm),$snap) ;
refresh_snapshots_database($vm) ;
@@ -2146,13 +2249,13 @@ OPTIONS
$disks =$lv->get_disk_stats($vm) ;
foreach($disks as $disk) {
$file = $disk["file"] ;
$output = "" ;
$output = array() ;
exec("qemu-img info --backing-chain -U '$file' | grep image:",$output) ;
foreach($output as $key => $line) {
$line=str_replace("image: ","",$line) ;
$output[$key] = $line ;
$output[$key] = $line ;
}
$snaps[$vm][$disk["device"]] = $output ;
$snaps[$vm][$disk["device"]] = $output ;
$rev = "r".$disk["device"] ;
$reversed = array_reverse($output) ;
$snaps[$vm][$rev] = $reversed ;
@@ -2167,7 +2270,7 @@ OPTIONS
$cmdstr = "virsh blockpull '$vm' --path '$path' --verbose --pivot --delete" ;
$cmdstr = "virsh blockpull '$vm' --path '$path' --verbose --wait " ;
# Process disks and update path.
$snapdisks=($snapslist[$snap]['disks']) ;
$snapdisks=($snapslist[$snap]['disks']) ;
if ($base != "--base" && $base != "") {
#get file name from snapshot.
$snapdisks=($snapslist[$base]['disks']) ;
@@ -2184,9 +2287,9 @@ OPTIONS
$error = execCommand_nchan($cmdstr,$path) ;
if (!$error) {
$arrResponse = ['error' => substr($output[0],6) ] ;
if (!$error) {
$arrResponse = ['error' => "Process Failed" ] ;
return($arrResponse) ;
} else {
# Remove nvram snapshot
@@ -2196,6 +2299,7 @@ OPTIONS
}
refresh_snapshots_database($vm) ;
$ret = $ret = delete_snapshots_database("$vm","$snap") ;
if($ret)
$data = ["error" => "Unable to remove snap metadata $snap"] ;
else
@@ -2241,6 +2345,6 @@ OPTIONS
*/
}
?>

View File

@@ -69,14 +69,14 @@ function addVMContext(name, uuid, template, state, vmrcurl, vmrcprotocol, log, c
if (x!=-1) path = path.substring(0,x);
if (vmrcurl !== "" && state == "running") {
if (console == "web" || console == "both") {
var vmrctext=_("VM Console") + "(" + vmrcprotocol + ")" ;
var vmrctext=_("VM Console") + " (" + vmrcprotocol + ")" ;
opts.push({text:vmrctext, icon:"fa-desktop", action:function(e) {
e.preventDefault();
window.open(vmrcurl, '_blank', 'scrollbars=yes,resizable=yes');
}});
}
if (console == "remote" || console == "both") {
opts.push({text:_("VM remote-viewer")+ "(" + vmrcprotocol + ")" , icon:"fa-desktop", action:function(e) {
opts.push({text:_("VM remote-viewer")+ " (" + vmrcprotocol + ")" , icon:"fa-desktop", action:function(e) {
e.preventDefault();
ajaxVMDispatchconsoleRV({action:"domain-consoleRV", uuid:uuid, vmrcurl:vmrcurl}, "loadlist") ;
}});
@@ -137,12 +137,12 @@ function addVMContext(name, uuid, template, state, vmrcurl, vmrcprotocol, log, c
}});
if (vmrcprotocol == "VNC" || vmrcprotocol == "SPICE") {
if (console == "web" || console == "both") {
opts.push({text:_("Start with console")+ "(" + vmrcprotocol + ")" , icon:"fa-play", action:function(e) {
opts.push({text:_("Start with console")+ " (" + vmrcprotocol + ")" , icon:"fa-play", action:function(e) {
e.preventDefault();
ajaxVMDispatchconsole({action:"domain-start-console", uuid:uuid, vmrcurl:vmrcurl}, "loadlist") ;
}});}
if (console == "remote" || console == "both") {
opts.push({text:_("Start with remote-viewer")+ "(" + vmrcprotocol + ")" , icon:"fa-play", action:function(e) {
opts.push({text:_("Start with remote-viewer")+ " (" + vmrcprotocol + ")" , icon:"fa-play", action:function(e) {
e.preventDefault();
ajaxVMDispatchconsoleRV({action:"domain-start-consoleRV", uuid:uuid, vmrcurl:vmrcurl}, "loadlist") ;
}});

View File

@@ -1,6 +1,7 @@
#!/usr/bin/php -q
<?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,
@@ -11,47 +12,47 @@
*/
?>
<?
$docroot = $docroot ?? $_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp';
$docroot ??= ($_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp');
require_once "$docroot/webGui/include/Wrappers.php";
require_once "$docroot/plugins/dynamix.vm.manager/include/libvirt_helpers.php";
require_once "$docroot/plugins/dynamix.docker.manager/include/DockerClient.php";
// add translations
$_SERVER['REQUEST_URI'] = '';
$login_locale = _var($display,'locale');
require_once "$docroot/plugins/dynamix.docker.manager/include/DockerClient.php";
require_once "$docroot/webGui/include/Translations.php";
require_once "$docroot/plugins/dynamix.vm.manager/include/libvirt_helpers.php";
function write(...$messages){
$com = curl_init();
curl_setopt_array($com,[
CURLOPT_URL => 'http://localhost/pub/vmaction?buffer_length=1',
CURLOPT_UNIX_SOCKET_PATH => '/var/run/nginx.socket',
CURLOPT_POST => 1,
CURLOPT_RETURNTRANSFER => true
]);
foreach ($messages as $message) {
curl_setopt($com, CURLOPT_POSTFIELDS, $message);
curl_exec($com);
}
curl_close($com);
$com = curl_init();
curl_setopt_array($com,[
CURLOPT_URL => 'http://localhost/pub/vmaction?buffer_length=1',
CURLOPT_UNIX_SOCKET_PATH => '/var/run/nginx.socket',
CURLOPT_POST => 1,
CURLOPT_RETURNTRANSFER => true
]);
foreach ($messages as $message) {
curl_setopt($com, CURLOPT_POSTFIELDS, $message);
curl_exec($com);
}
curl_close($com);
}
function execCommand_nchan($command,$idx) {
$waitID = mt_rand();
[$cmd,$args] = explode(' ',$command,2);
write("<p class='logLine'></p>","addLog\0<fieldset class='docker'><legend>"._('Command execution')."</legend>".basename($cmd).' '.str_replace(" -","<br>&nbsp;&nbsp;-",htmlspecialchars($args))."<br><span id='wait-$waitID'>"._('Please wait')." </span><p class='logLine'></p></fieldset>","show_Wait\0$waitID");
write("addLog\0<br>") ;
write("addToID\0$idx\0 $action") ;
$proc = popen("$command 2>&1",'r');
while ($out = fgets($proc)) {
$out = preg_replace("%[\t\n\x0B\f\r]+%", '',$out);
if (substr($out,0,1) == "B") { ;
write("progress\0$idx\0".htmlspecialchars(substr($out,strrpos($out,"Block Pull")))) ;
} else echo write("addToID\0$idx\0 ".htmlspecialchars($out));
}
$retval = pclose($proc);
$out = $retval ? _('The command failed').'.' : _('The command finished successfully').'!';
write("stop_Wait\0$waitID","addLog\0<br><b>$out</b>");
return $retval===0;
$waitID = mt_rand();
[$cmd,$args] = explode(' ',$command,2);
write("<p class='logLine'></p>","addLog\0<fieldset class='docker'><legend>"._('Command execution')."</legend>".basename($cmd).' '.str_replace(" -","<br>&nbsp;&nbsp;-",htmlspecialchars($args))."<br><span id='wait-$waitID'>"._('Please wait')." </span><p class='logLine'></p></fieldset>","show_Wait\0$waitID");
write("addLog\0<br>") ;
#write("addToID\0$idx\0 $action") ;
$proc = popen("$command 2>&1",'r');
while ($out = fgets($proc)) {
$out = preg_replace("%[\t\n\x0B\f\r]+%", '',$out);
if (substr($out,0,1) == "B") { ;
write("progress\0$idx\0".htmlspecialchars(substr($out,strrpos($out,"Block Pull")))) ;
} else echo write("addToID\0$idx\0 ".htmlspecialchars($out));
}
$retval = pclose($proc);
$out = $retval ? _('The command failed').'.' : _('The command finished successfully').'!';
write("stop_Wait\0$waitID","addLog\0<br><b>$out</b>");
return $retval===0;
}
#{action:"snap-", uuid:uuid , snapshotname:target , remove:remove, free:free ,removemeta:removemeta ,keep:keep, desc:desc}
@@ -65,10 +66,10 @@ $style[] = "legend{font-size:1.1rem!important;font-weight:bold}";
$style[] = "</style>";
foreach (explode('&', $url) as $chunk) {
$param = explode("=", $chunk);
if ($param) {
${urldecode($param[0])} = urldecode($param[1]) ;
}
$param = explode("=", $chunk);
if ($param) {
${urldecode($param[0])} = urldecode($param[1]) ;
}
}
$id = 1 ;
write(implode($style)."<p class='logLine'></p>");
@@ -78,25 +79,23 @@ write("addLog\0".htmlspecialchars("VMName $name "));
write("addLog\0".htmlspecialchars("SNAP $snapshotname "));
write("addLog\0".htmlspecialchars("Base $targetbase "));
if ($action == "commit") {
write("addLog\0".htmlspecialchars("Top $targettop "));
write("addLog\0".htmlspecialchars("Pivot $targetpivot "));
write("addLog\0".htmlspecialchars("Delete $targetdelete "));
write("addLog\0".htmlspecialchars("Top $targettop "));
write("addLog\0".htmlspecialchars("Pivot $targetpivot "));
write("addLog\0".htmlspecialchars("Delete $targetdelete "));
}
switch ($action) {
case "commit":
vm_blockcommit($name,$snapshotname,$path,$targetbase,$targettop,$targetpivot,$targetdelete) ;
break ;
case "copy":
vm_blockcopy($name,$snapshotname,$path,$targetbase,$targettop,$pivot,' ') ;
break;
case "pull":
vm_blockpull($name,$snapshotname,$path,$targetbase,$targettop,$pivot,' ') ;
break ;
}
case "commit":
vm_blockcommit($name,$snapshotname,$path,$targetbase,$targettop,$targetpivot,$targetdelete) ;
break ;
case "copy":
vm_blockcopy($name,$snapshotname,$path,$targetbase,$targettop,$pivot,' ') ;
break;
case "pull":
vm_blockpull($name,$snapshotname,$path,$targetbase,$targettop,$pivot,' ') ;
break ;
}
#execCommand_nchan("ls /") ;
write("stop_Wait\0$waitID") ;
write('_DONE_','');
?>
?>

View File

@@ -1,6 +1,7 @@
#!/usr/bin/php -q
<?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,
@@ -11,67 +12,65 @@
*/
?>
<?
$docroot = $docroot ?? $_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp';
require_once "$docroot/webGui/include/Wrappers.php";
$docroot ??= ($_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp');
require_once "$docroot/webGui/include/Helpers.php";
require_once "$docroot/plugins/dynamix.docker.manager/include/DockerClient.php";
require_once "$docroot/plugins/dynamix.vm.manager/include/libvirt_helpers.php";
// add translations
$_SERVER['REQUEST_URI'] = '';
$login_locale = _var($display,'locale');
require_once "$docroot/plugins/dynamix.docker.manager/include/DockerClient.php";
require_once "$docroot/webGui/include/Translations.php";
require_once "$docroot/plugins/dynamix.vm.manager/include/libvirt_helpers.php";
require_once "$docroot/webGui/include/Helpers.php";
function write(...$messages){
$com = curl_init();
curl_setopt_array($com,[
CURLOPT_URL => 'http://localhost/pub/vmaction?buffer_length=1',
CURLOPT_UNIX_SOCKET_PATH => '/var/run/nginx.socket',
CURLOPT_POST => 1,
CURLOPT_RETURNTRANSFER => true
]);
foreach ($messages as $message) {
curl_setopt($com, CURLOPT_POSTFIELDS, $message);
curl_exec($com);
}
curl_close($com);
}
function execCommand_nchan($command,$idx,$refcmd=false) {
$waitID = mt_rand();
if ($refcmd) {
[$cmd,$args] = explode(' ',$refcmd,2);
write("<p class='logLine'></p>","addLog\0<fieldset class='docker'><legend>"._('Command execution')."</legend>".basename($cmd).' '.str_replace(" -","<br>&nbsp;&nbsp;-",htmlspecialchars($args))."<br><span id='wait-$waitID'>"._('Please wait')." </span><p class='logLine'></p></fieldset>","show_Wait\0$waitID");
$rtn = exec("$refcmd 2>&1", $output,$return) ;
if ($return == 0) $reflinkok = true ; else {
$reflinkok = false ;
write("addLog\0<br><b>{$output[0]}</b>");
}
$out = $return ? _('The command failed revert to rsync')."." : _('The command finished successfully').'!';
write("stop_Wait\0$waitID","addLog\0<br><b>$out</b>");
}
if ($reflinkok) {
return true ;
} else {
$waitID = mt_rand();
[$cmd,$args] = explode(' ',$command,2);
write("<p class='logLine'></p>","addLog\0<fieldset class='docker'><legend>"._('Command execution')."</legend>".basename($cmd).' '.str_replace(" -","<br>&nbsp;&nbsp;-",htmlspecialchars($args))."<br><span id='wait-$waitID'>"._('Please wait')." </span><p class='logLine'></p></fieldset>","show_Wait\0$waitID");
write("addToID\0$idx\0Cloning VM: ") ;
$proc = popen("$command 2>&1 &",'r');
while ($out = fread($proc,100)) {
$out = preg_replace("%[\t\n\x0B\f\r]+%", '',$out);
$out = trim($out) ;
$values = explode(' ',$out) ;
$string = _("Data copied: ").$values[0].' '._(" Percentage: ").$values[1].' '._(" Transfer Rate: ").$values[2].' '._(" Time remaining: ").$values[4].$values[5] ;
write("progress\0$idx\0".htmlspecialchars($string)) ;
if ($out) $stringsave=$string ;
}
$retval = pclose($proc);
write("progress\0$idx\0".htmlspecialchars($stringsave)) ;
$out = $retval ? _('The command failed').'.' : _('The command finished successfully').'!';
write("stop_Wait\0$waitID","addLog\0<br><b>$out</b>");
return $retval===0;
function write(...$messages) {
$com = curl_init();
curl_setopt_array($com,[
CURLOPT_URL => 'http://localhost/pub/vmaction?buffer_length=1',
CURLOPT_UNIX_SOCKET_PATH => '/var/run/nginx.socket',
CURLOPT_POST => 1,
CURLOPT_RETURNTRANSFER => true
]);
foreach ($messages as $message) {
curl_setopt($com, CURLOPT_POSTFIELDS, $message);
curl_exec($com);
}
curl_close($com);
}
function execCommand_nchan_clone($command,$idx,$refcmd=false) {
$waitID = mt_rand();
if ($refcmd) {
[$cmd,$args] = explode(' ',$refcmd,2);
write("<p class='logLine'></p>","addLog\0<fieldset class='docker'><legend>"._('Command execution')."</legend>".basename($cmd).' '.str_replace(" -","<br>&nbsp;&nbsp;-",htmlspecialchars($args))."<br><span id='wait-$waitID'>"._('Please wait')." </span><p class='logLine'></p></fieldset>","show_Wait\0$waitID");
$rtn = exec("$refcmd 2>&1", $output,$return) ;
if ($return == 0) $reflinkok = true ; else {
$reflinkok = false ;
write("addLog\0<br><b>{$output[0]}</b>");
}
$out = $return ? _('The command failed revert to rsync')."." : _('The command finished successfully').'!';
write("stop_Wait\0$waitID","addLog\0<br><b>$out</b>");
}
if ($reflinkok) {
return true ;
} else {
$waitID = mt_rand();
[$cmd,$args] = explode(' ',$command,2);
write("<p class='logLine'></p>","addLog\0<fieldset class='docker'><legend>"._('Command execution')."</legend>".basename($cmd).' '.str_replace(" -","<br>&nbsp;&nbsp;-",htmlspecialchars($args))."<br><span id='wait-$waitID'>"._('Please wait')." </span><p class='logLine'></p></fieldset>","show_Wait\0$waitID");
write("addToID\0$idx\0Cloning VM: ") ;
$proc = popen("$command 2>&1 &",'r');
while ($out = fread($proc,100)) {
$out = preg_replace("%[\t\n\x0B\f\r]+%", '',$out);
$out = trim($out);
$values = explode(' ',$out);
$string = _("Data copied: ").$values[0].' '._(" Percentage: ").$values[1].' '._(" Transfer Rate: ").$values[2].' '._(" Time remaining: ").$values[4].$values[5];
write("progress\0$idx\0".htmlspecialchars($string));
if ($out) $stringsave=$string;
}
$retval = pclose($proc);
write("progress\0$idx\0".htmlspecialchars($stringsave));
$out = $retval ? _('The command failed').'.' : _('The command finished successfully').'!';
write("stop_Wait\0$waitID","addLog\0<br><b>$out</b>");
return $retval===0;
}
}
@@ -86,10 +85,10 @@ $style[] = "legend{font-size:1.1rem!important;font-weight:bold}";
$style[] = "</style>";
foreach (explode('&', $url) as $chunk) {
$param = explode("=", $chunk);
if ($param) {
${urldecode($param[0])} = urldecode($param[1]) ;
}
$param = explode("=", $chunk);
if ($param) {
${urldecode($param[0])} = urldecode($param[1]) ;
}
}
$id = 1 ;
write(implode($style)."<p class='logLine'></p>");
@@ -99,10 +98,10 @@ write("<p class='logLine'></p>","addLog\0<fieldset class='docker'><legend>"._("O
write("addLog\0".htmlspecialchars("Cloning $name to $clone"));
switch ($action) {
case "clone":
$rtn = vm_clone($name,$clone,$overwrite,$start,$edit,$free,$waitID) ;
break ;
}
case "clone":
$rtn = vm_clone($name,$clone,$overwrite,$start,$edit,$free,$waitID) ;
break ;
}
write("stop_Wait\0$waitID") ;
if ($rtn) write('_DONE_',''); else write('_ERROR_','');
?>
?>

View File

@@ -0,0 +1,4 @@
.fileTree{background:#f2f2f2;width:300px;max-height:150px;overflow-y:scroll;overflow-x:hidden;position:relative;z-index:100;display:none}
#vmform table.multiple{margin:10px 0;background:#f2f2f2;background-size:800px 100%;background-position:-800px;background-repeat:no-repeat;background-clip:content-box;transition:background 0.3s linear}
#template_img_chooser_outer{position:absolute;display:none;border-radius:5px;border:1px solid <?=$border?>;background:#f2f2f2;z-index:10}
span#dropbox{border:1px solid <?=$border?>;background:#f2f2f2;padding:28px 12px;line-height:72px;margin-right:16px;}

View File

@@ -0,0 +1,4 @@
.fileTree{background:#1c1c1c;width:300px;max-height:150px;overflow-y:scroll;overflow-x:hidden;position:relative;z-index:100;display:none}
#vmform table.multiple{margin:10px 0;background:#1c1c1c;background-size:800px 100%;background-position:-800px;background-repeat:no-repeat;background-clip:content-box;transition:background 0.3s linear}
#template_img_chooser_outer{position:absolute;display:none;border-radius:5px;border:1px solid <?=$border?>;background:#1c1c1c;z-index:10}
span#dropbox{border:1px solid <?=$border?>;background:#1c1c1c;padding:28px 12px;line-height:72px;margin-right:16px;}

View File

@@ -0,0 +1,4 @@
.fileTree{background:#1c1c1c;width:300px;max-height:150px;overflow-y:scroll;overflow-x:hidden;position:relative;z-index:100;display:none}
#vmform table.multiple{margin:10px 0;background:#1c1c1c;background-size:800px 100%;background-position:-800px;background-repeat:no-repeat;background-clip:content-box;transition:background 0.3s linear}
#template_img_chooser_outer{position:absolute;display:none;border-radius:5px;border:1px solid <?=$border?>;background:#1c1c1c;z-index:10}
span#dropbox{border:1px solid <?=$border?>;background:#1c1c1c;padding:28px 12px;line-height:72px;margin-right:16px;}

View File

@@ -0,0 +1,4 @@
.fileTree{background:#f2f2f2;width:300px;max-height:150px;overflow-y:scroll;overflow-x:hidden;position:relative;z-index:100;display:none}
#vmform table.multiple{margin:10px 0;background:#f2f2f2;background-size:800px 100%;background-position:-800px;background-repeat:no-repeat;background-clip:content-box;transition:background 0.3s linear}
#template_img_chooser_outer{position:absolute;display:none;border-radius:5px;border:1px solid <?=$border?>;background:#f2f2f2;z-index:10}
span#dropbox{border:1px solid <?=$border?>;background:#f2f2f2;padding:28px 12px;line-height:72px;margin-right:16px;}

View File

@@ -0,0 +1,43 @@
body{-webkit-overflow-scrolling:touch}
#vmform table{margin-top:0}
#vmform div.title + table{margin-top:0}
#vmform table tr{vertical-align:top;line-height:40px}
#vmform table tr td:nth-child(odd){width:300px;text-align:right;padding-right:10px}
#vmform table tr td:nth-child(even){width:110px}
#vmform table tr td:first-child{padding-right:30px}
#vmform table tr td:last-child{width:inherit}
#vmform .multiple{position:relative}
#vmform .sectionbutton{position:absolute;left:2px;cursor:pointer;opacity:0.4;font-size:1.4rem;line-height:17px;z-index:10;transition-property:opacity,left;transition-duration:0.1s;transition-timing-function:linear}
#vmform .sectionbutton.remove{top:0;opacity:0.3}
#vmform .sectionbutton.add{bottom:0}
#vmform .sectionbutton:hover{opacity:1.0}
#vmform .sectiontab{position:absolute;top:2px;bottom:2px;left:0;width:6px;border-radius:3px;background-color:#DDDDDD;transition-property:background,width;transition-duration:0.1s;transition-timing-function:linear}
#vmform .multiple:hover .sectionbutton{opacity:0.7;left:4px}
#vmform .multiple:hover .sectionbutton.remove{opacity:0.6}
#vmform .multiple:hover .sectiontab{background-color:#CCCCCC;width:8px}
#vmform table.multiple:hover{background-position:0 0;}
#vmform table.multiple td{padding:5px 0}
span.advancedview_panel{display:none;line-height:16px;margin-top:1px}
.basic{display:none}
.advanced{/*Empty placeholder*/}
.switch-button-label.off{color:inherit}
#template_img{cursor:pointer}
#template_img:hover{opacity:0.5}
#template_img:hover i{opacity:1.0}
.template_img_chooser_inner{display:inline-block;width:80px;margin-bottom:15px;margin-right:10px;text-align:center;}
.template_img_chooser_inner img{width:48px;height:48px}
.template_img_chooser_inner p{text-align:center;line-height:8px;}
#template_img_chooser{width:560px;height:300px;overflow-y:scroll;position:relative}
#template_img_chooser div:hover{background-color:#eee;cursor:pointer;}
#form_content{display:none}
#vmform .four{overflow:hidden}
#vmform .four label{float:left;display:table-cell;width:15%;}
#vmform .four label:nth-child(4n+4){}
#vmform .four label.cpu1{width:28%;height:16px;line-height:16px}
#vmform .four label.cpu2{width:3%;height:16px;line-height:16px}
#vmform .mac_generate{cursor:pointer;margin-left:-5px;color:#08C;font-size:1.3rem;transform:translate(0px, 2px)}
#vmform .disk{display:none}
#vmform .disk_preview{display:inline-block;color:#BBB;transform:translate(0px, 1px)}
i.fa-plus-circle,i.fa-minus-circle{margin-left:8px}
input[type=checkbox]{margin-left:0}
#vmform table.timers td.present {width:150px;}

View File

@@ -0,0 +1,4 @@
.fileTree{background:#f2f2f2;width:300px;max-height:150px;overflow-y:scroll;overflow-x:hidden;position:relative;z-index:100;display:none}
#vmform table.multiple{margin:10px 0;background:#f2f2f2;background-size:800px 100%;background-position:-800px;background-repeat:no-repeat;background-clip:content-box;transition:background 0.3s linear}
#template_img_chooser_outer{position:absolute;display:none;border-radius:5px;border:1px solid <?=$border?>;background:#f2f2f2;z-index:10}
span#dropbox{border:1px solid <?=$border?>;background:#f2f2f2;padding:28px 12px;line-height:72px;margin-right:16px;}

View File

@@ -0,0 +1,4 @@
.fileTree{background:#1c1c1c;width:300px;max-height:150px;overflow-y:scroll;overflow-x:hidden;position:relative;z-index:100;display:none}
#vmform table.multiple{margin:10px 0;background:#1c1c1c;background-size:800px 100%;background-position:-800px;background-repeat:no-repeat;background-clip:content-box;transition:background 0.3s linear}
#template_img_chooser_outer{position:absolute;display:none;border-radius:5px;border:1px solid <?=$border?>;background:#1c1c1c;z-index:10}
span#dropbox{border:1px solid <?=$border?>;background:#1c1c1c;padding:28px 12px;line-height:72px;margin-right:16px;}

View File

@@ -0,0 +1,4 @@
.fileTree{background:#1c1c1c;width:300px;max-height:150px;overflow-y:scroll;overflow-x:hidden;position:relative;z-index:100;display:none}
#vmform table.multiple{margin:10px 0;background:#1c1c1c;background-size:800px 100%;background-position:-800px;background-repeat:no-repeat;background-clip:content-box;transition:background 0.3s linear}
#template_img_chooser_outer{position:absolute;display:none;border-radius:5px;border:1px solid <?=$border?>;background:#1c1c1c;z-index:10}
span#dropbox{border:1px solid <?=$border?>;background:#1c1c1c;padding:28px 12px;line-height:72px;margin-right:16px;}

View File

@@ -0,0 +1,4 @@
.fileTree{background:#f2f2f2;width:300px;max-height:150px;overflow-y:scroll;overflow-x:hidden;position:relative;z-index:100;display:none}
#vmform table.multiple{margin:10px 0;background:#f2f2f2;background-size:800px 100%;background-position:-800px;background-repeat:no-repeat;background-clip:content-box;transition:background 0.3s linear}
#template_img_chooser_outer{position:absolute;display:none;border-radius:5px;border:1px solid <?=$border?>;background:#f2f2f2;z-index:10}
span#dropbox{border:1px solid <?=$border?>;background:#f2f2f2;padding:28px 12px;line-height:72px;margin-right:16px;}

View File

@@ -0,0 +1,43 @@
body{-webkit-overflow-scrolling:touch}
#vmform table{margin-top:0}
#vmform div.title + table{margin-top:0}
#vmform table tr{vertical-align:top;line-height:40px}
#vmform table tr td:nth-child(odd){width:300px;text-align:right;padding-right:10px}
#vmform table tr td:nth-child(even){width:110px}
#vmform table tr td:first-child{padding-right:30px}
#vmform table tr td:last-child{width:inherit}
#vmform .multiple{position:relative}
#vmform .sectionbutton{position:absolute;left:2px;cursor:pointer;opacity:0.4;font-size:1.4rem;line-height:17px;z-index:10;transition-property:opacity,left;transition-duration:0.1s;transition-timing-function:linear}
#vmform .sectionbutton.remove{top:0;opacity:0.3}
#vmform .sectionbutton.add{bottom:0}
#vmform .sectionbutton:hover{opacity:1.0}
#vmform .sectiontab{position:absolute;top:2px;bottom:2px;left:0;width:6px;border-radius:3px;background-color:#DDDDDD;transition-property:background,width;transition-duration:0.1s;transition-timing-function:linear}
#vmform .multiple:hover .sectionbutton{opacity:0.7;left:4px}
#vmform .multiple:hover .sectionbutton.remove{opacity:0.6}
#vmform .multiple:hover .sectiontab{background-color:#CCCCCC;width:8px}
#vmform table.multiple:hover{background-position:0 0;}
#vmform table.multiple td{padding:5px 0}
span.advancedview_panel{display:none;line-height:16px;margin-top:1px}
.basic{display:none}
.advanced{/*Empty placeholder*/}
.switch-button-label.off{color:inherit}
#template_img{cursor:pointer}
#template_img:hover{opacity:0.5}
#template_img:hover i{opacity:1.0}
.template_img_chooser_inner{display:inline-block;width:80px;margin-bottom:15px;margin-right:10px;text-align:center;}
.template_img_chooser_inner img{width:48px;height:48px}
.template_img_chooser_inner p{text-align:center;line-height:8px;}
#template_img_chooser{width:560px;height:300px;overflow-y:scroll;position:relative}
#template_img_chooser div:hover{background-color:#eee;cursor:pointer;}
#form_content{display:none}
#vmform .four{overflow:hidden}
#vmform .four label{float:left;display:table-cell;width:15%;}
#vmform .four label:nth-child(4n+4){}
#vmform .four label.cpu1{width:28%;height:16px;line-height:16px}
#vmform .four label.cpu2{width:3%;height:16px;line-height:16px}
#vmform .mac_generate{cursor:pointer;margin-left:-5px;color:#08C;font-size:1.3rem;transform:translate(0px, 2px)}
#vmform .disk{display:none}
#vmform .disk_preview{display:inline-block;color:#BBB;transform:translate(0px, 1px)}
i.fa-plus-circle,i.fa-minus-circle{margin-left:8px}
input[type=checkbox]{margin-left:0}
#vmform table.timers td.present {width:150px;}

Some files were not shown because too many files have changed in this diff Show More