use std::time::Duration;
use crate::{
Builder, Result,
lifecycle::{
LifecycleState, TransitionId,
msgs::{
ChangeState, ChangeStateRequest, GetAvailableStates, GetAvailableStatesRequest,
GetAvailableTransitions, GetAvailableTransitionsRequest, GetState, GetStateRequest,
LcState, LcTransitionDescription,
},
},
node::ZNode,
service::ZClient,
};
pub struct ZLifecycleClient {
change_state: ZClient<ChangeState>,
get_state: ZClient<GetState>,
get_available_states: ZClient<GetAvailableStates>,
get_available_transitions: ZClient<GetAvailableTransitions>,
}
impl ZLifecycleClient {
pub fn new(node: &ZNode, node_name: &str) -> Result<Self> {
let change_state = node
.create_client::<ChangeState>(&format!("{node_name}/change_state"))
.build()?;
let get_state = node
.create_client::<GetState>(&format!("{node_name}/get_state"))
.build()?;
let get_available_states = node
.create_client::<GetAvailableStates>(&format!("{node_name}/get_available_states"))
.build()?;
let get_available_transitions = node
.create_client::<GetAvailableTransitions>(&format!(
"{node_name}/get_available_transitions"
))
.build()?;
Ok(Self {
change_state,
get_state,
get_available_states,
get_available_transitions,
})
}
pub async fn configure(&self, timeout: Duration) -> Result<bool> {
self.trigger(TransitionId::Configure, timeout).await
}
pub async fn activate(&self, timeout: Duration) -> Result<bool> {
self.trigger(TransitionId::Activate, timeout).await
}
pub async fn deactivate(&self, timeout: Duration) -> Result<bool> {
self.trigger(TransitionId::Deactivate, timeout).await
}
pub async fn cleanup(&self, timeout: Duration) -> Result<bool> {
self.trigger(TransitionId::Cleanup, timeout).await
}
pub async fn shutdown(&self, timeout: Duration) -> Result<bool> {
let transition_id = match self.get_state(timeout).await? {
LifecycleState::Unconfigured => TransitionId::UnconfiguredShutdown,
LifecycleState::Active => TransitionId::ActiveShutdown,
_ => TransitionId::InactiveShutdown,
};
self.trigger(transition_id, timeout).await
}
pub async fn trigger(&self, transition: TransitionId, timeout: Duration) -> Result<bool> {
let req = ChangeStateRequest {
transition: crate::lifecycle::msgs::LcTransition {
id: transition as u8,
label: String::new(),
},
};
let resp = self.change_state.call_with_timeout(&req, timeout).await?;
Ok(resp.success)
}
pub async fn get_state(&self, timeout: Duration) -> Result<LifecycleState> {
let resp = self
.get_state
.call_with_timeout(&GetStateRequest {}, timeout)
.await?;
Ok(state_from_lc(&resp.current_state))
}
pub async fn get_available_states(&self, timeout: Duration) -> Result<Vec<LcState>> {
let resp = self
.get_available_states
.call_with_timeout(&GetAvailableStatesRequest {}, timeout)
.await?;
Ok(resp.available_states)
}
pub async fn get_available_transitions(
&self,
timeout: Duration,
) -> Result<Vec<LcTransitionDescription>> {
let resp = self
.get_available_transitions
.call_with_timeout(&GetAvailableTransitionsRequest {}, timeout)
.await?;
Ok(resp.available_transitions)
}
}
fn state_from_lc(s: &LcState) -> LifecycleState {
match s.id {
1 => LifecycleState::Unconfigured,
2 => LifecycleState::Inactive,
3 => LifecycleState::Active,
4 => LifecycleState::Finalized,
_ => LifecycleState::Unconfigured,
}
}