Merge pull request #2020 from bergware/master

VM template fixes
This commit is contained in:
tom mortensen
2025-02-15 12:22:35 -08:00
committed by GitHub
13 changed files with 198 additions and 159 deletions

View File

@@ -325,10 +325,12 @@ $xml2 = build_xml_templates($strXML);
#disable rename if snapshots exist
$snapshots = getvmsnapshots($arrConfig['domain']['name']);
if ($snapshots != null && count($snapshots) && !$boolNew) {
if ($snapshots!=null && count($snapshots) && !$boolNew) {
$snaphidden = "";
$namedisable = "disabled";
$snapcount = count($snapshots);
} else {
$snaphidden = "hidden";
$namedisable = "";
$snapcount = "0";
}
@@ -347,11 +349,16 @@ if ($snapshots != null && count($snapshots) && !$boolNew) {
<input type="hidden" name="domain[memoryBacking]" id="domain_memorybacking" value="<?=htmlspecialchars($arrConfig['domain']['memoryBacking'])?>">
<table>
<tr class="hidden">
<tr class="<?=$snaphidden?>">
<td></td>
<td><span class="orange-text"><i class="fa fa-fw fa-warning"></i> _(Rename disabled, <?=$snapcount?> snapshot(s) exists)_.</span></td>
<td></td>
</tr>
<tr id="zfs-name" class="hidden">
<td></td>
<td>
<span id="snap-rename" class="orange-text"><i class="fa fa-warning"></i> _(Rename disabled, <?=$snapcount?> snapshot(s) exists.)_</span>
<span id="zfs-name" class="orange-text"><i class="fa fa-warning"></i> _(Name contains invalid characters or does not start with an alphanumberic for a ZFS storage location<br>Only these special characters are valid Underscore (_) Hyphen (-) Colon (:) Period (.))_</span>
<span class="orange-text"><i class="fa fa-fw fa-warning"></i> _(Name contains invalid characters or does not start with an alphanumberic for a ZFS storage location)_</span><br>
<span class="green-text"><i class="fa fa-fw fa-info-circle"></i> _(Only these special characters are valid Underscore (_) Hyphen (-) Colon (:) Period (.))_</span>
</td>
<td></td>
</tr>
@@ -655,7 +662,7 @@ if (!isset($arrValidMachineTypes[$arrConfig['domain']['machine']])) {
<tr class="advanced">
<td>_(BIOS)_:</td>
<td>
<span class="width"><select name="domain[ovmf]" id="domain_ovmf" onchange="BIOSChange(this)" class="narrow">
<span class="width"><select name="domain[ovmf]" id="domain_ovmf" onchange="BIOSChange(this.value)" class="narrow">
<?
echo mk_option($arrConfig['domain']['ovmf'], '0', _('SeaBIOS'));
if (file_exists('/usr/share/qemu/ovmf-x64/OVMF_CODE-pure-efi.fd')) {
@@ -913,7 +920,7 @@ if (!isset($arrValidMachineTypes[$arrConfig['domain']['machine']])) {
<tr class="advanced disk_bus_options">
<td>_(vDisk Bus)_:</td>
<td>
<span class="width"><select name="disk[<?=$i?>][bus]" class="disk_bus narrow" onchange="BusChange(this)">
<span class="width"><select name="disk[<?=$i?>][bus]" class="disk_bus narrow" onchange="BusChange(this.value,<?=$i?>)">
<?mk_dropdown_options($arrValidDiskBuses, $arrDisk['bus']);?>
</select></span>
<span class="label">_(Boot Order)_:</span>
@@ -924,7 +931,7 @@ if (!isset($arrValidMachineTypes[$arrConfig['domain']['machine']])) {
</select>
<?if ($arrDisk['bus'] == "virtio" || $arrDisk['bus'] == "usb") $ssddisabled = "hidden"; else $ssddisabled = "";?>
<span id="disk[<?=$i?>][rotatetext]" class="label <?=$ssddisabled?>">_(SSD)_:</span>
<input type="checkbox" id="disk[<?=$i?>][rotation]" class="trim rotation second <?=$ssddisabled?>" onchange="updateSSDCheck(this)" name="disk[<?=$i?>][rotation]" <?=$arrDisk['rotation'] ? "checked ":"";?> value="<?=$arrDisk['rotation']?>">
<input type="checkbox" id="disk[<?=$i?>][rotation]" class="rotation <?=$ssddisabled?>" onchange="updateSSDCheck(this)" name="disk[<?=$i?>][rotation]" <?=$arrDisk['rotation'] ? "checked ":"";?> value="<?=$arrDisk['rotation']?>">
</td>
<td></td>
</tr>
@@ -1066,7 +1073,7 @@ if (!isset($arrValidMachineTypes[$arrConfig['domain']['machine']])) {
<tr class="advanced disk_bus_options">
<td>_(vDisk Bus)_:</td>
<td>
<span class="width"><select name="disk[{{INDEX}}][bus]" class="disk_bus narrow" onchange="BusChange(this)">
<span class="width"><select name="disk[{{INDEX}}][bus]" class="disk_bus narrow" onchange="BusChange(this.value,{{INDEX}})">
<?mk_dropdown_options($arrValidDiskBuses, '');?>
</select></span>
<span class="label">_(Boot Order)_:</span>
@@ -1076,7 +1083,7 @@ if (!isset($arrValidMachineTypes[$arrConfig['domain']['machine']])) {
<?mk_dropdown_options($arrValidDiskDiscard, "unmap");?>
</select>
<span id="disk[{{INDEX}}][rotatetext]" class="label hidden">_(SSD)_:</span>
<input type="checkbox" id="disk[{{INDEX}}][rotation]" class="trim rotation second hidden" onchange="updateSSDCheck(this)" name="disk[{{INDEX}}[rotation]" value='0'>
<input type="checkbox" id="disk[{{INDEX}}][rotation]" class="rotation hidden" onchange="updateSSDCheck(this)" name="disk[{{INDEX}}[rotation]" value='0'>
</td>
<td></td>
<tr class="advanced disk_bus_options">
@@ -1282,9 +1289,9 @@ foreach ($arrConfig['shares'] as $i => $arrShare) {
?>
</select></span>
<span id="Porttext" class="label <?=$hiddenport?>">_(VM Console Port)_:</span>
<input type="number" size="5" maxlength="5" id="port" class="trim second <?=$hiddenport?>" name="gpu[<?=$i?>][port]" value="<?=$arrGPU['port']?>">
<input id="port" type="number" size="5" maxlength="5" class="trim second <?=$hiddenport?>" name="gpu[<?=$i?>][port]" value="<?=$arrGPU['port']?>">
<span id="WSPorttext" class="label <?=$hiddenwsport?>">_(VM Console WS Port)_:</span>
<input type="number" size="5" maxlength="5" id="wsport" class="trim second <?=$hiddenwsport?>" name="gpu[<?=$i?>][wsport]" value="<?=$arrGPU['wsport']?>">
<input id="wsport" type="number" size="5" maxlength="5" class="trim second <?=$hiddenwsport?>" name="gpu[<?=$i?>][wsport]" value="<?=$arrGPU['wsport']?>">
</td>
<td></td>
</tr>
@@ -1296,7 +1303,7 @@ foreach ($arrConfig['shares'] as $i => $arrShare) {
</select></span>
<?if ($arrGPU['model'] == "virtio3d") $vmcrender = ""; else $vmcrender = "hidden";?>
<span id="vncrendertext" class="label <?=$vncrender?>">_(Render GPU)_:</span>
<select id="vncrender" name="gpu[<?=$i?>][render]" class="narrow second <?=$vncrender?>">
<select id="vncrender" name="gpu[<?=$i?>][render]" class="second <?=$vncrender?>">
<?
echo mk_option($arrGPU['render'], 'auto', _('Auto'));
foreach ($arrValidGPUDevices as $arrDev) echo mk_option($arrGPU['render'], $arrDev['id'], $arrDev['name'].' ('.$arrDev['id'].')');
@@ -1307,7 +1314,7 @@ foreach ($arrConfig['shares'] as $i => $arrShare) {
if ($arrGPU['model'] == "qxl") $vncdspopt = ""; else $vncdspopt = "hidden";
?>
<span id="vncdspopttext" class="label <?=$vncdspopt?>">_(Display(s) and RAM)_:</span>
<select id="vncdspopt" name="gpu[<?=$i?>][DisplayOptions]" class="narrow second <?=$vncdspopt?>">
<select id="vncdspopt" name="gpu[<?=$i?>][DisplayOptions]" class="second <?=$vncdspopt?>">
<?
foreach ($arrDisplayOptions as $key => $value) echo mk_option($arrGPU['DisplayOptions'], htmlentities($value['qxlxml'],ENT_QUOTES), _($value['text']));
?>
@@ -1342,7 +1349,7 @@ foreach ($arrConfig['shares'] as $i => $arrShare) {
<?
if ($arrValidGPUDevices[$arrGPU['id']]['bootvga'] == "1") $bootgpuhidden = "";
?>
<tr id="gpubootvga<?=$i?>" class="<?=$bootgpuhidden?>"><td>_(Graphics ROM Needed?)_:</td><td><span class="orange-text"><i class="fa fa-warning"></i> _(GPU is primary adapater, vbios may be required.)_</span></td></tr>
<tr id="gpubootvga<?=$i?>" class="<?=$bootgpuhidden?>"><td>_(Graphics ROM Needed)_?:</td><td><span class="orange-text"><i class="fa fa-warning"></i> _(GPU is primary adapter, vbios may be required)_.</span></td></tr>
</table>
<?if ($i == 0 || $i == 1) {?>
@@ -1416,7 +1423,7 @@ foreach ($arrConfig['shares'] as $i => $arrShare) {
</td>
<td></td>
</tr>
<tr id="gpubootvga{{INDEX}}" class="hidden"><td>_(Graphics ROM Needed?)_:</td><td><span class="orange-text"><i class="fa fa-warning"></i> _(GPU is primary adapater, vbios may be required.)_</span></td></tr>
<tr id="gpubootvga{{INDEX}}" class="hidden"><td>_(Graphics ROM Needed)_?:</td><td><span class="orange-text"><i class="fa fa-warning"></i> _(GPU is primary adapter, vbios may be required)_.</span></td></tr>
</table>
</script>
@@ -1746,8 +1753,8 @@ foreach ($arrConfig['nic'] as $i => $arrNic) {
$clockcount = 0;
if (!empty($arrClocks)) {
foreach ($arrClocks as $i => $arrTimer) {
if ($i == "offset") continue;
if ($clockcount == 0) $clocksourcetext = _("Timer Source").":"; else $clocksourcetext = "";
if ($i == 'offset') continue;
if ($clockcount == 0) $clocksourcetext = _('Timer Source').':'; else $clocksourcetext = "";
?>
<tr>
<td><?=$clocksourcetext?></td>
@@ -1941,7 +1948,6 @@ foreach ($arrConfig['evdev'] as $i => $arrEvdev) {
</td>
</tr>
</table>
</div>
<table>
<tr>
@@ -1960,6 +1966,7 @@ foreach ($arrConfig['evdev'] as $i => $arrEvdev) {
<td></td>
</tr>
</table>
</div>
<?if ($boolNew) {?>
<blockquote class="inline_help">
@@ -2033,34 +2040,25 @@ function ShareChange(share) {
}
}
function BusChange(bus) {
var value = bus.value;
var index = bus.name.indexOf("]") + 1;
var name = bus.name.substr(0,index);
function BusChange(value, index) {
$('input[id="disk['+index+'][rotation]"]').removeClass('hidden');
$('span[id="disk['+index+'][rotatetext]"]').removeClass('hidden');
if (value == "virtio" || value == "usb" ) {
$('#'+name+"[rotatetext]").hide();
$('#'+name+"[rotation]").hide();
} else {
$('#'+name+"[rotation]").show();
$('#'+name+"[rotatetext]").show();
$('input[id="disk['+index+'][rotation]"]').addClass('hidden');
$('span[id="disk['+index+'][rotatetext]"]').addClass('hidden');
}
}
function updateSSDCheck(ssd) {
var value = ssd.value;
var index = ssd.name.indexOf("]") + 1;
var name = ssd.name.substr(0,index);
ssd.value = $('#'+name+"[rotation]").prop('checked') ? "1" : "0";
ssd.value = $(ssd).prop('checked') ? "1" : "0";
}
function BIOSChange(bios) {
var value = bios.value;
function BIOSChange(value) {
$("#USBBoottext").removeClass('hidden');
$("#domain_usbboot").removeClass('hidden');
if (value == "0") {
$("#USBBoottext").hide();
$("#domain_usbboot").hide();
} else {
$("#USBBoottext").show();
$("#domain_usbboot").show();
$("#USBBoottext").addClass('hidden');
$("#domain_usbboot").addClass('hidden');
}
}
@@ -2117,17 +2115,19 @@ function SetBootorderfields(usbbootvalue) {
/* Remove characters not allowed in share name. */
function checkName(name) {
/* Declare variables at the function scope */
var isValidName
$('#zfs-name').hide();
isValidName = /^[A-Za-z0-9][A-Za-z0-9\-_.: ]*$/.test(name);
$('#zfs-name').removeClass();
if (isValidName) {
$('#btnSubmit').prop("disabled",false);
$('#zfs-name').addClass('hidden')
} else {
if (storageType == "zfs") {
$('#btnSubmit').prop("disabled",true); $('#zfs-name').show();
$('#btnSubmit').prop("disabled",true);
} else {
$('#btnSubmit').prop("disabled",false);
$('#zfs-name').addClass('hidden')
}
else $('#btnSubmit').prop("disabled",false);
}
}
@@ -2151,54 +2151,50 @@ function USBBootChange(usbboot) {
}
function AutoportChange(autoport) {
$("#port").removeClass('hidden');
$("#Porttext").removeClass('hidden');
$("#wsport").removeClass('hidden');
$("#WSPorttext").removeClass('hidden');
if (autoport.value == "yes") {
$("#port").hide();
$("#Porttext").hide();
$("#wsport").hide();
$("#WSPorttext").hide();
$("#port").addClass('hidden');
$("#Porttext").addClass('hidden');
$("#wsport").addClass('hidden');
$("#WSPorttext").addClass('hidden');
} else {
var protocol = document.getElementById("protocol").value;
$("#port").show();
$("#Porttext").show();
if (protocol == "vnc") {
$("#wsport").show();
$("#WSPorttext").show();
} else {
$("#wsport").hide();
$("#WSPorttext").hide();
if (protocol != "vnc") {
$("#wsport").addClass('hidden');
$("#WSPorttext").addClass('hidden');
}
}
}
function VMConsoleDriverChange(driver) {
$("#vncrender").removeClass('hidden');
$("#vncrendertext").removeClass('hidden');
if (driver.value != "virtio3d") {
$("#vncrender").hide();
$("#vncrendertext").hide();
} else {
$("#vncrender").show();
$("#vncrendertext").show();
$("#vncrender").addClass('hidden');
$("#vncrendertext").addClass('hidden');
}
$("#vncdspopt").removeClass('hidden');
$("#vncdspopttext").removeClass('hidden');
if (driver.value != "qxl") {
$("#vncdspopt").hide();
$("#vncdspopttext").hide();
} else {
$("#vncdspopt").show();
$("#vncdspopttext").show();
$("#vncdspopt").addClass('hidden');
$("#vncdspopttext").addClass('hidden');
}
}
function ProtocolChange(protocol) {
var autoport = $("#autoport").val();
$("port").removeClass('hidden');
$("Porttext").removeClass('hidden');
$("wsport").removeClass('hidden');
$("WSPorttext").removeClass('hidden');
if (autoport == "yes") {
$("port").hide();
$("Porttext").hide();
$("wsport").hide();
$("WSPorttext").hide();
} else {
$("port").show();
$("Porttext").show();
$("wsport").show();
$("WSPorttext").show();
$("port").addClass('hidden');
$("Porttext").addClass('hidden');
$("wsport").addClass('hidden');
$("WSPorttext").addClass('hidden');
}
}
@@ -2440,16 +2436,11 @@ $(function() {
});
$("#vmform").on("change", ".cpu", function changeCPUEvent(){
var myvalue = $(this).val();
var mylabel = $(this).children('option:selected').text();
var cpumigrate = document.getElementById("domain_cpumigrate_text");
var cpumigrate_text = document.getElementById("domain_cpumigrate");
if (myvalue == "custom") {
$("#domain_cpumigrate_text").hide();
$("#domain_cpumigrate").hide();
} else {
$("#domain_cpumigrate_text").show();
$("#domain_cpumigrate").show();
$("#domain_cpumigrate_text").removeClass('hidden');
$("#domain_cpumigrate").removeClass('hidden');
if ($(this).val() == "custom") {
$("#domain_cpumigrate_text").addClass('hidden');
$("#domain_cpumigrate").addClass('hidden');
}
});
@@ -2465,19 +2456,17 @@ $(function() {
slideDownRows($vnc_sections.not(isVMAdvancedMode() ? '.basic' : '.advanced'));
var MultiSel = document.getElementById("GPUMultiSel0");
MultiSel.disabled = true;
if ($("#vncmodel").val() == "virtio3d") {
$("#vncrender").show();
$("#vncrendertext").show();
} else {
$("#vncrender").hide();
$("#vncrendertext").hide();
$("#vncrender").removeClass('hidden');
$("#vncrendertext").removeClass('hidden');
if ($("#vncmodel").val() != "virtio3d") {
$("#vncrender").addClass('hidden');
$("#vncrendertext").addClass('hidden');
}
if ($("#vncmodel").val() == "qxl") {
$("#vncdspopt").show();
$("#vncdspopttext").show();
} else {
$("#vncdspopt").hide();
$("#vncdspopttext").hide();
$("#vncdspopt").removeClass('hidden');
$("#vncdspopttext").removeClass('hidden');
if ($("#vncmodel").val() != "qxl") {
$("#vncdspopt").addClass('hidden');
$("#vncdspopttext").addClass('hidden');
}
} else {
slideUpRows($vnc_sections);
@@ -2486,12 +2475,15 @@ $(function() {
if (myvalue=="nogpu") MultiSel.disabled = true; else MultiSel.disabled = false;
}
}
if (mylabel == "_(None)_") $("#gpubootvga"+myindex).hide();
if (myvalue != "_(virtual)_" && myvalue != '' && myvalue != "_(nogpu)_") {
if (ValidGPUs[myvalue].bootvga == "1") $("#gpubootvga"+myindex).show(); else $("#gpubootvga"+myindex).hide();
$("#gpubootvga"+myindex).removeClass();
if (mylabel == "_(None)_") $("#gpubootvga"+myindex).addClass('hidden');
if (myvalue != "_(virtual)_" && myvalue != "" && myvalue != "_(nogpu)_") {
if (ValidGPUs[myvalue].bootvga != "1") $("#gpubootvga"+myindex).addClass('hidden');
} else {
$("#gpubootvga"+myindex).addClass('hidden');
}
$romfile = $(this).closest('table').find('.romfile');
if (myvalue == '_(virtual)_' || myvalue == '' || myvalue =="_(nogpu)_") {
if (myvalue == "_(virtual)_" || myvalue == "" || myvalue == "_(nogpu)_") {
slideUpRows($romfile.not(isVMAdvancedMode() ? '.basic' : '.advanced'));
$romfile.filter('.advanced').removeClass('advanced').addClass('wasadvanced');
} else {
@@ -2642,13 +2634,13 @@ $(function() {
$panel.find('input').prop('disabled', true);
$button.val($button.attr('busyvalue'));
swal({
title: '_(Template Name)_',
text: "_(Enter name:\nIf name already exists it will be replaced.)_",
title: "_(Template Name)_",
text: "_(Enter name)_:\n_(If name already exists it will be replaced)_.",
type: "input",
showCancelButton: true,
closeOnConfirm: false,
//animation: "slide-from-top",
inputPlaceholder: "_(Leaving blank will use OS name.)_"
inputPlaceholder: "_(Leaving blank will use OS name)_."
},
function(inputValue) {
postdata=postdata+"&templatename="+inputValue;
@@ -2710,12 +2702,12 @@ $(function() {
$button.val($button.attr('busyvalue'));
swal({
title: "_(Template Name)_",
text: "_(Enter name:\nIf name already exists it will be replaced.)_",
text: "_(Enter name)_:\n_(If name already exists it will be replaced)_.",
type: "input",
showCancelButton: true,
closeOnConfirm: false,
//animation: "slide-from-top",
inputPlaceholder: "_(Leaving blank will use OS name.)_"
inputPlaceholder: "_(Leaving blank will use OS name)_."
},
function(inputValue) {
postdata=postdata+"&templatename="+inputValue;

View File

@@ -48,6 +48,7 @@ function check_encryption() {
echo "<tr id='copy'><td></td><td class='gap'>",_('Retype passphrase'),":</td><td><input type='password' name='copy' maxlength='512' value='' onkeyup='selectInput(this.form)'></td></tr>";
echo "<tr id='file'><td></td><td class='gap'>",_('Keyfile'),":</td><td><input type='file' name='local' onchange='getFileContent(event,this.form)'></td></tr>";
}
function maintenance_mode() {
echo "<tr>";
echo "<td></td>";
@@ -55,6 +56,7 @@ function maintenance_mode() {
echo "<td><b>",_('Maintenance mode'),"</b> - ",_('if checked, Start array but do not mount disks'),"</td>";
echo "</tr>";
}
function status_indicator() {
global $var;
switch (_var($var,'mdColor')) {
@@ -65,15 +67,18 @@ function status_indicator() {
}
echo "<a class='info'><i class='fa fa-$orb orb $color-orb'></i><span>$help</span></a>";
}
function missing_cache() {
global $disks;
$missing = false;
foreach (cache_filter($disks) as $disk) $missing |= (strpos(_var($disk,'status'),'_MISSING')!==false);
return $missing;
}
function resync($d) {
return in_array($d,['P','Q']) ? 'Parity-Sync' : 'Data-Rebuild';
}
function print_error($error) {
return sprintf(_('Finding **%s** error'.($error==1?'':'s')),$error?:'0');
}
@@ -111,6 +116,7 @@ function toggle_state(device,name,action) {
devices.stop();
$.post('/webGui/include/ToggleState.php',{device:device,name:name,action:action},function(){setTimeout(function(){devices.start();},1000);if (button) $(button).prop('disabled',false);});
}
function display_diskio() {
if ($.cookie('diskio')===undefined) {
$('span.diskio').show(); $('span.number').hide();
@@ -118,20 +124,25 @@ function display_diskio() {
$('span.number').show(); $('span.diskio').hide();
}
}
function toggle_diskio(init) {
if (!init) {
if ($.cookie('diskio')===undefined) $.cookie('diskio','diskio',{expires:3650}); else $.removeCookie('diskio');
}
if ($.cookie('diskio')===undefined) {
$('i.toggle').removeClass('fa-list').addClass('fa-tachometer');
$('#clearstats').addClass('hidden');
} else {
$('i.toggle').removeClass('fa-tachometer').addClass('fa-list');
$('#clearstats').removeClass('hidden');
}
display_diskio();
}
function base64(str) {
return window.btoa(unescape(encodeURIComponent(str)));
}
function selectInput(form) {
<?if ($wrong && $keyfile):?>
form.input.value = 'file';
@@ -175,12 +186,14 @@ function selectInput(form) {
item.prop('disabled',!form.file.value);
}
}
function getFileContent(event,form) {
var input = event.target;
var reader = new FileReader();
reader.onload = function(){form.file.value=reader.result;selectInput(form);};
reader.readAsDataURL(input.files[0]);
}
function prepareInput(form,button) {
if (button) button.disabled = true;
$.post('/webGui/include/Report.php',{cmd:'state',pools:'<?=implode(',',$pools)?>'},function(state) {
@@ -220,6 +233,7 @@ function prepareInput(form,button) {
}
});
}
function parityWarning(form) {
if (form.md_invalidslot.checked) {
<?if (strpos(_var($disks['parity2'],'status'),'_NP')===false):?>
@@ -232,10 +246,12 @@ function parityWarning(form) {
}
swal({title:"_(Proceed to start)_",text:text,html:true,type:'warning',showCancelButton:true,confirmButtonText:"_(Proceed)_",cancelButtonText:"_(Cancel)_"},function(){prepareInput(form);});
}
function tab0() {
$.removeCookie('one');
$.cookie('tab','tab0');
}
function stopArray(form) {
$(form).append('<input type="hidden" name="cmdStop" value="Stop">');
<?if ($confirm['stop']):?>
@@ -244,6 +260,7 @@ function stopArray(form) {
form.submit();
<?endif;?>
}
function stopParity(form,text) {
$(form).append('<input type="hidden" name="cmdCheckCancel" value="">');
<?if ($confirm['stop']):?>
@@ -252,6 +269,7 @@ function stopParity(form,text) {
form.submit();
<?endif;?>
}
function pauseParity(form) {
$.post('/webGui/include/ParityControl.php',{action:'pause'},function(){
$('#pauseButton').val("_(Resume)_").prop('disabled',true).prop('onclick',null).off('click').click(function(){resumeParity(form);});
@@ -259,6 +277,7 @@ function pauseParity(form) {
form.submit();
});
}
function resumeParity(form) {
$.post('/webGui/include/ParityControl.php',{action:'resume'},function(){
$('#pauseButton').val("_(Pause)_").prop('disabled',true).prop('onclick',null).off('click').click(function(){pauseParity(form);});
@@ -266,9 +285,11 @@ function resumeParity(form) {
form.submit();
});
}
function parityHistory() {
openChanges("parity_history", "_(Parity Operation History)_", "phistory");
}
function shutdown_now(form,cmd) {
$(form).append('<input type="hidden" name="cmd" value="'+cmd+'">');
<?if ($confirm['down']):?>
@@ -281,9 +302,11 @@ function shutdown_now(form,cmd) {
form.submit();
<?endif;?>
}
function toggleApply(checked) {
$('input[name="#apply"]').prop('disabled',!checked);
}
<?if ($tabbed):?>
$('.tabs').append(ctrl);
if ($.cookie('tab')=='tab0') $('i.toggle').hide();
@@ -292,7 +315,6 @@ $('#tab'+$('input[name$="tabs"]').length).click(function(){tab0(); $('i.toggle')
$('div[class=title]:not(":last, .disable_diskio")').each(function(){$(this).append(ctrl);});
<?endif;?>
$('.tooltip_diskio').tooltipster({delay:100,trigger:'custom',triggerOpen:{mouseenter:true},triggerClose:{click:false,scroll:true,mouseleave:true}});
toggle_diskio(true);
<?if (_var($var,'fsState')=='Started'):?>
var mymonitor = new NchanSubscriber('/sub/mymonitor',{subscriber:'websocket'});
@@ -422,7 +444,9 @@ setTimeout(function(){paritymonitor.start();},5000);
$(function(){
var form = document.arrayOps;
if (form.input !== undefined) selectInput(form);
toggle_diskio(true);
});
function formatWarning(val) {
if (val==true) {
swal({
@@ -720,7 +744,7 @@ endswitch;
<table markdown="1" class="array_status noshift">
<tr><td></td><td><input type="button" id="spinup-button" onclick="$('[id^=button-]').prop('disabled',true);toggle_state('up')" value="_(Spin Up)_"><input type="button" id="spindown-button" onclick="$('[id^=button-]').prop('disabled',true);toggle_state('down')" value="_(Spin Down)_"></td>
<td>**_(Spin Up)_** _(will immediately spin up all disks)_.<br>**_(Spin Down)_** _(will immediately spin down all disks)_.</td></tr>
<tr><td></td><td><input type="button" value="_(Clear Stats)_" onclick="toggle_state('Clear')"></td><td>**_(Clear Stats)_** _(will immediately clear all disk statistics)_.</td></tr>
<tr id="clearstats" class="hidden"><td></td><td><input type="button" value="_(Clear Stats)_" onclick="toggle_state('Clear')"></td><td>**_(Clear Stats)_** _(will immediately clear all disk statistics)_.</td></tr>
<tr><td></td><td class="line" colspan="2"></td></tr>
</table>
<?if (_var($var,'shareUser')=='e' && $pool_devices):?>

View File

@@ -64,24 +64,24 @@ function enable_wifi(state) {
$('input[name="#arg[1]"]').val(state);
}
function update_wifi() {
$.post('/webGui/include/Wireless.php',{cmd:'list'},function(text) {
function update_wifi(load) {
$.post('/webGui/include/Wireless.php',{cmd:'list',load:load},function(text) {
if (text.length > 0) {
var wifi = JSON.parse(text);
$('#connected').html(wifi.active);
$('#my_networks').html(wifi.saved);
$('#other_networks').html(wifi.other);
if (wifi.other.length) $('#other_networks').html(wifi.other);
}
});
timers.wifi = setTimeout(update_wifi,10000);
timers.wifi = setTimeout(update_wifi,6000);
}
function manage_wifi(ssid,task) {
if (task==2) {
clearTimeout(timers.wifi);
$.post('/webGui/include/Wireless.php',{cmd:'forget',ssid:ssid},function(){
clearTimeout(timers.wifi);
swal.close();
setTimeout(update_wifi);
setTimeout(function(){update_wifi(1);});
});
return;
}
@@ -146,7 +146,7 @@ function showSecurity(val) {
<?if (_var($wlan0,'WIFI')=='yes'):?>
$(function() {
$('#wifi').show();
update_wifi();
update_wifi(1);
});
<?endif;?>
</script>

View File

@@ -23,50 +23,51 @@ if (isset($_POST['listen'])) {
function port($eth) {
$sys = "/sys/class/net";
if (substr($eth,0,4)=='wlan') return $eth;
$x = preg_replace('/[^0-9]/','',$eth);
return file_exists("$sys/br{$x}") ? "br${x}" : (file_exists("$sys/bond{$x}") ? "bond{$x}" : "eth{$x}");
$x = preg_replace('/[^0-9]/','',$eth) ?: '0';
return file_exists("$sys/br{$x}") ? "br{$x}" : (file_exists("$sys/bond{$x}") ? "bond{$x}" : "eth{$x}");
}
exec("grep -Po 'nameserver \K\S+' /etc/resolv.conf 2>/dev/null",$ns);
$eth = $_POST['port'];
$vlan = $_POST['vlan'];
$eth = $_POST['port'] ?? '';
$vlan = $_POST['vlan'] ?? '';
$wlan0 = $eth == 'wlan0';
$port = port($eth).($vlan ? ".$vlan" : "");
$v6on = trim(file_get_contents("/proc/sys/net/ipv6/conf/$port/disable_ipv6"))==='0';
$none = _('None');
$error = "<span class='red-text'>"._('Missing')."</span>";
$note = in_array($eth,['eth0','wlan0']) && !$vlan ? $error : $none;
$link = _(ucfirst(exec("ethtool $eth 2>/dev/null | awk '$1==\"Link\" {print $3;exit}'")) ?: 'Unknown')." ("._(exec("ethtool $eth 2>/dev/null | grep -Pom1 '^\s+Port: \K.*'") ?: ($eth=='wlan0' ? 'wifi' :'not present')).")";
$speed = _(preg_replace(['/^(\d+)/','/!/'],['$1 ',''],exec("ethtool $eth 2>/dev/null | awk '$1==\"Speed:\" {print $2;exit}'")) ?: 'Unknown');
$ipv4 = array_filter(explode(' ',exec("ip -4 -br addr show $port scope global 2>/dev/null | awk '{\$1=\$2=\"\";print;exit}' | sed -r 's/ metric [0-9]+//g; s/\/[0-9]+//g'")));
$gw4 = exec("ip -4 route show default dev $port 2>/dev/null | awk '{print \$3;exit}'") ?: $note;
$ipv4 = array_filter(explode(' ',exec("ip -4 -br addr show ".escapeshellarg($port)." scope global 2>/dev/null | awk '{\$1=\$2=\"\";print;exit}' | sed -r 's/ metric [0-9]+//g; s/\/[0-9]+//g'")));
$gw4 = exec("ip -4 route show default dev ".escapeshellarg($port)." 2>/dev/null | awk '{print \$3;exit}'") ?: $note;
$dns4 = array_filter($ns,function($ns){return strpos($ns,':')===false;});
$domain = exec("grep -Pom1 'domain \K.*' /etc/resolv.conf 2>/dev/null") ?: '---';
if ($v6on) {
$ipv6 = array_filter(explode(' ',exec("ip -6 -br addr show $port scope global -temporary 2>/dev/null | awk '{\$1=\$2=\"\";print;exit}' | sed -r 's/ metric [0-9]+//g; s/\/[0-9]+//g'")));
$gw6 = exec("ip -6 route show default dev $port 2>/dev/null | awk '{print \$3;exit}'") ?: $note;
$ipv6 = array_filter(explode(' ',exec("ip -6 -br addr show ".escapeshellarg($port)." scope global -temporary 2>/dev/null | awk '{\$1=\$2=\"\";print;exit}' | sed -r 's/ metric [0-9]+//g; s/\/[0-9]+//g'")));
$gw6 = exec("ip -6 route show default dev ".escapeshellarg($port)." 2>/dev/null | awk '{print \$3;exit}'") ?: $note;
$dns6 = array_filter($ns,function($ns){return strpos($ns,':')!==false;});
}
echo "<table style='text-align:left;font-size:1.2rem'>";
echo "<tr><td>&nbsp;</td><td>&nbsp;</td></tr>";
echo "<tr><td>"._('Interface link').":</td><td>$link</td></tr>";
echo "<tr><td>"._('Interface speed').":</td><td>$speed</td></tr>";
if ($eth=='wlan0') {
$ini = '/boot/config/wireless-networks.cfg';
$wifi = (array)@parse_ini_file($ini,true);
$att1 = $att2 = $att3 = '';
foreach ($wifi as $network => $option) {
if (isset($option['GROUP']) && $option['GROUP']=='active') {
$att1 = $network;
$att2 = $option['ATTR2'];
$att3 = $option['ATTR3'];
break;
}
if ($wlan0) {
exec("iw wlan0 link | awk '/^\s+(SSID|signal|[rt]x bitrate): /{print $1,$2,$3,$4}'",$speed);
if (count($speed)==4) {
$network = explode(': ',$speed[0])[1];
$signal = explode(': ',$speed[1])[1];
$rxrate = explode(': ',$speed[2])[1];
$txrate = explode(': ',$speed[3])[1];
} else {
$network = $signal = $rxrate = $txrate = _('Unknown');
}
if ($att1) echo "<tr><td>"._('Network').":</td><td>$att1</td></tr>";
if ($att2) echo "<tr><td>"._('Health').":</td><td>$att2</td></tr>";
if ($att3) echo "<tr><td>"._('Security').":</td><td>$att3</td></tr>";
echo "<tr><td>"._('Network name').":</td><td>$network</td></tr>";
echo "<tr><td>"._('Signal level').":</td><td>$signal</td></tr>";
echo "<tr><td>"._('Receive bitrate').":</td><td>$rxrate</td></tr>";
echo "<tr><td>"._('Transmit bitrate').":</td><td>$txrate</td></tr>";
} else {
$link = _(ucfirst(exec("ethtool ".escapeshellarg($eth)." 2>/dev/null | awk '$1==\"Link\" {print $3;exit}'")) ?: 'Unknown')." ("._(exec("ethtool ".escapeshellarg($eth)." 2>/dev/null | grep -Pom1 '^\s+Port: \K.*'") ?: 'not present').")";
$speed = _(preg_replace(['/^(\d+)/','/!/'],['$1 ',''],exec("ethtool ".escapeshellarg($eth)." 2>/dev/null | awk '$1==\"Speed:\" {print $2;exit}'")) ?: 'Unknown');
echo "<tr><td>"._('Interface link').":</td><td>$link</td></tr>";
echo "<tr><td>"._('Interface speed').":</td><td>$speed</td></tr>";
}
if (count($ipv4)) foreach ($ipv4 as $ip) {
echo "<tr><td>"._('IPv4 address').":</td><td>$ip</td></tr>";

View File

@@ -27,7 +27,7 @@ case 'Add Route':
break;
default:
exec("ip -4 route show table all|grep -Pv '^(127\\.0\\.0\\.0)|table local|unreachable'",$ipv4);
exec("ip -6 route show table all|grep -Pv '^([am:]|(f[ef][0-9][0-9])::)|expires|table local|unreachable'",$ipv6);
exec("ip -6 route show table all|grep -Pv '^([am:]|(f[ef][0-9][0-9])::)|table local|unreachable'",$ipv6);
foreach ($ipv4 as $info) {
$cell = explode(' ',$info);
$route = $cell[0];

View File

@@ -20,7 +20,7 @@ $tmp = '/var/tmp/attr';
$wifi = is_readable($cfg) ? (array)parse_ini_file($cfg,true) : [];
$attr = is_readable($tmp) ? (array)parse_ini_file($tmp,true) : [];
$md5 = md5(json_encode($attr),true);
$cmd = $_POST['cmd'];
$cmd = $_POST['cmd'] ?? '';
$masks = [
'255.0.0.0' => '8', '255.255.0.0' => '16', '255.255.128.0' => '17', '255.255.192.0' => '18',
'255.255.224.0' => '19', '255.255.240.0' => '20', '255.255.248.0' => '21', '255.255.252.0' => '22',
@@ -74,14 +74,27 @@ function saveAttr() {
switch ($cmd) {
case 'list':
$load = $_POST['load'] ?? false;
$title = _('Connect to WiFi network');
$port = array_key_first($wifi);
$carrier = "/sys/class/net/$port/carrier";
$wlan = scanWifi($port);
$echo = [];
$index = 0;
if ($load && count(array_keys($wifi)) > 1) {
foreach ($wifi as $network => $block) {
if ($network == $port) continue;
$wlan[$index]['bss'] = $block['ATTR1'];
$wlan[$index]['signal'] = $block['ATTR2'];
$wlan[$index]['security'] = $block['ATTR3'] ?? $block['SECURITY'];
$wlan[$index]['ssid'] = $network;
$index++;
}
$index = 0;
} else {
$wlan = scanWifi($port);
}
if (count(array_column($wlan,'ssid'))) {
$up = file_exists($carrier) && file_get_contents($carrier)==1;
$up = is_readable($carrier) && file_get_contents($carrier)==1;
$alive = $up ? exec("iw ".escapeshellarg($port)." link 2>/dev/null | grep -Pom1 'SSID: \K.+'") : '';
$state = $up ? _('Connected') : _('Disconnected');
$color = $up ? 'blue' : 'red';
@@ -106,7 +119,7 @@ case 'list':
}
if (empty($echo['active'])) $echo['active'][] = "<dl><dt>"._('Connected').":</dt><dd>"._('None')."</dd>";
if (empty($echo['saved'])) $echo['saved'][] = "<dl><dt>"._('My networks').":</dt><dd>"._('None')."</dd>";
if (empty($echo['other'])) $echo['other'][] = "<dl><dt>"._('Other networks').":</dt><dd>"._('None')."</dd>";
if (empty($echo['other'])) $echo['other'][] = $load ? "" : "<dl><dt>"._('Other networks').":</dt><dd>"._('None')."</dd>";
$echo['active'] = implode($echo['active']);
$echo['saved'] = implode($echo['saved']);
$echo['other'] = implode($echo['other']);
@@ -133,7 +146,7 @@ case 'join':
$dns6 = _var($wifi[$ssid],'DNS6','no');
$ip6 = _var($wifi[$ssid],'IP6');
$mask6 = _var($wifi[$ssid],'MASK6','64');
$gwv6 = _var($wifi[$ssid],'GATEWAY6');
$gw6 = _var($wifi[$ssid],'GATEWAY6');
$server6 = _var($wifi[$ssid],'SERVER6');
$safe = _var($wifi[$ssid],'SECURITY');
$attr1 = $attr[$ssid]['ATTR1'];

View File

@@ -270,6 +270,6 @@ function check_network_connectivity(): bool {
function lan_port($port, $state=false) {
$system = '/sys/class/net';
$exist = file_exists("$system/$port");
return !$state ? $exist : ($exist ? file_get_contents("$system/$port/carrier") : false);
return !$state ? $exist : ($exist ? (@file_get_contents("$system/$port/carrier") ?: 0) : false);
}
?>

View File

@@ -53,10 +53,12 @@ while (true) {
$locale_init = _var($display,'locale');
update_translation($locale_init);
}
if (file_exists($ini) && file_exists($wlan0)) {
if (is_readable($ini) && is_readable($wlan0)) {
$wifi = parse_ini_file($ini);
$up = file_get_contents($wlan0)==1;
$echo['color'] = $up ? 'blue-text' : 'red-text';
$echo['title'] = $up ? _('WiFi connected') : _('WiFi disconnected');
$alive = $up ? exec("iw wlan0 link 2>/dev/null | grep -Pom1 'SSID: \K.+'") : '';
$echo['color'] = $alive==$wifi['SSID'] ? 'blue-text' : 'red-text';
$echo['title'] = $alive==$wifi['SSID'] ? _('WiFi connected') : _('WiFi disconnected');
} else {
$echo['color'] = 'grey-text';
$echo['title'] = _('No active WiFi');

View File

@@ -26,7 +26,7 @@ $cfg = '/boot/config/network.cfg';
function port($x) {
$sys = "/sys/class/net";
return file_exists("$sys/br{$x}") ? "br${x}" : (file_exists("$sys/bond{$x}") ? "bond{$x}" : "eth{$x}");
return file_exists("$sys/br{$x}") ? "br{$x}" : (file_exists("$sys/bond{$x}") ? "bond{$x}" : "eth{$x}");
}
function update_wireguard($ifname) {

View File

@@ -211,9 +211,9 @@ case 'add':
$noBrowser = true;
break;
case 'l':
$nginx = parse_ini_file('/var/local/emhttp/nginx.ini');
$nginx = (array)@parse_ini_file('/var/local/emhttp/nginx.ini');
$link = $value;
$fqdnlink = (strpos($link,"http") === 0) ? $link : $nginx['NGINX_DEFAULTURL'].$link;
$fqdnlink = (strpos($link,"http") === 0) ? $link : ($nginx['NGINX_DEFAULTURL']??'').$link;
break;
}
}

View File

@@ -28,10 +28,10 @@ if ($arg == 'yes') {
} elseif ($arg == 'no') {
exec("/etc/rc.d/rc.wireless stop");
exec("$docroot/webGui/scripts/update_services 5");
} else {
} elseif (($wifi['wlan0']['WIFI']??'') == 'yes') {
foreach ($wifi as $network => $block) {
if ($network == $port) continue;
if ($block['GROUP'] == $state && (!$arg || $arg == $network)) {
if (($block['GROUP']??'') == $state && (!$arg || $arg == $network)) {
$text[] = "SSID=\"$network\"";
unset($block['GROUP']);
foreach ($block as $key => $value) $text[] = "$key=\"$value\"";

View File

@@ -3,3 +3,4 @@ td.gap{padding-left:26px!important}
td.wrap{white-space:normal!important}
span#pass{display:none;margin-left:20px}
input[type=checkbox]{margin-left:0}
.hidden{display:none}

View File

@@ -438,7 +438,7 @@ docker_network_start(){
if [[ $DOCKER_ALLOW_ACCESS == yes && -n $IPV4 ]]; then
# create shim interface and copy parent IPv4 address to shim interface
[[ -e $SYSTEM/$LINK ]] || run ip link add link $NETWORK name $LINK type $ATTACH mode $MODE
run ip addr flush dev $LINK
run ip addr flush dev $LINK scope global
run ip -4 addr add $IPV4 dev $LINK metric 0
# disable IPv6 on shim interface
echo 1 >$CONF6/$LINK/disable_ipv6
@@ -464,13 +464,19 @@ docker_network_start(){
fi
elif [[ $TYPE != wlan ]]; then
if [[ $DOCKER_ALLOW_ACCESS == yes && -n $IPV4 ]]; then
run ip addr flush dev $VHOST
run ip addr flush dev $VHOST scope global
# copy IPv4 address to vhost interface
run ip -4 addr add $IPV4 dev $VHOST metric 0
log "prepared network $VHOST for host access"
elif [[ -e $SYSTEM/$VHOST ]]; then
# remove IP addresses
run ip addr flush dev $VHOST
else
VHOST=vhost${NETWORK//[^0-9.]/}
if [[ -e $SYSTEM/$VHOST ]]; then
# remove IP addresses of vhost
run ip addr flush dev $VHOST scope global
# remove routing of vhost
run ip -4 route flush dev $VHOST
run ip -6 route flush dev $VHOST
fi
fi
fi
fi