1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
use std::sync::Arc;
use crate::core::client::{VimClient, Result};
/// FailoverClusterManager provides operations to manage a vCenter
/// High Availability Cluster (VCHA Cluster).
///
/// A VCHA Cluster consists of three VMs. One is the Active vCenter VM that
/// serves client requests. Second is the Passive VM that is identical to the
/// Active vCenter VM in terms of resources and capabilities. Passive VM
/// constantly receives updates from Active VM and takes over the role of
/// Active vCenter VM in the event of failover. Third is the Witness VM that
/// acts as a quorum VM in a VCHA Cluster. Sole purpose of Witness VM is to
/// avoid classic split-brain problem in a VCHA Cluster.
/// A VCHA Cluster has following states -
/// 1\. Healthy - All three nodes in a VCHA Cluster are healthy and connected.
/// State replication between Active and Passive node is working and both
/// nodes are in-sync.
/// 2\. Degraded - A VCHA Cluster is said to be in degraded state when it has
/// lost one of the three nodes. Node loss can be due to various reasons and
/// as a result the lost node is not visible to other two nodes. If an Active
/// node is lost, Passive node will take the role of Active node. If Passive or
/// Witness node is lost, Active node will continue to serve requests. A VCHA
/// Cluster can also be in degraded state if state replication fails between
/// Active and Passive nodes.
/// 3\. Isolated - All three nodes are isolated from each other. If this happens
/// while VCHA Cluster is in enabled mode, Active node stops serving client
/// requests. If nodes are isolated in a disabled VCHA Cluster mode, Active
/// node continues to serve client requests.
/// A VCHA Cluster has following modes -
/// 1\. Enabled - State replication between Active and Passive nodes is
/// enabled and automatic failover happens if Active node fails while the
/// VCHA Cluster is in a healthy state.
/// 2\. Disabled - All three nodes are part of VCHA Cluster but state
/// replication and automatic failover is disabled.
/// 3\. Maintenance - All three nodes are part of VCHA Cluster but automatic
/// failover is disabled while state replication continues. Active node continues
/// to serve client requests even if Passive and Witness nodes are lost.
#[derive(Clone)]
pub struct FailoverClusterManager {
client: Arc<dyn VimClient>,
mo_id: String,
}
impl FailoverClusterManager {
pub fn new(client: Arc<dyn VimClient>, mo_id: &str) -> Self {
Self {
client,
mo_id: mo_id.to_string(),
}
}
/// Returns last known health of the VCHA Cluster.
///
/// ***Required privileges:*** System.Read
pub async fn get_vcha_cluster_health(&self) -> Result<crate::types::structs::VchaClusterHealth> {
let bytes = self.client.invoke("", "FailoverClusterManager", &self.mo_id, "GetVchaClusterHealth", None).await?;
let result: crate::types::structs::VchaClusterHealth = crate::core::client::unmarshal(self.client.transport(), &bytes)?;
Ok(result)
}
/// Returns current mode of a VCHA Cluster.
///
/// ***Required privileges:*** System.Read
pub async fn get_cluster_mode(&self) -> Result<String> {
let bytes = self.client.invoke("", "FailoverClusterManager", &self.mo_id, "getClusterMode", None).await?;
let result: String = crate::core::client::unmarshal(self.client.transport(), &bytes)?;
Ok(result)
}
/// Allows a caller to initiate a failover from Active vCenter Server node
/// to the Passive node.
///
/// By default it is a forced failover. The planned
/// flag can be used to initiate it as a planned failover.
/// For forced failover, Active node immediately initiates a failover. This
/// may result into a data loss after failover.
/// For planned failover, Active node flushes all the state to the
/// Passive node, waits for the flush to complete before causing a failover.
/// After the failover, Passive node starts without any data loss.
/// A failover is allowed only in the following cases -
/// 1\. Cluster's mode is enabled and all cluster members are present.
/// 2\. Cluster's mode is maintenance and all cluster members are present.
/// API throws an exception in all other cases.
///
/// ***Required privileges:*** Global.VCServer
///
/// ## Parameters:
///
/// ### planned
/// \- if false, a failover is initiated immediate and may
/// result in data loss.
/// if true, a failover is initated after the Active node
/// flushes its state to Passive and there is no data loss.
///
/// ## Returns:
///
/// Refers instance of *Task*.
pub async fn initiate_failover_task(&self, planned: bool) -> Result<crate::types::structs::ManagedObjectReference> {
let input = InitiateFailoverRequestType {planned, };
let bytes = self.client.invoke("", "FailoverClusterManager", &self.mo_id, "initiateFailover_Task", Some(&input)).await?;
let result: crate::types::structs::ManagedObjectReference = crate::core::client::unmarshal(self.client.transport(), &bytes)?;
Ok(result)
}
/// setClusterMode method allows caller to manipulate the mode of a
/// VCHA Cluster
/// Following mode transitions are allowed -
/// enabled -> disabled - Allowed only in healthy and degraded states.
///
/// enabled -> maintenance - Allowed only in healthy state.
/// disabled -> enabled - Allowed only in healthy state.
/// maintenance -> enabled - Allowed only in healthy state with all nodes
/// are running the same version.
/// maintenance -> disabled - Allowed only in healthy state with all nodes
/// are running the same version.
/// All other transitions are not allowed.
/// VCHA Cluster configuration remains intact in any of the cluster modes.
///
/// ***Required privileges:*** Global.VCServer
///
/// ## Parameters:
///
/// ### mode
/// -
///
/// ## Returns:
///
/// This method returns a *Task* object with which to
/// monitor the progress of the operation.
///
/// Refers instance of *Task*.
pub async fn set_cluster_mode_task(&self, mode: &str) -> Result<crate::types::structs::ManagedObjectReference> {
let input = SetClusterModeRequestType {mode, };
let bytes = self.client.invoke("", "FailoverClusterManager", &self.mo_id, "setClusterMode_Task", Some(&input)).await?;
let result: crate::types::structs::ManagedObjectReference = crate::core::client::unmarshal(self.client.transport(), &bytes)?;
Ok(result)
}
/// A list of method names that must not be called and will throw
/// a fault due to some other method running that the disabled method
/// can cause side-effects for.
///
/// This list may include the following methods:
/// - *FailoverClusterManager.setClusterMode_Task*
/// - *FailoverClusterManager.getClusterMode*
/// - *FailoverClusterManager.initiateFailover_Task*
/// - *FailoverClusterManager.GetVchaClusterHealth*
///
/// GetClusterHealth will also be disabled if Deploy is in progress.
/// As with other disabled methods there will be no property updates
/// on this property when called with non-zero property collector versions.
///
/// ***Required privileges:*** System.Read
pub async fn disabled_cluster_method(&self) -> Result<Option<Vec<String>>> {
let pv_opt = self.client.fetch_property_raw("", "FailoverClusterManager", &self.mo_id, "disabledClusterMethod").await?;
match pv_opt {
Some(pv) => Ok(Some(crate::core::client::extract_property(pv)?)),
None => Ok(None),
}
}
}
struct InitiateFailoverRequestType {
planned: bool,
}
impl miniserde::Serialize for InitiateFailoverRequestType {
fn begin(&self) -> miniserde::ser::Fragment<'_> {
miniserde::ser::Fragment::Map(Box::new(InitiateFailoverRequestTypeSer { data: self, seq: 0 }))
}
}
struct InitiateFailoverRequestTypeSer<'b> {
data: &'b InitiateFailoverRequestType,
seq: usize,
}
impl<'b> miniserde::ser::Map for InitiateFailoverRequestTypeSer<'b> {
fn next(&mut self) -> Option<(std::borrow::Cow<'_, str>, &dyn miniserde::Serialize)> {
let seq = self.seq;
self.seq += 1;
match seq {
0 => return Some((std::borrow::Cow::Borrowed("_typeName"), &"initiateFailoverRequestType")),
1 => return Some((std::borrow::Cow::Borrowed("planned"), &self.data.planned as &dyn miniserde::Serialize)),
_ => return None,
}
}
}
struct SetClusterModeRequestType<'a> {
mode: &'a str,
}
impl<'a> miniserde::Serialize for SetClusterModeRequestType<'a> {
fn begin(&self) -> miniserde::ser::Fragment<'_> {
miniserde::ser::Fragment::Map(Box::new(SetClusterModeRequestTypeSer { data: self, seq: 0 }))
}
}
struct SetClusterModeRequestTypeSer<'b, 'a> {
data: &'b SetClusterModeRequestType<'a>,
seq: usize,
}
impl<'b, 'a> miniserde::ser::Map for SetClusterModeRequestTypeSer<'b, 'a> {
fn next(&mut self) -> Option<(std::borrow::Cow<'_, str>, &dyn miniserde::Serialize)> {
let seq = self.seq;
self.seq += 1;
match seq {
0 => return Some((std::borrow::Cow::Borrowed("_typeName"), &"setClusterModeRequestType")),
1 => return Some((std::borrow::Cow::Borrowed("mode"), &self.data.mode as &dyn miniserde::Serialize)),
_ => return None,
}
}
}