diff --git a/emhttp/plugins/dynamix.vm.manager/CloneVM.page b/emhttp/plugins/dynamix.vm.manager/CloneVM.page
deleted file mode 100644
index b74cbccbc..000000000
--- a/emhttp/plugins/dynamix.vm.manager/CloneVM.page
+++ /dev/null
@@ -1,111 +0,0 @@
-Title="Clone VM"
-Tag="clipboard"
-Cond="(pgrep('libvirtd')!==false)"
-Markdown="false"
----
-
-
-// add vm translations (if needed)
-if (substr($_SERVER['REQUEST_URI'],0,4) != '/VMs') {
- $vms = "$docroot/languages/$locale/vms.dot";
- if (file_exists($vms)) $language = array_merge($language,unserialize(file_get_contents($vms)));
-}
-
-?>
-
-
-
-
-
"._('Invalid VM to edit').".
-
-
-
-
-
-
diff --git a/emhttp/plugins/dynamix.vm.manager/include/libvirt_helpers.php b/emhttp/plugins/dynamix.vm.manager/include/libvirt_helpers.php
index 7bf82d5cd..3a2efc8ee 100644
--- a/emhttp/plugins/dynamix.vm.manager/include/libvirt_helpers.php
+++ b/emhttp/plugins/dynamix.vm.manager/include/libvirt_helpers.php
@@ -1454,4 +1454,115 @@ private static $encoding = 'UTF-8';
if ($spicevmc || $qemuvdaagent) $copypaste = true ; else $copypaste = false ;
return $copypaste ;
}
+
+ function vm_clone($vm, $clone ,$overwrite,$start,$edit, $free, $waitID) {
+ global $lv,$domain_cfg ;
+ /*
+ Clone.
+
+ Stopped only.
+
+ Get new VM Name
+ Extract XML for VM to be cloned.
+ Check if directory exists.
+ Check for disk space
+
+ Stop VM Starting until clone is finished or fails.
+
+ Create new directory for Clone.
+ Update paths with new directory
+
+ Create new UUID
+ Create new MAC Address for NICs
+
+ Create VM Disks from source. Options full or Sparce. Method of copy?
+
+ release orginal VM to start.
+
+ If option to edit, show VMUpdate
+ */
+
+ #VM must be shutdown.
+ $res = $lv->get_domain_by_name($vm);
+ $dom = $lv->domain_get_info($res);
+ $state = $lv->domain_state_translate($dom['state']);
+ # if VM running shutdown. Record was running.
+ if ($state != 'shutdown') $arrResponse = $lv->domain_destroy($vm) ;
+ # Wait for shutdown?
+
+
+
+ $disks =$lv->get_disk_stats($vm) ;
+
+ $capacity = 0 ;
+
+ foreach($disks as $disk) {
+ $file = $disk["file"] ;
+ $pathinfo = pathinfo($file) ;
+ $filenew = $pathinfo["dirname"].'/'.$pathinfo["filename"].'.'.$name.'qcow2' ;
+ $diskspec .= " --diskspec '".$disk["device"]."',snapshot=external,file='".$filenew."'" ;
+ $capacity = $capacity + $disk["capacity"] ;
+ }
+ $dirpath = $pathinfo["dirname"] ;
+
+ #Check free space.
+ write("addLog\0".htmlspecialchars("Checking for free space"));
+ $dirfree = disk_free_space($pathinfo["dirname"]) ;
+
+ $capacity *= 1 ;
+
+ #if ($free == "yes" && $dirfree < $capacity) { $arrResponse = ['error' => _("Insufficent Storage for Clone")]; return $arrResponse ;}
+
+ #Clone XML
+ $res = $lv->domain_get_domain_by_uuid($uuid);
+
+ $strXML = $lv->domain_get_xml($res);
+ $uuid = $lv->domain_get_uuid($vm) ;
+ var_dump($uuid) ;
+ $config=domain_to_config($uuid) ;
+
+
+ #$config = array_replace_recursive($arrConfigDefaults, domain_to_config($uuid));
+ #$config = domain_to_config($uuid);
+ $config["domain"]["name"] = $clone ;
+ $config["domain"]["uuid"] = $lv->domain_generate_uuid() ;
+ $config["nic"]["0"]["mac"] = $lv->generate_random_mac_addr() ;
+ $config["domain"]["type"] = "kvm";
+
+
+ $files_exist = false ;
+ foreach ($config["disk"] as $diskid => $disk) {
+ $config["disk"][$diskid]["new"] = str_replace($name,$clonename,$config["disk"][$diskid]["new"]) ;
+ #var_dump(pathinfo($config["disk"][$diskid]["new"])) ;
+ $pi = pathinfo($config["disk"][$diskid]["new"]) ;
+ $isdir = is_dir($pi['dirname']) ;
+ if (is_file($config["disk"][$diskid]["new"])) $file_exists = true ;
+ #var_dump($isdir,$pi['dirname']) ;
+ }
+
+ $clonedir = $domain_cfg['DOMAINDIR'].$clone ;
+ #write("addLog\0".htmlspecialchars("Overwrite $overwrite Start $start Edit $edit Check Freespace $free"));
+ write("addLog\0".htmlspecialchars("Checking for image files"));
+ #if ($file_exists && $overwrite != "yes") { $arrResponse = ['error' => _("New image file names exist and Overwrite is no")]; return $arrResponse ;}
+
+ write("addLog\0".htmlspecialchars("Creating new XML $clone"));
+ $xml = $lv->config_to_xml($config) ;
+ file_put_contents("/tmp/xml" ,$xml) ;
+
+ foreach($disks as $disk) {
+ $cmdstr = "ls" ;
+ $error = execCommand_nchan($cmdstr,$path) ;
+ if (!$error) {
+ $arrResponse = ['error' => substr($output[0],6) ] ;
+ return($arrResponse) ;
+ } else {
+ $arrResponse = ['success' => true] ;
+ }
+
+ }
+ $arrResponse = ['error' => _("Insufficent Storage for Clone")];
+ return$arrResponse ;
+
+ }
+
?>
diff --git a/emhttp/plugins/dynamix.vm.manager/javascript/vmmanager.js b/emhttp/plugins/dynamix.vm.manager/javascript/vmmanager.js
index 15706b2c7..ab393079c 100644
--- a/emhttp/plugins/dynamix.vm.manager/javascript/vmmanager.js
+++ b/emhttp/plugins/dynamix.vm.manager/javascript/vmmanager.js
@@ -2,41 +2,6 @@ function displayconsole(url) {
window.open(url, '_blank', 'scrollbars=yes,resizable=yes');
}
-function getCloneName(name){
- var root = "" ;
- var match= ".iso" ;
- var box = $("#dialogWindow");
- box.html($("#templateClone").html());
-
- box.find('#VMBeingCloned').html(name).change() ;
-
- var height = 100;
- box.dialog({
- title: "Enter Clone Name",
- 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 = '';
- 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 downloadFile(source) {
var a = document.createElement('a');
a.setAttribute('href',source);
@@ -182,25 +147,12 @@ function addVMContext(name, uuid, template, state, vmrcurl, vmrcprotocol, log, c
opts.push({text:_("Logs"), icon:"fa-navicon", action:function(e){e.preventDefault(); openTerminal('log',name,log);}});
}
opts.push({text:_("Edit"), icon:"fa-pencil", href:path+'/UpdateVM?uuid='+uuid});
- opts.push({text:_("Clone2"), icon:"fa-clone", href:path+'/CloneVM?uuid='+uuid});
if (state == "shutoff") {
opts.push({text:_("Clone"), icon:"fa-clone", action:function(e) {
e.preventDefault();
- var clonename = getCloneName(name) ;
- /*swal({
- title:_("Enter"),
- text:_("From VM:")+name,
- type:"warning",
- showCancelButton:true,
- confirmButtonText:_('Proceed'),
- cancelButtonText:_('Cancel')
- },function(){
- $('#vm-'+uuid).find('i').removeClass('fa-play fa-square fa-pause').addClass('fa-refresh fa-spin');
- ajaxVMDispatch({action:"domain-clone", uuid:uuid }, "loadlist");
- }) ;*/
-
+ var clonename = VMClone(uuid,name) ;
}});
opts.push({divider:true});
@@ -280,3 +232,95 @@ function addVM() {
if (x!=-1) path = path.substring(0,x);
location = path+"/VMTemplates";
}
+
+
+function getCloneName(uuid,name){
+ var root = "" ;
+ var match= ".iso" ;
+ var box = $("#dialogWindow");
+ box.html($("#templateClone").html());
+
+ box.find('#VMBeingCloned').html(name).change() ;
+
+ var height = 100;
+ box.dialog({
+ title: "Enter Clone Name",
+ resizable: false,
+ width: 600,
+ height: 300,
+ modal: true,
+ show: {effect:'fade', duration:250},
+ hide: {effect:'fade', duration:250},
+ buttons: {
+ "Clone": function(){
+ var target = box.find('#target');
+ if (target.length) {
+ target = target.val();
+ if (!target ) {errorTarget(); return;}
+ } else target = '';
+ box.find('#target').prop('disabled',true);
+ ajaxVMDispatch({action:"domain-clone", uuid:uuid , clone:target}, "loadlist"); ;
+ box.dialog('close');
+ },
+ "Cancel": function(){
+ box.dialog('close');
+ }
+ }
+ });
+ dialogStyle();
+}
+
+function VMClone(uuid, name){
+
+ //var root = = '"'.$domain_cfg["MEDIADIR"].'"';?>;
+ var match= ".iso";
+ var box = $("#dialogWindow");
+ box.html($("#templateblock").html());
+ var height = 200;
+ box.html($("#templateClone").html());
+
+ box.find('#VMBeingCloned').html(name).change() ;
+
+ //document.getElementById("targetsnaprmv").checked = true ;
+ //document.getElementById("targetsnaprmvmeta").checked = true ;
+ //document.getElementById("targetsnapkeep").checked = true ;
+ //document.getElementById("targetsnapfspc").checked = true ;
+
+ box.dialog({
+ title: "_(VM Clone)_",
+ resizable: false,
+ width: 600,
+ height: 500,
+ modal: true,
+ show: {effect:'fade', duration:250},
+ hide: {effect:'fade', duration:250},
+ 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') ;
+
+
+ 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") ;
+ box.dialog('close');
+ },
+ "_(Cancel)_": function(){
+ box.dialog('close');
+ }
+ }
+ });
+ dialogStyle();
+}
\ No newline at end of file
diff --git a/emhttp/plugins/dynamix.vm.manager/scripts/VMClone.php b/emhttp/plugins/dynamix.vm.manager/scripts/VMClone.php
new file mode 100644
index 000000000..50d32782d
--- /dev/null
+++ b/emhttp/plugins/dynamix.vm.manager/scripts/VMClone.php
@@ -0,0 +1,90 @@
+#!/usr/bin/php -q
+
+
+$docroot = $docroot ?? $_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp';
+
+require_once "$docroot/webGui/include/Wrappers.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);
+ }
+function execCommand_nchan($command,$idx) {
+ $waitID = mt_rand();
+ [$cmd,$args] = explode(' ',$command,2);
+ write("