From 2903a586a5f19e546ed12841e0c7a170320fd82b Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Wed, 26 Feb 2020 18:05:14 +0100 Subject: [minilinux] Show warning if stage4 cannot be replicated --- modules-available/minilinux/inc/minilinux.inc.php | 75 ++++++++++++++++++++++ modules-available/minilinux/page.inc.php | 3 + .../minilinux/templates/filelist.html | 3 + 3 files changed, 81 insertions(+) diff --git a/modules-available/minilinux/inc/minilinux.inc.php b/modules-available/minilinux/inc/minilinux.inc.php index 7fe2035a..e79884f9 100644 --- a/modules-available/minilinux/inc/minilinux.inc.php +++ b/modules-available/minilinux/inc/minilinux.inc.php @@ -243,7 +243,9 @@ class MiniLinux if ($task !== false) { // Callback for db column TaskmanagerCallback::addCallback($task, 'mlGotLinux', $versionid); + self::checkStage4($data); } + // Race - someone else wrote a taskid to DB, just call self again to get that one if ($aff === 0) return self::downloadVersion($versionid); return $task; @@ -377,4 +379,77 @@ class MiniLinux } } + /** + * Check whether an optionally required stage4 is available. + * Return true if there is no stage4, otherwise check filesystem, + * or try to request from local dnbd3-server. + * @param array $data decoded data column from minilinux_version + * @param string[] $errors in array of error messages if not available + * @return bool true if stage4 is available or none required + */ + public static function checkStage4($data, &$errors = false) + { + $errors = []; + $image = false; + $rid = 0; + foreach (['agnostic', 'efi', 'bios'] as $type) { + if (!isset($data[$type]) || !isset($data[$type]['commandLine'])) + continue; + if (!preg_match('/\bslx\.stage4\.path=(\S+)/', $data[$type]['commandLine'], $out)) + continue; + $image = $out[1]; + if (preg_match('/\bslx\.stage4\.rid=(\d+)/', $data[$type]['commandLine'], $out)) { + $rid = $out[1]; + } + break; + } + if ($image === false) + return true; // No stage4 + if (file_exists(CONFIG_VMSTORE_DIR . '/' . $image)) + return true; // Already exists locally + // Not found locally -- try to replicate + $sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); + if ($sock === false) { + $errors[] = 'Error creatring socket to connect to dnbd3-server'; + return false; + } + socket_set_option($sock, SOL_SOCKET, SO_SNDTIMEO, array('sec' => 1, 'usec' => 0)); + socket_set_option($sock, SOL_SOCKET, SO_RCVTIMEO, array('sec' => 5, 'usec' => 0)); + if (@socket_connect($sock, '127.0.0.1', 5003) === false) { + $errors[] = 'Could not connect to local dnbd3-server'; + socket_close($sock); + return false; + } + // proto-version(16), image name\0, rid(16), flags(8) + $payload = pack('vA*xvC', 3, $image, $rid, 0); + // magic(16), cmd(16), payload-len(32), offset(64), handle(64) + $packet = pack('A*vVPP', 'sr', 2, strlen($payload), 0, 1234) . $payload; + if (!socket_send($sock, $packet, strlen($packet), 0)) { + $errors[] = 'Cannot send request to dnbd3-server'; + socket_close($sock); + return false; + } + $len = socket_recv($sock, $reply, 16, MSG_WAITALL); + if ($len === 0) { + $errors[] = 'Local dnbd3-server cannot replicate required stage4 from master-server'; + socket_close($sock); + return false; + } + if ($len !== 16) { + $errors[] = 'Incomplete reply received from local dnbd3-server. Stage4 might not replicate!'; + socket_close($sock); + return false; + } + socket_close($sock); + // Try to decode header + $reply = unpack('A2magic/vcmd/Vsize/Phandle', $reply); + if ($reply['magic'] !== 'sr') { + $errors[] = 'Reply has wrong magic'; + } + if ($reply['cmd'] !== 2) { + $errors[] = 'Reply is not CMD_IMAGE_REPLY'; + } + return empty($errors); + } + } \ No newline at end of file diff --git a/modules-available/minilinux/page.inc.php b/modules-available/minilinux/page.inc.php index 76bcb95f..faea7599 100644 --- a/modules-available/minilinux/page.inc.php +++ b/modules-available/minilinux/page.inc.php @@ -163,6 +163,9 @@ class Page_MiniLinux extends Page MiniLinux::setInstalledState($versionid, true); } } + if ($data['dltask'] !== false || $ver['installed']) { + MiniLinux::checkStage4($data, $data['s4_errors']); + } echo Render::parse('filelist', $data); } diff --git a/modules-available/minilinux/templates/filelist.html b/modules-available/minilinux/templates/filelist.html index b006fd1e..fdbef4ad 100644 --- a/modules-available/minilinux/templates/filelist.html +++ b/modules-available/minilinux/templates/filelist.html @@ -41,6 +41,9 @@ {{/files}} +{{#s4_errors}} +
{{lang_maybeMissingStage4}}: {{.}}
+{{/s4_errors}} {{#dltask}}

-- 
cgit v1.2.3-55-g7522