Wip update.

This commit is contained in:
SimonFair
2023-07-02 20:45:59 +01:00
parent 5c76b3c850
commit a08452c59e
3 changed files with 91 additions and 75 deletions

View File

@@ -267,7 +267,7 @@
}
function config_to_xml($config) {
function config_to_xml($config,$vmclone = false) {
$domain = $config['domain'];
$media = $config['media'];
$nics = $config['nic'];
@@ -463,19 +463,27 @@
$usbstr = '';
if (!empty($usb)) {
foreach($usb as $i => $v){
$usbx = explode(':', $v);
if ($vmclone) $usbx = explode(':', $v['id']); else $usbx = explode(':', $v);
$startupPolicy = '' ;
if (isset($usbopt[$v])) {
if (isset($usbopt[$v]) && !$vmclone ) {
if (strpos($usbopt[$v], "#remove") == false) $startupPolicy = 'startupPolicy="optional"' ; else $startupPolicy = '' ;
}
}
if ($vmclone ) {
if ($v["startupPolicy"] == "optional" ) $startupPolicy = 'startupPolicy="optional"' ; else $startupPolicy = '' ;
#$startupPolicy = 'startupPolicy="optional"' ;
}
$usbstr .= "<hostdev mode='subsystem' type='usb'>
<source $startupPolicy>
<vendor id='0x".$usbx[0]."'/>
<product id='0x".$usbx[1]."'/>
</source>" ;
if (!empty($usbboot[$v])) {
if (!empty($usbboot[$v]) && !$vmclone ) {
$usbstr .= "<boot order='".$usbboot[$v]."'/>" ;
}
}
if ($vmclone ) {
if ($v["usbboot"] != NULL) $usbstr .= "<boot order='".$v["usbboot"]."'/>" ;
}
$usbstr .= "</hostdev>";
}
}
@@ -857,20 +865,23 @@
if (empty($pci_id) || in_array($pci_id, $pcidevs_used)) {
continue;
}
[$pci_bus, $pci_slot, $pci_function] = my_explode(":", str_replace('.', ':', $pci_id), 3);
if ($vmclone) [$pci_bus, $pci_slot, $pci_function] = my_explode(":", str_replace('.', ':', $pci_id['id']), 3);
else [$pci_bus, $pci_slot, $pci_function] = my_explode(":", str_replace('.', ':', $pci_id), 3);
$pcidevs .= "<hostdev mode='subsystem' type='pci' managed='yes'>
<driver name='vfio'/>
<source>
<address domain='0x0000' bus='0x" . $pci_bus . "' slot='0x" . $pci_slot . "' function='0x" . $pci_function . "'/>
</source>" ;
if (!empty($pciboot[$pci_id])) {
if (!empty($pciboot[$pci_id]) && !$vmclone) {
$pcidevs .= "<boot order='".$pciboot[$pci_id]."'/>" ;
}
if (!empty($pci_id["boot"]) && $vmclone) {
$pcidevs .= "<boot order='".$pci_id["boot"]."'/>" ;
}
$pcidevs .= "</hostdev>";
$pcidevs_used[] = $pci_id;
if ($vmclone) $pcidevs_used[] = $pci_id['d']; else $pcidevs_used[] = $pci_id ;
}
}

View File

@@ -1481,84 +1481,86 @@ private static $encoding = 'UTF-8';
If option to edit, show VMUpdate
*/
$uuid = $lv->domain_get_uuid($clone) ;
write("addLog\0".htmlspecialchars("checking if Clone UUID exists $uuid"));
if ($uuid) { $arrResponse = ['error' => _("Clone VM name already inuse")]; return $arrResponse ;}
#VM must be shutdown.
$res = $lv->get_domain_by_name($vm);
$dom = $lv->domain_get_info($res);
$state = $lv->domain_state_translate($dom['state']);
file_put_contents("/tmp/cloningxml" ,$lv->domain_get_xml($res)) ;
# if VM running shutdown. Record was running.
if ($state != 'shutoff') {write("addLog\0".htmlspecialchars("Shuting down $vm current $state")); $arrResponse = $lv->domain_destroy($vm) ; }
# Wait for shutdown?
$uuid = $lv->domain_get_uuid($clone) ;
write("addLog\0".htmlspecialchars(_("Checking if clone exists")));
if ($uuid) { $arrResponse = ['error' => _("Clone VM name already inuse")]; return $arrResponse ;}
#VM must be shutdown.
$res = $lv->get_domain_by_name($vm);
$dom = $lv->domain_get_info($res);
$state = $lv->domain_state_translate($dom['state']);
$vmxml = $lv->domain_get_xml($res) ;
file_put_contents("/tmp/cloningxml" ,$vmxml) ;
# if VM running shutdown. Record was running.
if ($state != 'shutoff') {write("addLog\0".htmlspecialchars(_("Shuting down $vm current $state"))); $arrResponse = $lv->domain_destroy($vm) ; }
# Wait for shutdown?
$disks =$lv->get_disk_stats($vm) ;
$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' ;
$capacity = $capacity + $disk["capacity"] ;
$capacity = 0 ;
foreach($disks as $disk) {
$file = $disk["file"] ;
$pathinfo = pathinfo($file) ;
$filenew = $pathinfo["dirname"].'/'.$pathinfo["filename"].'.'.$name.'qcow2' ;
$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) { write("addLog\0".htmlspecialchars(_("Insufficent storage for clone"))); return false ;}
#Clone XML
$uuid = $lv->domain_get_uuid($vm) ;
$config=domain_to_config($uuid) ;
$config["domain"]["name"] = $clone ;
$config["domain"]["uuid"] = $lv->domain_generate_uuid() ;
foreach($config["nic"] as $index => $detail) {
$config["nic"][$index]["mac"] = $lv->generate_random_mac_addr() ;
}
$config["domain"]["type"] = "kvm";
$usbs = getVMUSBs($vmxml) ;
foreach($usbs as $i => $usb) {
if ($usb["checked"] == "checked") continue ;
unset($usbs[$i]) ;
}
$config["domain"]["usb"] = $usbs ;
$files_exist = false ;
$files_clone = array() ;
foreach ($config["disk"] as $diskid => $disk) {
$file_clone[$diskid]["source"] = $config["disk"][$diskid]["new"] ;
$config["disk"][$diskid]["new"] = str_replace($vm,$clone,$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 ;
$file_clone[$diskid]["target"] = $config["disk"][$diskid]["new"] ;
}
$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) { write("addLog\0".htmlspecialchars("Insufficent Storage for Clone")); return false ;}
#Clone XML
$uuid = $lv->domain_get_uuid($vm) ;
$config=domain_to_config($uuid) ;
$config["domain"]["name"] = $clone ;
$config["domain"]["uuid"] = $lv->domain_generate_uuid() ;
foreach($config["nic"] as $index => $detail) {
$config["nic"][$index]["mac"] = $lv->generate_random_mac_addr() ;
}
$config["domain"]["type"] = "kvm";
$files_exist = false ;
$files_clone = array() ;
foreach ($config["disk"] as $diskid => $disk) {
$file_clone[$diskid]["source"] = $config["disk"][$diskid]["new"] ;
$config["disk"][$diskid]["new"] = str_replace($vm,$clone,$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 ;
$file_clone[$diskid]["target"] = $config["disk"][$diskid]["new"] ;
}
$clonedir = $domain_cfg['DOMAINDIR'].$clone ;
if (!is_dir($clonedir)) mkdir($clonedir) ;
write("addLog\0".htmlspecialchars("Checking for image files"));
if ($file_exists && $overwrite != "yes") { write("addLog\0".htmlspecialchars("New image file names exist and Overwrite is set to No")); return( false) ; }
if ($file_exists && $overwrite != "yes") { write("addLog\0".htmlspecialchars(_("New image file names exist and Overwrite is not allowed"))); return( false) ; }
#Create duplicate files.
foreach($file_clone as $diskid => $disk) {
$cmdstr = "touch {$disk['target']}" ;
$sparse = "-S ";
$target = $disk['target'] ;
$source = $disk['source'] ;
$cmdstr = "rsync -ahPIX $sparse --out-format=%f --info=flist0,misc0,stats0,name1,progress2 '$source' '$target'" ;
$cmdstr = "rsync -ahPIXS --out-format=%f --info=flist0,misc0,stats0,name1,progress2 '$source' '$target'" ;
$error = execCommand_nchan($cmdstr,$path) ;
if (!$error) {
$arrResponse = ['error' => substr($output[0],6) ] ;
return($arrResponse) ;
} else {
$arrResponse = ['success' => true] ;
}
if (!$error) { write("addLog\0".htmlspecialchars("Image copied failed.")); return( false) ; }
}
write("<p class='logLine'></p>","addLog\0<fieldset class='docker'><legend>"._("Options for Block $action").": </legend><p class='logLine'></p><span id='wait-$waitID'></span></fieldset>");
write("<p class='logLine'></p>","addLog\0<fieldset class='docker'><legend>"._("Completing Clone").": </legend><p class='logLine'></p><span id='wait-$waitID'></span></fieldset>");
write("addLog\0".htmlspecialchars("Creating new XML $clone"));
$xml = $lv->config_to_xml($config) ;
$xml = $lv->config_to_xml($config, true) ;
file_put_contents("/tmp/clonexml" ,$xml) ;
$rtn = $lv->domain_define($xml) ;
return($rtn) ;

View File

@@ -21,6 +21,7 @@ $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";
require_once "$docroot/webGui/include/Helpers.php";
function write(...$messages){
$com = curl_init();
curl_setopt_array($com,[
@@ -40,16 +41,18 @@ function execCommand_nchan($command,$idx) {
[$cmd,$args] = explode(' ',$command,2);
write("<p class='logLine'></p>","addLog\0<fieldset class='docker'><legend>"._('Command execution')."</legend>".basename($cmd).' '.str_replace(" -","<br>&nbsp;&nbsp;-",htmlspecialchars($args))."<br><span id='wait-$waitID'>"._('Please wait')." </span><p class='logLine'></p></fieldset>","show_Wait\0$waitID");
write("addToID\0$idx\0 $action") ;
write("addToID\0$idx\0Cloning VM: ") ;
$proc = popen("$command 2>&1 &",'r');
while ($out = fread($proc,100)) {
$out = preg_replace("%[\t\n\x0B\f\r]+%", '',$out);
$out = trim($out) ;
$values = explode(' ',$out) ;
$string = "Data copied: ".$values[0]." Percentage: ".$values[1]." Transfer Rate: ".$values[2]." Time remaining: ".$values[3]." ".$values[4]." ".$values[5];
$string = _("Data copied: ").$values[0]._(" Percentage: ").$values[1]._(" Transfer Rate: ").$values[2]._(" Time remaining: ").$values[3] ;
write("progress\0$idx\0".htmlspecialchars($string)) ;
if ($out) $stringsave=$string ;
}
$retval = pclose($proc);
write("progress\0$idx\0".htmlspecialchars($stringsave)) ;
$out = $retval ? _('The command failed').'.' : _('The command finished successfully').'!';
write("stop_Wait\0$waitID","addLog\0<br><b>$out</b>");
return $retval===0;