Menu="VMs:1"
Title="Virtual Machines"
Tag="columns"
Cond="is_file('/var/run/libvirt/libvirtd.pid')"
Markdown="false"
---
<?PHP
/* 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,
 * as published by the Free Software Foundation.
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 */
?>
<?
$docroot ??= ($_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp');
require_once "$docroot/plugins/dynamix.vm.manager/include/libvirt_helpers.php";
$is_intel_cpu = is_intel_cpu();
$core_types = $is_intel_cpu ? get_intel_core_types() : [];
$themeName = $themeHelper->getThemeName();

$cpus = cpu_list();
$hover   = $themeHelper->isLightTheme() ? 'rgba(0,0,0,0.1)' : 'rgba(255,255,255,0.1)';
$bgcolor = $themeHelper->isLightTheme() ? '#f2f2f2' : '#1c1c1c';
$fgcolor = $themeHelper->isLightTheme() ? '#1c1c1c' : '#f2f2f2';
$incolor = $themeName !== 'gray' ? $bgcolor : '#121510';

function showCPUs($uuid) {
  global $cpus,$is_intel_cpu,$core_types;
  $vm = domain_to_config($uuid);
  $vcpu = $vm['domain']['vcpu'];
  $nopining = "";
  if (!is_array($vcpu)) $nopining = _("No pinning set");
  echo "<div class='four'>";
  foreach ($cpus as $pair) {
    unset($cpu1,$cpu2);
    [$cpu1, $cpu2] = my_preg_split('/[,-]/',$pair);
    $check = ($vcpu && in_array($cpu1, $vcpu)) ? 'fa-circle orange-text':'fa-circle-o';
    if ($is_intel_cpu && count($core_types) > 0) $core_type = "$core_types[$cpu1]"; else $core_type = "";
    if (!$cpu2) {
      echo "<label title='$core_type'><i class='fa fa-fw $check'></i>&nbsp;&nbsp;cpu $cpu1</label>";
    } else {
      echo "<label title='$core_type' class='cpu1'><i class='fa fa-fw $check'></i>&nbsp;&nbsp;cpu $cpu1 / $cpu2</label>";
      $check = ($vcpu && in_array($cpu2, $vcpu)) ? 'fa-circle orange-text':'fa-circle-o';
      echo "<label title='$core_type' class='cpu2'><i class='fa fa-fw $check'></i></label>";
    }
  }
  echo "<br><span>vCPUs: {$vm['domain']['vcpus']} $nopining</span>";
  echo "</div>";
}
function vsize($size,$expand=true) {
  $units = ['','K','M','G','T','P','E','Z','Y'];
  if ($expand) {
    $size = str_replace(['B',' ',','],'',strtoupper($size));
    [$c1,$c2] = my_preg_split('/(?<=[0-9])(?=[A-Z])/',$size);
    return $c1 * pow(1024,array_search($c2,$units)?:0);
  } else {
    $base = $size ? floor(log($size,1024)) : 0;
    return $size/pow(1024,$base).$units[$base];
  }
}

$uuid = unscript(_var($_GET,'uuid'));
$subaction = _var($_GET,'subaction');
if (isset($_GET['refresh'])) {
  $vm = unscript(_var($_GET,'name'));
  if ($lv->domain_is_active($vm)) {
    echo "<meta http-equiv='refresh' content='5; url=/VMs?name=$vm&amp;refresh=true'>";
    $msg = "Waiting for $vm to shutdown...";
  } else {
    $msg = "$vm has been shutdown";
  }
}
if ($subaction) {
  $vm = $lv->domain_get_name_by_uuid($uuid);
  if ($subaction == 'disk-resize') {
    $capacity = vsize($_GET['cap']);
    if ($capacity > vsize($_GET['oldcap'])) {
      shell_exec("qemu-img resize -q ".escapeshellarg(unscript($_GET['disk']??''))." ".vsize($capacity,0));
    $msg = $vm." disk capacity has been changed to {$_GET['cap']}";
    } else {
      $msg = "Error: disk capacity has to be greater than {$_GET['oldcap']}";
    }
  } elseif ($subaction == 'disk-remove') {
    $msg = $lv->domain_disk_remove($vm,_var($_GET,'dev'))
    ? "$vm disk has been removed"
    : "Error: ".$lv->get_last_error();
  } elseif ($subaction == 'snap-create') {
    $msg = $lv->domain_snapshot_create($vm)
    ? "Snapshot for $vm has been created"
    : "Error: ".$lv->get_last_error();
  } elseif ($subaction == 'snap-delete') {
    $msg = $lv->domain_snapshot_delete($vm,_var($_GET,'snap'))
    ? "Snapshot for $vm has been deleted"
    : "Error: ".$lv->get_last_error();
  } elseif ($subaction == 'snap-revert') {
    $msg = $lv->domain_snapshot_revert($vm,_var($_GET,'snap'))
    ? "$vm has been reverted"
    : "Error: ".$lv->get_last_error();
  } elseif ($subaction == 'snap-desc') {
    $msg = $lv->snapshot_set_metadata($vm,_var($_GET,'snap'),_var($_POST,'snapdesc'))
    ? "Snapshot description for $vm has been saved"
    : "Error: ".$lv->get_last_error();
  }
}
if ($libvirt_running=='yes') $vms = $lv->get_domains() ?: [];
if (empty($vms)) {
  $msg = $libvirt_running=='yes'
  ? 'No VMs defined. Create from template or add XML.'
  : 'Libvirt is not running. Goto Settings tab then click Start.';
}
?>
<link type="text/css" rel="stylesheet" href="<?autov('/webGui/styles/jquery.switchbutton.css')?>">
<link type="text/css" rel="stylesheet" href="<?autov("/webGui/styles/jquery.filetree.css")?>">

<script src="<?autov('/webGui/javascript/jquery.switchbutton.js')?>"></script>
<script src="<?autov('/plugins/dynamix.vm.manager/javascript/dynamix.vm.manager.js')?>"></script>
<script src="<?autov('/plugins/dynamix.vm.manager/javascript/vmmanager.js')?>"></script>
<script src="<?autov("/webGui/javascript/jquery.filetree.js")?>"></script>
<script>
function resetSorting() {
  if ($.cookie('lockbutton')==null) return;
  $('input[type=button]').prop('disabled',true);
  $.post('/plugins/dynamix.vm.manager/include/UserPrefs.php',{reset:true},function(){loadlist();});
}
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 box = $("#dialogWindow");
  box.html($("#templateISOboth").html());
  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)_",
    height: 'auto',
    width: 'auto',
    resizable: false,
    modal: true,
    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 box = $("#dialogWindow");
  box.html($("#templateISO").html());
  box.find('#target').attr('value',file).fileTreeAttach(null,null,function(path){
    box.find('#target').val(path).change();
  });
  box.dialog({
    title: "_(Select ISO)_",
    height: 'auto',
    width: 'auto',
    resizable: false,
    modal: true,
    buttons: {
      "_(Insert)_": function(){
        var target = box.find('#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");
        box.dialog('close');
      },
      "_(Cancel)_": function(){
        box.dialog('close');
      }
    }
  });
  dialogStyle();
}
function VMClone(uuid, name){
  var box = $("#dialogWindow");
  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;
  overwrite = box.find("#Overwrite");
  overwrite.attr("checked:true");
  box.dialog({
    title: "_(VM Clone)_",
    height: 'auto',
    width: 600,
    resizable: false,
    modal: true,
    buttons: {
      "_(Clone)_": function(){
        var target = box.find('#target');
        if (target.length) {
          target = target.val();
          //if (!target) {errorTarget(); return;}
        } else target = '';
        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';
        var regenmac = box.find('#Regenmac').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, regenmac:regenmac}));
        openVMAction((scripturl),"VM Clone", "dynamix.vm.manager", "loadlist");
        box.dialog('close');
      },
      "_(Cancel)_": function(){
        box.dialog('close');
      }
    }
  });
  dialogStyle();
}
function selectsnapshot(uuid, name ,snaps, opt, getlist,state ,fstype){
  var box = $("#dialogWindow");
  box.html($("#templatesnapshot"+opt).html());
  const capopt = opt.charAt(0).toUpperCase() + opt.slice(1);
  var optiontext = capopt + " _(Snapshot)_";
  box.find('#VMName').html(name);
  box.find('#fstype').html(fstype);
  if (fstype == "QEMU") box.find('#fstypeline').prop('hidden',true);
  box.find('#targetsnap').val(snaps);
  box.find('#targetsnapl').html(snaps);
  if (getlist) {
    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');
  }
  var memorydump = "no";
  document.getElementById("targetsnaprmv").checked = true;
  document.getElementById("targetsnaprmvmeta").checked = true;
  document.getElementById("targetsnapkeep").checked = true;
  document.getElementById("targetsnapfspc").checked = true;
  if (fstype == "ZFS") {
    box.find('#targetsnaprmv').prop('disabled',true);
    box.find('#targetsnaprmvmeta').prop('disabled',true);
  }
  if (state != "running") {
    box.find('#memoryline').prop('hidden',true);
    box.find('#targetsnapmem').prop('hidden',true);
    box.find('#targetsnapmem').prop('checked',false);
  } else {
    box.find('#memoryline').prop('hidden',false);
    box.find('#targetsnapmem').prop('hidden',false);
    box.find('#targetsnapmem').prop('checked',true);
  }
  box.dialog({
    title: optiontext,
    height: 'auto',
    width: 600,
    resizable: false,
    modal: true,
    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") {
          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") {
          free = box.find('#targetsnapfspc').prop('checked') ? 'yes' : 'no';
          fstypeuse = box.find('#targetsnapfstype').prop('checked') ? 'yes' : 'no';
          memorydump = box.find('#targetsnapmem').prop('checked') ? 'yes' : 'no';
          if (fstypeuse == "no") fstype ="QEMU";
          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, fstype:fstype,memorydump:memorydump}, "loadlist");
        box.dialog('close');
      },
      "_(Cancel)_": function(){
        box.dialog('close');
      }
    }
  });
  dialogStyle();
}
function selectblock(uuid, name, snaps, opt, getlist, state){
  var box = $("#dialogWindow");
  box.html($("#templateblock").html());
  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,
    height: 'auto',
    width: 600,
    resizable: false,
    modal: true,
    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") {
          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');
        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(){
        box.dialog('close');
      }
    }
  });
  dialogStyle();
}
var sortableHelper = function(e,ui){
  var child = ui.next();
  if (child.is(':visible')) child.addClass('unhide').hide();
  ui.children().each(function(){$(this).width($(this).width());});
  return ui;
};
function LockButton() {
  if ($.cookie('lockbutton')==null) {
    $.cookie('lockbutton','lockbutton');
    $('#resetsort').removeClass('nohand').addClass('hand');
    $('i.mover').show();
    $('#kvm_list .sortable').css({'cursor':'move'});
<?if ($themeHelper->isTopNavTheme()):?>
    $('div.nav-item.LockButton a').prop('title',"_(Lock sortable items)_");
    $('div.nav-item.LockButton b').removeClass('icon-u-lock green-text').addClass('icon-u-lock-open red-text');
<?endif;?>
    $('div.nav-item.LockButton span').text("_(Lock sortable items)_");
    $('#kvm_list').sortable({helper:sortableHelper,items:'.sortable',cursor:'grab',axis:'y',containment:'parent',delay:100,opacity:0.5,zIndex:9999,forcePlaceholderSize:true,
    update:function(e,ui){
      $('#kvm_list .sortable').each(function(){
        var parent = $(this).attr('parent-id');
        var child = $('tr[child-id="'+parent+'"]');
        child.detach().insertAfter($(this));
        if (child.hasClass('unhide')) child.removeClass('unhide').show();
      });
      var row = $('#kvm_list tr:first');
      var names = '', index = '';
      row.parent().children().find('td.vm-name').each(function(){names+=$(this).find('a').text()+';';index+=$(this).parent().parent().children().index($(this).parent())+';';});
      $.post('/plugins/dynamix.vm.manager/include/UserPrefs.php',{names:names,index:index});
    }});
  } else {
    $.removeCookie('lockbutton');
    $('#resetsort').removeClass('hand').addClass('nohand');
    $('i.mover').hide();
    $('#kvm_list .sortable').css({'cursor':'default'});
<?if ($themeHelper->isTopNavTheme()):?>
    $('div.nav-item.LockButton a').prop('title',"_(Unlock sortable items)_");
    $('div.nav-item.LockButton b').removeClass('icon-u-lock-open red-text').addClass('icon-u-lock green-text');
<?endif;?>
    $('div.nav-item.LockButton span').text("_(Unlock sortable items)_");
    $('#kvm_list').sortable('destroy');
  }
}
function loadlist() {
  timers.vm = setTimeout(function(){$('div.spinner.fixed').show('slow');},500);
  $.get('/plugins/dynamix.vm.manager/include/VMMachines.php',{show:$.cookie('vmshow')},function(d) {
    clearTimeout(timers.vm);
    var data = d.split(/\0/);
    $('#kvm_list').html(data[0]);
    $('head').append('<script>'+data[1]+'<\/script>');
<?foreach ($vms as $vm) {
  $res = $lv->get_domain_by_name($vm);
  $uuid = $lv->domain_get_uuid($res);
?>  $('.vcpu-<?=$uuid?>').tooltipster({
      trigger:'custom',
      triggerOpen:{mouseenter:true,click:true,touchstart:true},
      contentAsHTML:true,
      animation:'grow',
      triggerClose:{click:true,scroll:true,mouseleave:true,delay:1},
      interactive:true,
      viewportAware:true,
      functionBefore:function(instance,helper){instance.content("<?=showCPUs($uuid)?>");}
    });
<?}?>
    $('.autostart').switchButton({labels_placement:'right', on_label:"_(On)_", off_label:"_(Off)_"});
    $('.autostart').change(function() {
      $.post('/plugins/dynamix.vm.manager/include/VMajax.php',{action:'domain-autostart',uuid:$(this).attr('uuid'),autostart:$(this).prop('checked'),response:'json'},function(data){
        $(this).prop('checked', data.autostart);
      },'json');
    });
    $('div.spinner.fixed').hide('slow');
    $('input[type=button]').prop('disabled',false).show('slow');
    $('.text').click(showInput);
    $('.input').blur(hideInput);
    <?if (_var($display,'resize')):?>
      fillAvailableHeight({
        targetElementSelector: '.js-fill-available-height',
        elementSelectorsForHeight: [
          '.js-actions',
          '#kvm_table thead',
        ],
        elementSelectorsForSpacing: [
          '#kvm_table',
        ],
        manualSpacingOffset: 30, // without this, the main content will still be scrollable by like 20px
      });
      // Handle table header fixed positioning after resize
      function tableHeaderResize() {
        $('#kvm_table thead,#kvm_table tbody').removeClass('fixed');
        $('#kvm_table thead tr th').each(function(){$(this).width($(this).width());});
        $('#kvm_table tbody tr td').each(function(){$(this).width($(this).width());});
        $('#kvm_table thead,#kvm_table tbody').not('.child').addClass('fixed');
      }
      tableHeaderResize();
      $(window).bind('resize',function(){
        tableHeaderResize();
      });
  <?endif;?>
  });
}
$(function() {
<?if ($msg):?>
  <?$color = strpos($msg, "rror:")!==false ? 'red-text':'green-text'?>
  $('#countdown').html("<span class='<?=$color?>'><?=_($msg)?></span>");
<?endif;?>
  $('#btnAddVM').click(function AddVMEvent(){$('.tab>input#tab2').click();});
  $.removeCookie('lockbutton');
  loadlist();
});
</script>

