file); if (is_string($ret)) return $ret; return isset($taskId) ? $taskId : false; }; $ret = $ret($taskId); if (is_string($ret)) { $taskId = $ret; } elseif (is_array($ret) && isset($ret['id'])) { $taskId = $ret['id']; } } Property::set('ipxe-task-id', $taskId, 15); return $taskId; } /** * Try to automatically determine the primary IP address of the server. * This only works if the server has either one public IPv4 address (and potentially * one or more non-public addresses), or one private address. * * @return boolean true if current configured IP address is still valid, or if a new address could * successfully be determined, false otherwise */ public static function autoUpdateServerIp() { for ($i = 0; $i < 5; ++$i) { $task = Taskmanager::submit('LocalAddressesList'); if ($task !== false) break; sleep(1); } if ($task === false) return false; $task = Taskmanager::waitComplete($task, 10000); if (!isset($task['data']['addresses']) || empty($task['data']['addresses'])) return false; $serverIp = Property::getServerIp(); $publicCandidate = 'none'; $privateCandidate = 'none'; foreach ($task['data']['addresses'] as $addr) { if (substr($addr['ip'], 0, 4) === '127.' || preg_match('/^\d+\.\d+\.\d+\.\d+$/', $addr['ip']) !== 1) continue; if ($addr['ip'] === $serverIp) return true; if (Util::isPublicIpv4($addr['ip'])) { if ($publicCandidate === 'none') $publicCandidate = $addr['ip']; else $publicCandidate = 'many'; } else { if ($privateCandidate === 'none') $privateCandidate = $addr['ip']; else $privateCandidate = 'many'; } } if ($publicCandidate !== 'none' && $publicCandidate !== 'many') { Property::setServerIp($publicCandidate, true); return true; } if ($privateCandidate !== 'none' && $privateCandidate !== 'many') { Property::setServerIp($privateCandidate, true); return true; } return false; } /** * Mount the VM store into the server. * * @param array $vmstore VM Store configuration to use. If false, read from properties * @param bool $ifLocalOnly Only execute task if the storage type is local (used for DNBD3) * @return string|false task id of mount procedure, or false on error */ public static function mount($vmstore = false, $ifLocalOnly = false) { if ($vmstore === false) { $vmstore = Property::getVmStoreConfig(); } if (!is_array($vmstore)) return false; if (isset($vmstore['storetype'])) { $storetype = $vmstore['storetype']; } else { $storetype = 'unknown'; } if ($storetype === 'nfs') { $addr = $vmstore['nfsaddr']; $opts = 'nfsopts'; } elseif ($storetype === 'cifs') { $addr = $vmstore['cifsaddr']; $opts = 'cifsopts'; } else { $opts = null; $addr = 'null'; } // Bail out if storage is not local, and we only want to run it in that case if ($ifLocalOnly && $addr !== 'null') return false; if (isset($vmstore[$opts])) { $opts = $vmstore[$opts]; }else { $opts = null; } $status = Taskmanager::submit('MountVmStore', array( 'address' => $addr, 'type' => 'images', 'opts' => $opts, 'localNfs' => !Module::isAvailable('dnbd3') || !Dnbd3::isEnabled() || Dnbd3::hasNfsFallback(), 'username' => $vmstore['cifsuser'], 'password' => $vmstore['cifspasswd'] )); if (!Taskmanager::isFailed($status)) { // In case we have a concurrent active task, this should be enough // for the taskmanager to give us the existing id $status = Taskmanager::waitComplete($status, 100); } return $status['data']['existingTask'] ?? $status['id'] ?? false; } /** * Check and process all callbacks. * * @return boolean Whether there are still callbacks pending */ public static function checkCallbacks() { $tasksLeft = false; $callbackList = TaskmanagerCallback::getPendingCallbacks(); foreach ($callbackList as $taskid => $callbacks) { $status = Taskmanager::status($taskid); if ($status === false) continue; foreach ($callbacks as $callback) { TaskmanagerCallback::handleCallback($callback, $status); } if (Taskmanager::isFailed($status) || Taskmanager::isFinished($status)) Taskmanager::release($status); else $tasksLeft = true; } return $tasksLeft; } private static function triggerDaemons($action, $parent, &$taskids) { $task = Taskmanager::submit('Systemctl', array( 'operation' => $action, 'service' => 'dmsd', 'parentTask' => $parent, 'failOnParentFail' => false )); if (isset($task['id'])) { $taskids['dmsdid'] = $task['id']; $parent = $task['id']; } $task = Taskmanager::submit('Systemctl', array( 'operation' => $action, 'service' => 'dnbd3-server', 'parentTask' => $parent, 'failOnParentFail' => false )); if (isset($task['id'])) { $taskids['dnbd3id'] = $task['id']; $parent = $task['id']; } return $parent; } /** * Stop any daemons that might be sitting on the VMstore, or database. */ public static function stopDaemons($parent, &$taskids) { $parent = self::triggerDaemons('stop', $parent, $taskids); $task = Taskmanager::submit('LdadpLauncher', array( 'ids' => array(), 'parentTask' => $parent, 'failOnParentFail' => false )); if (isset($task['id'])) { $taskids['ldadpid'] = $task['id']; $parent = $task['id']; } return $parent; } }