From 633e43127c6d1a96d47587eed2739bdaff6c3d4f Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Sat, 16 Nov 2013 15:42:16 +0100 Subject: Add minilinux download functionality and ipxe compilation scripts --- apis/download.inc.php | 96 ++++++++++++++++++++++++++++++++++++++++++-------- apis/exec.inc.php | 75 +++++++++++++++++++++++++++++++++++++++ apis/getconfig.inc.php | 1 + 3 files changed, 158 insertions(+), 14 deletions(-) create mode 100644 apis/exec.inc.php (limited to 'apis') diff --git a/apis/download.inc.php b/apis/download.inc.php index 4be67521..b9033c6f 100644 --- a/apis/download.inc.php +++ b/apis/download.inc.php @@ -3,38 +3,106 @@ User::load(); if (!User::hasPermission('superadmin')) die('No permission'); -if (!isset($_REQUEST['type'])) die('No type'); -if (!isset($_REQUEST['file'])) die('No file'); -if (!isset($_REQUEST['id'])) die('No id'); require_once('inc/render.inc.php'); -$type = $_REQUEST['type']; +if (!isset($_REQUEST['file'])) die('No file'); +if (!isset($_REQUEST['id'])) die('No id'); $file = preg_replace('/[^a-z0-9\.\-_]/is', '', $_REQUEST['file']); $id = $_REQUEST['id']; +// Progress update only + +if (isset($_REQUEST['progress'])) { + $progress = preg_replace('/[^a-z0-9\-]/', '', $_REQUEST['progress']); + $pid = (isset($_REQUEST['pid']) ? (int)$_REQUEST['pid'] : 0); + $log = '/tmp/' . $progress . '.log'; + if (!file_exists($log)) { + echo Render::parse('download-error', array('file' => $file)); + exit(0); + } + $error = false; + $percent = 0; + $fh = fopen($log, 'r'); + while (!feof($fh)) { + $line = fgets($fh); + if (preg_match('/ ERROR (\d{3}):/', $line, $out)) { + $error = $out[1]; + break; + } + if (preg_match('/ (\d+)% /', $line, $out)) { + $percent = $out[1]; + } + } + fclose($fh); + if ($error === false && $pid > 0 && $percent != 100 && !posix_kill($pid, 0)) $error = 'Process died - ' . $line; + if ($error !== false) { + echo Render::parse('download-error', array('file' => $file, 'code' => $error)); + unlink($log); + exit(0); + } + if ($percent == 100) { + echo Render::parse('download-complete' ,array('file' => $file)); + unlink($log); + } else { + echo Render::parse('download-progress' ,array('file' => $file, 'progress' => $progress, 'id' => $id, 'percent' => $percent, 'pid' => $pid)); + } + exit(0); +} + +// Actual download request + +if (!isset($_REQUEST['type'])) die('No type'); + + +$type = $_REQUEST['type']; +$directExec = true; +$overwrite = isset($_REQUEST['exec']); + switch ($type) { case 'tgz': $remote = CONFIG_REMOTE_TGZ; $local = CONFIG_TGZ_LIST_DIR; break; +case 'ml': + $remote = CONFIG_REMOTE_ML; + $local = CONFIG_HTTP_DIR . '/default'; + $directExec = false; + $overwrite = true; + break; default: die('Invalid download type'); } @mkdir($local, 0755, true); -if (file_exists($local . '/' . $file) && !isset($_REQUEST['exec'])) { - echo Render::parse('download-overwrite', array('file' => $file, 'id' => $id, 'query' => $_SERVER['REQUEST_URI']));; +if (file_exists($local . '/' . $file) && !$overwrite) { + echo Render::parse('download-overwrite', array('file' => $file, 'id' => $id, 'query' => $_SERVER['REQUEST_URI'])); exit(0); } -$ret = Util::downloadToFile($local . '/' . $file, $remote . '/' . $file, 20, $code); -if ($ret === false || $code < 200 || $code >= 300) { - @unlink($local . '/' . $file); - echo Render::parse('download-error', array('file' => $file, 'remote' => $remote, 'code' => $code)); - exit(0); +if ($directExec) { + // Blocking inline download + $ret = Util::downloadToFile($local . '/' . $file, $remote . '/' . $file, 20, $code); + if ($ret === false || $code < 200 || $code >= 300) { + @unlink($local . '/' . $file); + echo Render::parse('download-error', array('file' => $file, 'remote' => $remote, 'code' => $code)); + exit(0); + } + + // No execution - just return dialog + echo Render::parse('download-complete', array('file' => $file)); +} else { + // Use WGET + $logfile = 'slx-' . mt_rand() . '-' . time(); + exec("wget --timeout=10 -O $local/$file -o /tmp/${logfile}.log -b $remote/$file", $retstr, $retval); + unlink("$local/${file}.md5"); + if ($retval != 0) { + echo Render::parse('download-error', array('file' => $destination, 'remote' => $source, 'code' => implode(' // ', $retstr) . ' - ' . $retval)); + exit(0); + } + $pid = 0; + foreach ($retstr as $line) if (preg_match('/ (\d+)([,\.\!\:]|$)/', $line, $out)) $pid = $out[1]; + file_put_contents("$local/${file}.lck", $pid . ' ' . $logfile); + echo Render::parse('download-progress', array('file' => $file, 'progress' => $logfile, 'id' => $id, 'percent' => '0', 'pid' => $pid)); } -// No execution - just return dialog -echo Render::parse('download-complete', array('file' => $file)); - diff --git a/apis/exec.inc.php b/apis/exec.inc.php new file mode 100644 index 00000000..94a94a00 --- /dev/null +++ b/apis/exec.inc.php @@ -0,0 +1,75 @@ + 10) array_shift($lastLines); + } + fclose($fh); + $running = ($pid == 0 || posix_kill($pid, 0)); + echo Render::parse('exec-progress', array('progress' => $progress, 'id' => $id, 'pid' => $pid, 'running' => $running, 'text' => implode('', $lastLines))); + if (!$running) unlink($log); + exit(0); +} + +// Actual download request +// type ip id + +if (!isset($_REQUEST['type'])) die('No type'); + + +$type = $_REQUEST['type']; + +switch ($type) { +case 'ipxe': + if (!isset($_REQUEST['ip'])) die('No IP given'); + $ip = preg_replace('/[^0-9\.]/', '', $_REQUEST['ip']); + $command = '/opt/openslx/build_ipxe.sh "' . CONFIG_IPXE_DIR . '/last-ip" "' . $ip . '"'; + $conf = Render::parse('txt-ipxeconfig', array( + 'SERVER' => $ip + )); + if (false === file_put_contents('/opt/openslx/ipxe/ipxelinux.ipxe', $conf)) die('Error writing iPXE Config'); + $conf = Render::parse('txt-pxeconfig', array( + 'SERVER' => $ip, + 'DEFAULT' => 'openslx' + )); + if (false === file_put_contents(CONFIG_TFTP_DIR . '/pxelinux.cfg/default', $conf)) die('Error writing PXE Menu'); + break; +default: + die('Invalid exec type'); +} + +$logfile = 'slx-' . mt_rand() . '-' . time(); +error_log('**EXEC: ' . "$command '/tmp/${logfile}.log'"); +exec("$command '/tmp/${logfile}.log'", $retstr, $retval); +if ($retval != 0) { + echo Render::parse('exec-error', array('error' => implode(' // ', $retstr) . ' - ' . $retval)); + exit(0); +} +$pid = 0; +foreach ($retstr as $line) if (preg_match('/PID: (\d+)\./', $line, $out)) $pid = $out[1]; +echo Render::parse('exec-progress', array('progress' => $logfile, 'id' => $id, 'pid' => $pid, 'running' => true)); + diff --git a/apis/getconfig.inc.php b/apis/getconfig.inc.php index a3d2bd91..6edb55be 100644 --- a/apis/getconfig.inc.php +++ b/apis/getconfig.inc.php @@ -5,5 +5,6 @@ $res = Database::simpleQuery('SELECT setting.setting, setting.defaultvalue, sett LEFT JOIN setting_global AS tbl USING (setting) ORDER BY setting ASC'); // TODO: Add setting groups and sort order while ($row = $res->fetch(PDO::FETCH_ASSOC)) { + if (empty($row['value'])) $row['value'] = $row['defaultvalue']; echo $row['setting'] . "='" . str_replace("'", "'\"'\"'", $row['value']) . "'\n"; } -- cgit v1.2.3-55-g7522