<div class="TableContainer">
    <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" class="js-fill-available-height"><tr><td colspan='8'></td></tr></tbody>
    </table>
</div>

<div class="js-actions">
  <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>

<div id="dialogWindow"></div>
<div id="iframe-popup"></div>

<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 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="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>
<tr id="memoryline"><td>_(Memory dump)_:</td><td><input type="checkbox" id="targetsnapmem"  checked></td></tr>
<tr id="fstypeline"><td>_(FS Native Snapshot)_:</td><td><label id="fstype"></label><input type="checkbox" id="targetsnapfstype">_(Unchecked will use QEMU External Snapshot)_</td></tr>
</table>
</div>

<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>
<tr id="fstypeline"><td>_(Snapshot Method)_:</td><td><label id="fstype"></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>

<div id="templatesnapshotremove" class="template">
<h3>!! _(Warning removing Snapshots can break the chain)_ !!</h3>

_(VM Name)_: <label id="VMName"></label><br>
_(Snapshot Name)_: <input type="text" id="targetsnap" hidden><label id="targetsnapl"></label><label id="targetsnapimages"></label>
</div>

<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="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="" checked></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>_(Regenerate MAC addresses)_:</td><td><input type="checkbox" id="Regenmac" value="" checked ></td></tr>
<tr><td>_(Check free space)_:</td><td><input type="checkbox" id="Free" value="" checked></td></tr>
</table>
</div>
