"File: '$file' not found"]; break; } // read new cpu assignments $cpuset = explode(',',file_get_contents($file)); unlink($file); $vcpus = count($cpuset); // initial cores/threads assignment $cores = $vcpus; $threads = 1; $ht = exec("lscpu|grep -Po '^Thread\\(s\\) per core:\\s+\\K\\d+'") ?: 1; // fetch hyperthreading // adjust for hyperthreading if ($vcpus > $ht && $vcpus%$ht===0) { $cores /= $ht; $threads = $ht; } $uuid = $lv->domain_get_uuid($lv->get_domain_by_name($name)); $dom = $lv->domain_get_domain_by_uuid($uuid); $auto = $lv->domain_get_autostart($dom)==1; $xml = simplexml_load_string($lv->domain_get_xml($dom)); // update topology and vpcus $xml->cpu->topology['cores'] = $cores; $xml->cpu->topology['threads'] = $threads; $xml->vcpu = $vcpus; $pin = []; foreach ($xml->cputune->emulatorpin->attributes() as $key => $value) $pin[$key] = (string)$value; unset($xml->cputune); $xml->addChild('cputune'); for ($i = 0; $i < $vcpus; $i++) { $vcpu = $xml->cputune->addChild('vcpupin'); $vcpu['vcpu'] = $i; $vcpu['cpuset'] = $cpuset[$i]; } if ($pin) { $attr = $xml->cputune->addChild('emulatorpin'); foreach ($pin as $key => $value) $attr[$key] = $value; } // stop running vm first? $running = $lv->domain_get_state($dom)=='running'; if ($running) { $lv->domain_shutdown($dom); for ($n =0; $n < 30; $n++) { // allow up to 30s for VM to shutdown sleep(1); if ($stopped = $lv->domain_get_state($dom)=='shutoff') break; } } else $stopped = true; if (!$stopped) { $reply = ['error' => _('Failed to stop')." '$name'"]; break; } $lv->nvram_backup($uuid); $lv->domain_undefine($dom); $lv->nvram_restore($uuid); if (!$lv->domain_define($xml->saveXML())) { $reply = ['error' => $lv->get_last_error()]; break; } $lv->domain_set_autostart($dom, $auto); if ($running && !$lv->domain_start($dom)) { $reply = ['error' => $lv->get_last_error()]; } else { $reply = ['success' => $name]; } break; case 'ct': // update docker container require_once "$docroot/plugins/dynamix.docker.manager/include/DockerClient.php"; $DockerClient = new DockerClient(); $DockerTemplates = new DockerTemplates(); // get available networks $subnet = DockerUtil::network(DockerUtil::custom()); // get full template path $xml = $DockerTemplates->getUserTemplate($name); list($cmd, $ct, $repository) = xmlToCommand($xml); $imageID = $DockerClient->getImageID($repository); // pull image $container = $DockerClient->getContainerDetails($ct); // determine if the container is still running if (!empty($container) && !empty($container['State']) && !empty($container['State']['Running'])) { // since container was already running, put it back it to a running state after update $cmd = str_replace('/docker create ', '/docker run -d ', $cmd); // attempt graceful stop of container first $DockerClient->stopContainer($ct); } // force kill container if still running after time-out $DockerClient->removeContainer($ct); execCommand($cmd,false); $DockerClient->flushCaches(); $newImageID = $DockerClient->getImageID($repository); // remove old orphan image since it's no longer used by this container if ($imageID && $imageID != $newImageID) { $DockerClient->removeImage($imageID); } $reply = ['success' => $name]; break; case 'is': $cfg = '/boot/syslinux/syslinux.cfg'; $syslinux = file($cfg, FILE_IGNORE_NEW_LINES+FILE_SKIP_EMPTY_LINES); $size = count($syslinux); $make = false; $file = "/var/tmp/$name.tmp"; $isolcpus = file_get_contents($file); if ($isolcpus != '') { $numbers = explode(',',$isolcpus); sort($numbers,SORT_NUMERIC); $isolcpus = $previous = array_shift($numbers); $range = false; // convert sequential numbers to a range foreach ($numbers as $number) { if ($number == $previous+1) { $range = true; } else { if ($range) {$isolcpus .= '-'.$previous; $range = false;} $isolcpus .= ','.$number; } $previous = $number; } if ($range) $isolcpus .= '-'.$previous; $isolcpus = "isolcpus=$isolcpus"; } unlink($file); $i = 0; while ($i < $size) { // find sections and exclude safemode if (scan($syslinux[$i],'label ') && !scan($syslinux[$i],'safe mode') && !scan($syslinux[$i],'safemode')) { $n = $i + 1; // find the current requested setting while (!scan($syslinux[$n],'label ') && $n < $size) { if (scan($syslinux[$n],'append ')) { $cmd = preg_split('/\s+/',trim($syslinux[$n])); // replace an existing setting for ($c = 1; $c < count($cmd); $c++) if (scan($cmd[$c],'isolcpus')) {$make |= ($cmd[$c]!=$isolcpus); $cmd[$c] = $isolcpus; break;} // or insert a new setting if ($c==count($cmd) && $isolcpus) {array_splice($cmd,-1,0,$isolcpus); $make = true;} $syslinux[$n] = ' '.str_replace(' ',' ',implode(' ',$cmd)); } $n++; } $i = $n - 1; } $i++; } if ($make) file_put_contents($cfg, implode("\n",$syslinux)."\n"); $reply = ['success' => $name]; break; } header('Content-Type: application/json'); die(json_encode($reply)); ?>