Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

VM Snapshots #1331

Closed
wants to merge 20 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
292 changes: 290 additions & 2 deletions emhttp/plugins/dynamix.vm.manager/VMMachines.page
Expand Up @@ -18,6 +18,7 @@ Markdown="false"
*/
?>
<?
$docroot = $docroot ?? $_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp';
require_once "$docroot/plugins/dynamix.vm.manager/include/libvirt_helpers.php";

$cpus = cpu_list();
Expand Down Expand Up @@ -121,6 +122,7 @@ 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}
Expand All @@ -134,7 +136,7 @@ i.mover{margin-right:8px;display:none}
.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)_</th><th>_(Graphics)_</th><th class="th3">_(Autostart)_</th></tr></thead>
<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">
Expand Down Expand Up @@ -163,7 +165,54 @@ function resetSorting() {
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 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.dialog({
title: "Select ISOs for CDROMs",
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 = '';
var target2 = box.find('#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");
box.dialog('close');
},
"_(Cancel)_": function(){
box.dialog('close');
}
}
});
dialogStyle();
}
function getisoimage(uuid,dev,bus,file){
var root = <?= '"'.$domain_cfg["MEDIADIR"].'"';?>;
Expand Down Expand Up @@ -203,8 +252,171 @@ function getisoimage(uuid,dev,bus,file){
});
dialogStyle();
}

function selectsnapshot(uuid, name ,snaps, opt, getlist,state){

var root = <?= '"'.$domain_cfg["MEDIADIR"].'"';?>;
var match= ".iso";
var box = $("#dialogWindow2");
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) ;
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) ;
}
},'json');
}

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,
width: 600,
height: 500,
modal: true,
show: {effect:'fade', duration:250},
hide: {effect:'fade', duration:250},

buttons: {
"_(Proceed)_": 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 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' ;
}
if (opt == "create") {
var x = box.find('#targetsnapfspc').prop('checked') ;
if (x) free = 'yes' ; else free = 'no' ;
var 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");
box.dialog('close');
},
"_(Cancel)_": function(){
box.dialog('close');
}
}
});
dialogStyle();
}

function selectblock(uuid, name ,snaps, opt, getlist,state){

var root = <?= '"'.$domain_cfg["MEDIADIR"].'"';?>;
var match= ".iso";
var box = $("#dialogWindow2");
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 ;
if (getlist) {
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) ;
}
},'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();
}

box.dialog({
title: "_("+optiontext+ ")_",
resizable: false,
width: 600,
height: 500,
modal: true,
show: {effect:'fade', duration:250},
hide: {effect:'fade', duration:250},
buttons: {
_("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 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') ;
}
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") ;
box.dialog('close');
},
"_(Cancel)_": function(){
box.dialog('close');
}
}
});
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',"_(Close)_").prop('onclick',null).off('click').click(function(){box.dialog('close');});
$('.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'});
Expand Down Expand Up @@ -304,5 +516,81 @@ $(function() {
<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>
<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>

<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>
</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>

<label id="targetsnapimages"></label><br>


</div>

<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><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>
</table>
<input type="checkbox" id="targetsnapkeep" hidden><br>
<label id="targetsnapimages"></label><br>
</div>
</div>