From 9a6fb250ee0d5936e9d61325b6f4a99a1e290cdd Mon Sep 17 00:00:00 2001 From: Dmitry Tantsur Date: Sun, 27 Oct 2024 15:52:21 +0100 Subject: [PATCH 1/2] chore(compute): clean up ServerAction --- src/compute/servers.rs | 45 +++++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 23 deletions(-) diff --git a/src/compute/servers.rs b/src/compute/servers.rs index 321d02937a..3a48d54f5a 100644 --- a/src/compute/servers.rs +++ b/src/compute/servers.rs @@ -341,7 +341,6 @@ impl Server { /// An action to perform on a server. #[derive(Clone, Debug, Serialize)] #[non_exhaustive] -#[allow(missing_copy_implementations)] pub enum ServerAction { /// Adds a security group to a server. #[serde(rename = "addSecurityGroup")] @@ -380,6 +379,16 @@ pub enum ServerAction { #[serde(skip_serializing_if = "Option::is_none")] metadata: Option>, }, + /// Force-deletes a server before deferred cleanup. + #[serde(rename = "forceDelete", serialize_with = "unit_to_null")] + ForceDelete, + /// Shows console output for a server. + #[serde(rename = "os-getConsoleOutput")] + GetConsoleOutput { + /// The number of lines to fetch from the end of console log. All lines will be returned if this is not specified. + #[serde(skip_serializing_if = "Option::is_none")] + length: Option, + }, /// Pauses a server. Changes its status to PAUSED. #[serde(rename = "pause", serialize_with = "unit_to_null")] Pause, @@ -416,12 +425,21 @@ pub enum ServerAction { #[serde(rename = "OS-DCF:diskConfig")] disk_config: String, }, + /// Restores a previously soft-deleted server instance. + #[serde(rename = "restore", serialize_with = "unit_to_null")] + Restore, /// Resumes a suspended server and changes its status to ACTIVE. #[serde(rename = "resume", serialize_with = "unit_to_null")] Resume, /// Cancels and reverts a pending resize action for a server. #[serde(rename = "revertResize", serialize_with = "unit_to_null")] RevertResize, + /// Shelves a server. + #[serde(rename = "shelve", serialize_with = "unit_to_null")] + Shelve, + /// Shelf-offloads, or removes, a shelved server. + #[serde(rename = "shelveOffload", serialize_with = "unit_to_null")] + ShelveOffload, /// Starts a stopped server. #[serde(rename = "os-start", serialize_with = "unit_to_null")] Start, @@ -431,6 +449,9 @@ pub enum ServerAction { /// Suspends a server and changes its status to SUSPENDED. #[serde(rename = "suspend", serialize_with = "unit_to_null")] Suspend, + /// Trigger a crash dump in a server. + #[serde(rename = "trigger_crash_dump", serialize_with = "unit_to_null")] + TriggerCrashDump, /// Unlocks a locked server. #[serde(rename = "unlock", serialize_with = "unit_to_null")] Unlock, @@ -440,28 +461,6 @@ pub enum ServerAction { /// Unrescues a server. Changes status to ACTIVE. #[serde(rename = "unrescue", serialize_with = "unit_to_null")] Unrescue, - /// Force-deletes a server before deferred cleanup. - #[serde(rename = "forceDelete", serialize_with = "unit_to_null")] - ForceDelete, - /// Restores a previously soft-deleted server instance. - #[serde(rename = "restore", serialize_with = "unit_to_null")] - Restore, - /// Shows console output for a server. - #[serde(rename = "os-getConsoleOutput")] - OsGetConsoleOutput { - /// The number of lines to fetch from the end of console log. All lines will be returned if this is not specified. - #[serde(skip_serializing_if = "Option::is_none")] - length: Option, - }, - /// Shelves a server. - #[serde(rename = "shelve", serialize_with = "unit_to_null")] - Shelve, - /// Shelf-offloads, or removes, a shelved server. - #[serde(rename = "shelveOffload", serialize_with = "unit_to_null")] - ShelveOffload, - /// Trigger a crash dump in a server. - #[serde(rename = "trigger_crash_dump", serialize_with = "unit_to_null")] - TriggerCrashDump, } #[async_trait] From e9ceafb9fb00f55e816c70a12dd64939352a5d8f Mon Sep 17 00:00:00 2001 From: Dmitry Tantsur Date: Sun, 27 Oct 2024 16:11:43 +0100 Subject: [PATCH 2/2] feat(compute): explicit get_console_output --- src/compute/api.rs | 38 +++++++++++++---------- src/compute/protocol.rs | 6 ++++ src/compute/servers.rs | 22 ++++++++++--- tests/integration-create-delete-server.rs | 6 ++++ 4 files changed, 51 insertions(+), 21 deletions(-) diff --git a/src/compute/api.rs b/src/compute/api.rs index a5abbe18ac..da2cef7c5f 100644 --- a/src/compute/api.rs +++ b/src/compute/api.rs @@ -19,7 +19,8 @@ use std::fmt::Debug; use osauth::common::{IdAndName, Ref}; use osauth::services::COMPUTE; -use osauth::{Error, ErrorKind}; +use osauth::ErrorKind; +use serde::de::DeserializeOwned; use serde::Serialize; use super::super::common::ApiVersion; @@ -315,31 +316,36 @@ pub async fn list_servers_detail( } /// Run an action on a server. -pub async fn server_action_with_args( - session: &Session, - id: S1, - action: Q, -) -> Result> +pub async fn server_action(session: &Session, id: S1, action: Q) -> Result<()> where S1: AsRef, Q: Serialize + Send + Debug, { trace!("Running {:?} on server {}", action, id.as_ref(),); - let response = session + let _ = session .post(COMPUTE, &["servers", id.as_ref(), "action"]) .json(&action) .send() .await?; debug!("Successfully ran {:?} on server {}", action, id.as_ref()); - Ok(match response.content_length() { - Some(0) => None, - _ => Some( - response - .json::() - .await - .map_err(|e| Error::new(ErrorKind::InvalidResponse, e.to_string()))?, - ), - }) + Ok(()) +} + +/// Run an action on a server and return result. +pub async fn server_action_with_result(session: &Session, id: S1, action: Q) -> Result +where + S1: AsRef, + Q: Serialize + Send + Debug, + R: DeserializeOwned + Send, +{ + trace!("Running {:?} on server {}", action, id.as_ref(),); + let response = session + .post(COMPUTE, &["servers", id.as_ref(), "action"]) + .json(&action) + .fetch() + .await?; + debug!("Successfully ran {:?} on server {}", action, id.as_ref()); + Ok(response) } /// Whether key pair pagination is supported. diff --git a/src/compute/protocol.rs b/src/compute/protocol.rs index c8defbeec8..7501115700 100644 --- a/src/compute/protocol.rs +++ b/src/compute/protocol.rs @@ -395,3 +395,9 @@ impl Default for ServerPowerState { fn default_flavor_is_public() -> bool { true } + +#[derive(Clone, Debug, Deserialize)] +pub struct GetConsoleOutput { + /// Output as a string. + pub output: String, +} diff --git a/src/compute/servers.rs b/src/compute/servers.rs index 3a48d54f5a..4ca834cdce 100644 --- a/src/compute/servers.rs +++ b/src/compute/servers.rs @@ -292,6 +292,11 @@ impl Server { updated_at: DateTime } + /// Run an action on the server. + pub async fn action(&mut self, action: ServerAction) -> Result<()> { + api::server_action(&self.session, &self.inner.id, action).await + } + /// Delete the server. pub async fn delete(self) -> Result> { api::delete_server(&self.session, &self.inner.id).await?; @@ -302,6 +307,17 @@ impl Server { )) } + /// Get the console output as a string. + /// + /// Length is the number of lines to fetch from the end of console log. + /// All lines will be returned if this is not specified. + pub async fn get_console_output(&self, length: Option) -> Result { + let action = ServerAction::GetConsoleOutput { length }; + let result: protocol::GetConsoleOutput = + api::server_action_with_result(&self.session, &self.inner.id, action).await?; + Ok(result.output) + } + /// Reboot the server. pub async fn reboot( &mut self, @@ -331,11 +347,6 @@ impl Server { target: protocol::ServerStatus::ShutOff, }) } - - /// Run an action on the server. - pub async fn action(&mut self, action: ServerAction) -> Result> { - api::server_action_with_args(&self.session, &self.inner.id, action).await - } } /// An action to perform on a server. @@ -384,6 +395,7 @@ pub enum ServerAction { ForceDelete, /// Shows console output for a server. #[serde(rename = "os-getConsoleOutput")] + #[doc(hidden)] GetConsoleOutput { /// The number of lines to fetch from the end of console log. All lines will be returned if this is not specified. #[serde(skip_serializing_if = "Option::is_none")] diff --git a/tests/integration-create-delete-server.rs b/tests/integration-create-delete-server.rs index a6be6aef09..4adf53cd1d 100644 --- a/tests/integration-create-delete-server.rs +++ b/tests/integration-create-delete-server.rs @@ -171,6 +171,12 @@ async fn test_basic_server_ops() { .await .expect("Failed to delete floating IP"); + let console = server + .get_console_output(Some(10)) + .await + .expect("Failed to get console output"); + assert!(console.len() > 0); + server .delete() .await