From e3388acaca0ce6f1a2d4cb17e535497f2689118a Mon Sep 17 00:00:00 2001 From: Dan Engelbrecht Date: Sat, 21 Mar 2026 23:13:34 +0100 Subject: zen hub command (#877) - Feature: Added `zen hub` command for managing a hub server and its provisioned module instances: - `zen hub up` - Start a hub server (equivalent to `zen up` in hub mode) - `zen hub down` - Shut down a hub server - `zen hub provision ` - Provision a storage server instance for a module - `zen hub deprovision ` - Deprovision a storage server instance - `zen hub hibernate ` - Hibernate a provisioned instance (shut down, data preserved) - `zen hub wake ` - Wake a hibernated instance - `zen hub status [moduleid]` - Show state of all instances or a specific module - Feature: Added new hub HTTP endpoints for instance lifecycle management: - `POST /hub/modules/{moduleid}/hibernate` - Hibernate the instance for the given module - `POST /hub/modules/{moduleid}/wake` - Wake a hibernated instance for the given module - Improvement: `zen up` refactored to use shared `StartupZenServer`/`ShutdownZenServer` helpers (also used by `zen hub up`/`zen hub down`) - Bugfix: Fixed shutdown event not being cleared after the server process exits in `ZenServerInstance::Shutdown()`, which could cause stale state on reuse --- src/zenserver/hub/storageserverinstance.cpp | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) (limited to 'src/zenserver/hub/storageserverinstance.cpp') diff --git a/src/zenserver/hub/storageserverinstance.cpp b/src/zenserver/hub/storageserverinstance.cpp index bab501429..7933cfa70 100644 --- a/src/zenserver/hub/storageserverinstance.cpp +++ b/src/zenserver/hub/storageserverinstance.cpp @@ -123,7 +123,7 @@ StorageServerInstance::DeprovisionLocked() m_State = HubInstanceState::Unprovisioned; } -void +bool StorageServerInstance::HibernateLocked() { // Signal server to shut down, but keep data around for later wake @@ -133,16 +133,13 @@ StorageServerInstance::HibernateLocked() ZEN_WARN("Attempted to hibernate storage server instance for module '{}' which is not provisioned (state: '{}')", m_ModuleId, ToString(m_State.load())); - return; + return false; } if (!m_ServerInstance.IsRunning()) { ZEN_WARN("Attempted to hibernate storage server instance for module '{}' which is not running", m_ModuleId); - - // This is an unexpected state. Should consider the instance invalid? - - return; + return false; } m_State = HubInstanceState::Hibernating; @@ -150,12 +147,13 @@ StorageServerInstance::HibernateLocked() { m_ServerInstance.Shutdown(); m_State = HubInstanceState::Hibernated; - return; + return true; } catch (const std::exception& Ex) { ZEN_ERROR("Failed to hibernate storage server instance for module '{}': {}", m_ModuleId, Ex.what()); m_State = HubInstanceState::Provisioned; // Shutdown failed; instance is still running + return false; } } @@ -166,9 +164,10 @@ StorageServerInstance::WakeLocked() if (m_State.load() != HubInstanceState::Hibernated) { - ZEN_WARN("Attempted to wake storage server instance for module '{}' which is not hibernated", m_ModuleId); - - return true; // Instance is already usable (noop success) + ZEN_WARN("Attempted to wake storage server instance for module '{}' which is not hibernated (state: '{}')", + m_ModuleId, + ToString(m_State.load())); + return false; } ZEN_ASSERT_FORMAT(!m_ServerInstance.IsRunning(), "Storage server instance for module '{}' is already running", m_ModuleId); @@ -389,11 +388,11 @@ StorageServerInstance::ExclusiveLockedPtr::Deprovision() m_Instance->DeprovisionLocked(); } -void +bool StorageServerInstance::ExclusiveLockedPtr::Hibernate() { ZEN_ASSERT(m_Instance != nullptr); - m_Instance->HibernateLocked(); + return m_Instance->HibernateLocked(); } bool -- cgit v1.2.3