VM edit corrections

- create image when new vdisk is added
- keep sound card selection included
- fix add/remove of network interfaces
This commit is contained in:
bergware
2018-09-15 13:24:00 +02:00
parent 869d04306f
commit 968df19f40
5 changed files with 83 additions and 30 deletions
@@ -1085,6 +1085,20 @@
];
}
function create_vdisk(&$new) {
global $lv;
$index = 0;
foreach ($new['disk'] as $i => $disk) {
$index++;
if ($disk['new']) {
$disk = $lv->create_disk_image($disk, $new['domain']['name'], $index);
if ($disk['error']) return $disk['error'];
$new['disk'][$i] = $disk;
}
}
return false;
}
function array_update_recursive(&$old, &$new) {
$hostold = $old['devices']['hostdev']; // existing devices including custom settings
$hostnew = $new['devices']['hostdev']; // GUI generated devices
@@ -1115,7 +1129,8 @@
// update parent arrays
if (!$old['devices']['hostdev']) unset($old['devices']['hostdev']);
if (!$new['devices']['hostdev']) unset($new['devices']['hostdev']);
unset($old['cputune']['vcpupin'],$old['devices']['graphics'],$old['devices']['video'],$old['devices']['disk']);
// remove existing auto-generated settings
unset($old['cputune']['vcpupin'],$old['devices']['graphics'],$old['devices']['video'],$old['devices']['disk'],$old['devices']['interface']);
// set namespace
$new['metadata']['vmtemplate']['@attributes']['xmlns'] = 'unraid';
}
@@ -201,11 +201,16 @@ $hdrXML = "<?xml version='1.0' encoding='UTF-8'?>\n"; // XML encoding declaratio
$xml = $_POST['xmldesc'];
} else {
// form view
$arrExistingConfig = custom::createArray('domain',$strXML);
$arrUpdatedConfig = custom::createArray('domain',$lv->config_to_xml($_POST));
array_update_recursive($arrExistingConfig, $arrUpdatedConfig);
$arrConfig = array_replace_recursive($arrExistingConfig, $arrUpdatedConfig);
$xml = custom::createXML('domain',$arrConfig)->saveXML();
if ($error = create_vdisk($_POST) === false) {
$arrExistingConfig = custom::createArray('domain',$strXML);
$arrUpdatedConfig = custom::createArray('domain',$lv->config_to_xml($_POST));
array_update_recursive($arrExistingConfig, $arrUpdatedConfig);
$arrConfig = array_replace_recursive($arrExistingConfig, $arrUpdatedConfig);
$xml = custom::createXML('domain',$arrConfig)->saveXML();
} else {
echo json_encode(['error' => $error]);
exit;
}
}
// delete and create the VM
$lv->nvram_backup($uuid);
@@ -232,7 +237,7 @@ $hdrXML = "<?xml version='1.0' encoding='UTF-8'?>\n"; // XML encoding declaratio
$boolRunning = $lv->domain_get_state($dom)=='running';
$strXML = $lv->domain_get_xml($dom);
$boolNew = false;
$arrConfig = domain_to_config($uuid);
$arrConfig = array_replace_recursive($arrConfigDefaults, domain_to_config($uuid));
} else {
// edit new VM
$boolRunning = false;
@@ -1418,6 +1423,7 @@ $(function() {
$("#vmform .formview #btnSubmit").click(function frmSubmit() {
var $button = $(this);
var $panel = $('.formview');
var form = $button.closest('form');
$("#vmform .disk_select option:selected").not("[value='manual']").closest('table').each(function () {
var v = $(this).find('.disk_preview').html();
@@ -1428,24 +1434,34 @@ $(function() {
<?if (!$boolNew):?>
// signal devices to be added or removed
$button.closest('form').find('input[name="usb[]"],input[name="pci[]"]').each(function(){
form.find('input[name="usb[]"],input[name="pci[]"]').each(function(){
if (!$(this).prop('checked')) $(this).prop('checked',true).val($(this).val()+'#remove');
});
// remove unused graphic cards
var gpus = [], i = 0;
do {
var gpu = $button.closest('form').find('select[name="gpu['+(i++)+'][id]"] option:selected').val();
var gpu = form.find('select[name="gpu['+(i++)+'][id]"] option:selected').val();
if (gpu) gpus.push(gpu);
} while (gpu);
$button.closest('form').find('select[name="gpu[0][id]"] option').each(function(){
form.find('select[name="gpu[0][id]"] option').each(function(){
var gpu = $(this).val();
if (gpu != 'vnc' && !gpus.includes(gpu)) $('form#vmform').append('<input type="hidden" name="pci[]" value="'+gpu+'#remove">');
if (gpu != 'vnc' && !gpus.includes(gpu)) form.append('<input type="hidden" name="pci[]" value="'+gpu+'#remove">');
});
// remove unused sound cards
var sound = [], i = 0;
do {
var audio = form.find('select[name="audio['+(i++)+'][id]"] option:selected').val();
if (audio) sound.push(audio);
} while (audio);
form.find('select[name="audio[0][id]"] option').each(function(){
var audio = $(this).val();
if (audio && !sound.includes(audio)) form.append('<input type="hidden" name="pci[]" value="'+audio+'#remove">');
});
<?endif?>
var postdata = $button.closest('form').find('input,select').serialize().replace(/'/g,"%27");
<?if (!$boolNew):?>
// keep checkbox visually unchecked
$button.closest('form').find('input[name="usb[]"],input[name="pci[]"]').each(function(){
form.find('input[name="usb[]"],input[name="pci[]"]').each(function(){
if ($(this).val().indexOf('#remove')>0) $(this).prop('checked',false);
});
<?endif?>
@@ -392,7 +392,7 @@ $hdrXML = "<?xml version='1.0' encoding='UTF-8'?>\n"; // XML encoding declaratio
$boolRunning = $lv->domain_get_state($dom)=='running';
$strXML = $lv->domain_get_xml($dom);
$boolNew = false;
$arrConfig = domain_to_config($uuid);
$arrConfig = array_replace_recursive($arrConfigDefaults, domain_to_config($uuid));
} else {
// edit new VM
$boolRunning = false;
@@ -1116,29 +1116,40 @@ $(function() {
$("#vmform .formview #btnSubmit").click(function frmSubmit() {
var $button = $(this);
var $panel = $('.formview');
var form = $button.closest('form');
$panel.find('input').prop('disabled', false); // enable all inputs otherwise they wont post
<?if (!$boolNew):?>
// signal devices to be added or removed
$button.closest('form').find('input[name="usb[]"],input[name="pci[]"]').each(function(){
form.find('input[name="usb[]"],input[name="pci[]"]').each(function(){
if (!$(this).prop('checked')) $(this).prop('checked',true).val($(this).val()+'#remove');
});
// remove unused graphic cards
var gpus = [], i = 0;
do {
var gpu = $button.closest('form').find('select[name="gpu['+(i++)+'][id]"] option:selected').val();
var gpu = form.find('select[name="gpu['+(i++)+'][id]"] option:selected').val();
if (gpu) gpus.push(gpu);
} while (gpu);
$button.closest('form').find('select[name="gpu[0][id]"] option').each(function(){
form.find('select[name="gpu[0][id]"] option').each(function(){
var gpu = $(this).val();
if (gpu != 'vnc' && !gpus.includes(gpu)) $('form#vmform').append('<input type="hidden" name="pci[]" value="'+gpu+'#remove">');
if (gpu != 'vnc' && !gpus.includes(gpu)) form.append('<input type="hidden" name="pci[]" value="'+gpu+'#remove">');
});
// remove unused sound cards
var sound = [], i = 0;
do {
var audio = form.find('select[name="audio['+(i++)+'][id]"] option:selected').val();
if (audio) sound.push(audio);
} while (audio);
form.find('select[name="audio[0][id]"] option').each(function(){
var audio = $(this).val();
if (audio && !sound.includes(audio)) form.append('<input type="hidden" name="pci[]" value="'+audio+'#remove">');
});
<?endif?>
var postdata = $button.closest('form').find('input,select').serialize().replace(/'/g,"%27");
var postdata = form.find('input,select').serialize().replace(/'/g,"%27");
<?if (!$boolNew):?>
// keep checkbox visually unchecked
$button.closest('form').find('input[name="usb[]"],input[name="pci[]"]').each(function(){
form.find('input[name="usb[]"],input[name="pci[]"]').each(function(){
if ($(this).val().indexOf('#remove')>0) $(this).prop('checked',false);
});
<?endif?>
@@ -394,7 +394,7 @@ $hdrXML = "<?xml version='1.0' encoding='UTF-8'?>\n"; // XML encoding declaratio
$boolRunning = $lv->domain_get_state($dom)=='running';
$strXML = $lv->domain_get_xml($dom);
$boolNew = false;
$arrConfig = domain_to_config($uuid);
$arrConfig = array_replace_recursive($arrConfigDefaults, domain_to_config($uuid));
} else {
// edit new VM
$boolRunning = false;
@@ -1118,29 +1118,40 @@ $(function() {
$("#vmform .formview #btnSubmit").click(function frmSubmit() {
var $button = $(this);
var $panel = $('.formview');
var form = $button.closest('form');
$panel.find('input').prop('disabled', false); // enable all inputs otherwise they wont post
<?if (!$boolNew):?>
// signal devices to be added or removed
$button.closest('form').find('input[name="usb[]"],input[name="pci[]"]').each(function(){
form.find('input[name="usb[]"],input[name="pci[]"]').each(function(){
if (!$(this).prop('checked')) $(this).prop('checked',true).val($(this).val()+'#remove');
});
// remove unused graphic cards
var gpus = [], i = 0;
do {
var gpu = $button.closest('form').find('select[name="gpu['+(i++)+'][id]"] option:selected').val();
var gpu = form.find('select[name="gpu['+(i++)+'][id]"] option:selected').val();
if (gpu) gpus.push(gpu);
} while (gpu);
$button.closest('form').find('select[name="gpu[0][id]"] option').each(function(){
form.find('select[name="gpu[0][id]"] option').each(function(){
var gpu = $(this).val();
if (gpu != 'vnc' && !gpus.includes(gpu)) $('form#vmform').append('<input type="hidden" name="pci[]" value="'+gpu+'#remove">');
if (gpu != 'vnc' && !gpus.includes(gpu)) form.append('<input type="hidden" name="pci[]" value="'+gpu+'#remove">');
});
// remove unused sound cards
var sound = [], i = 0;
do {
var audio = form.find('select[name="audio['+(i++)+'][id]"] option:selected').val();
if (audio) sound.push(audio);
} while (audio);
form.find('select[name="audio[0][id]"] option').each(function(){
var audio = $(this).val();
if (audio && !sound.includes(audio)) form.append('<input type="hidden" name="pci[]" value="'+audio+'#remove">');
});
<?endif?>
var postdata = $button.closest('form').find('input,select').serialize().replace(/'/g,"%27");
var postdata = form.find('input,select').serialize().replace(/'/g,"%27");
<?if (!$boolNew):?>
// keep checkbox visually unchecked
$button.closest('form').find('input[name="usb[]"],input[name="pci[]"]').each(function(){
form.find('input[name="usb[]"],input[name="pci[]"]').each(function(){
if ($(this).val().indexOf('#remove')>0) $(this).prop('checked',false);
});
<?endif?>