openstack/baremetal/types.rs
1// Copyright 2023 Dmitry Tantsur <dtantsur@protonmail.com>
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use crate::common::CommaSeparated;
16use crate::utils::SortDir;
17use osauth::QueryItem;
18use serde::Deserialize;
19
20protocol_enum! {
21 /// Provision state of the node.
22 enum ProvisionState = Unknown {
23 /// Previously deployed node is being adopted.
24 Adopting = "adopting",
25 /// Adopting a deployed node has failed.
26 AdoptFailed = "adopt failed",
27 /// Node is deployed.
28 Active = "active",
29 /// Node is available for deployment.
30 Available = "available",
31 /// A synchronous cleaning/preparing action is running.
32 Cleaning = "cleaning",
33 /// Cleaning has failed.
34 CleanFailed = "clean failed",
35 /// Waiting for an asynchronous cleaning/preparing action.
36 CleanWait = "clean wait",
37 /// A synchronous deployment action is running.
38 Deploying = "deploying",
39 /// Deployment has failed.
40 DeployFailed = "deploy failed",
41 /// Waiting for an asynchronous deployment action.
42 DeployWait = "wait call-back",
43 /// Processing inspection data.
44 Inspecting = "inspecting",
45 /// Inspection has failed.
46 InspectFailed = "inspect failed",
47 /// Waiting for inspection data from the ramdisk.
48 InspectWait = "inspect wait",
49 /// Node is freshly enrolled.
50 Enroll = "enroll",
51 /// Node is enrolled and manageable.
52 Manageable = "manageable",
53 /// Node is in rescue mode.
54 Rescue = "rescue",
55 /// Node is being prepared for rescue.
56 Rescuing = "rescuing",
57 /// Rescuing node failed.
58 RescueFailed = "rescue failed",
59 /// Waiting for rescue ramdisk to come up.
60 RescueWait = "rescue wait",
61 /// Node is being undeployed (instance deletion).
62 Undeploying = "deleting",
63 /// Undeployment failed before cleaning.
64 UndeployFailed = "error",
65 /// Node is exiting rescue mode.
66 Unrescuing = "unrescuing",
67 /// Exiting rescue mode has failed.
68 UnrescueFailed = "unrescue failed",
69 /// Management access is being verified.
70 Verifying = "verifying",
71
72 /// Reported provision state is not supported.
73 Unknown = ""
74 }
75}
76
77impl ProvisionState {
78 /// Whether the state is stable.
79 ///
80 /// A node will stay in a stable state forever, unless explicitly moved to a different state.
81 /// Error states are not considered stable since they require an action.
82 pub fn is_stable(&self) -> bool {
83 matches!(
84 self,
85 ProvisionState::Active
86 | ProvisionState::Available
87 | ProvisionState::Enroll
88 | ProvisionState::Manageable
89 | ProvisionState::Rescue
90 )
91 }
92
93 /// Whether the state represents a failure.
94 ///
95 /// Failure states are similar to stable states since nodes do not leave them automatically.
96 /// But they require intervention for recovery.
97 pub fn is_failure(&self) -> bool {
98 matches!(
99 self,
100 ProvisionState::AdoptFailed
101 | ProvisionState::CleanFailed
102 | ProvisionState::DeployFailed
103 | ProvisionState::InspectFailed
104 | ProvisionState::RescueFailed
105 | ProvisionState::UndeployFailed
106 | ProvisionState::UnrescueFailed
107 )
108 }
109}
110
111protocol_enum! {
112 /// Target provision state of the node.
113 enum TargetProvisionState {
114 /// Node will be deployed (instance active).
115 Active = "active",
116 /// Node will be undeployed (instance deleted).
117 Deleted = "deleted",
118 /// Node will be available (after instance deletion and cleaning).
119 Available = "available",
120 /// Node will be manageable.
121 Manageable = "manageable",
122 /// Node will be in rescue mode.
123 Rescue = "rescue"
124 }
125}
126
127protocol_enum! {
128 /// Power state of the node.
129 enum PowerState {
130 /// Node is powered off.
131 Off = "power off",
132 /// Node is powered on.
133 On = "power on",
134 /// Error when getting power state.
135 Error = "error"
136 }
137}
138
139protocol_enum! {
140 /// Target power state of the node.
141 enum TargetPowerState {
142 /// Power off the node (hard power off).
143 Off = "power off",
144 /// Power on the node.
145 On = "power on",
146 /// Reboot the node (hard reboot).
147 Reboot = "rebooting",
148 /// Power off the node (soft power off).
149 SoftOff = "soft power off",
150 /// Reboot the node (soft reboot).
151 SoftReboot = "soft rebooting"
152 }
153}
154
155protocol_enum! {
156 /// Interface of a deploy or clean step
157 enum StepInterface {
158 BIOS = "bios",
159 Deploy = "deploy",
160 Management = "management",
161 Power = "power",
162 RAID = "raid"
163 }
164}
165
166protocol_enum! {
167 /// Type of a fault.
168 enum Fault {
169 /// Failure to manage the power state.
170 Power = "power failure",
171 /// Failure of a clean step.
172 Clean = "clean failure",
173 /// Failure to clean up when aborting rescue.
174 RescueAbort = "rescue abort failure"
175 }
176}
177
178#[derive(Debug, Clone, Deserialize)]
179/// A deploy step.
180pub struct DeployStep {
181 /// Interface to which the step belongs.
182 pub interface: StepInterface,
183 /// Step name.
184 #[serde(rename = "step")]
185 pub name: String,
186 /// Priority in which the step runs.
187 pub priority: u32,
188}
189
190#[derive(Debug, Clone, Deserialize)]
191/// A clean step.
192pub struct CleanStep {
193 /// Whether cleaning can be aborted on this step.
194 #[serde(default)]
195 pub abortable: bool,
196 /// Interface to which the step belongs.
197 pub interface: StepInterface,
198 /// Step name.
199 #[serde(rename = "step")]
200 pub name: String,
201 /// Priority in which the step runs.
202 pub priority: u32,
203 /// Whether the step requires an agent ramdisk to be running.
204 #[serde(default = "crate::utils::some_truth")]
205 pub requires_ramdisk: bool,
206}
207
208protocol_enum! {
209 /// Sort key for listing nodes.
210 #[allow(missing_docs)]
211 enum NodeSortKey {
212 AllocationID = "allocation_uuid",
213 AutomatedClean = "automated_clean",
214 BIOSInterface = "bios_interface",
215 BootInterface = "boot_interface",
216 ChassisID = "chassis_uuid",
217 ConductorGroup = "conductor_group",
218 // TODO(dtantsur): is sorting by conductor actually possible?
219 // ConductorName = "conductor",
220 ConsoleEnabled = "console_enabled",
221 ConsoleInterface = "console_interface",
222 CreatedAt = "created_at",
223 DeployInterface = "deploy_interface",
224 Description = "description",
225 Driver = "driver",
226 ID = "uuid",
227 InspectInterface = "inspect_interface",
228 InspectionFinishedAt = "inspection_finished_at",
229 InspectionStartedAt = "inspection_started_at",
230 InstanceID = "instance_uuid",
231 Lessee = "lessee",
232 Maintenance = "maintenance",
233 ManagementInterface = "management_interface",
234 Name = "name",
235 NetworkInterface = "network_interface",
236 Owner = "owner",
237 PowerInterface = "power_interface",
238 PowerState = "power_state",
239 Protected = "protected",
240 ProvisionState = "provision_state",
241 ProvisionUpdatedAt = "provision_updated_at",
242 RAIDInterface = "raid_interface",
243 RescueInterface = "rescue_interface",
244 Reservation = "reservation",
245 ResourceClass = "resource_class",
246 Retired = "retired",
247 Shard = "shard",
248 StorageInterface = "storage_interface",
249 TargetPowerState = "target_power_state",
250 TargetProvisionState = "target_provision_state",
251 UpdatedAt = "updated_at",
252 VendorInterface = "vendor_interface"
253 }
254}
255
256/// Filter for node objects.
257#[derive(Debug, Clone, QueryItem)]
258pub enum NodeFilter {
259 // FIXME(dtantsur): Marker and Limit are always used, move out of Vec<NodeFilter> (in Query)
260 /// Marker (last Node that was fetched).
261 Marker(String),
262 /// Limit on the number of fetched nodes.
263 Limit(usize),
264 /// Key to sort on.
265 SortKey(NodeSortKey),
266 /// Sorting direction.
267 SortDir(SortDir),
268
269 /// Node associated with an instance.
270 Associated(bool),
271 /// Nodes with the given chassis UUID.
272 ChassisID(String),
273 /// Nodes with descriptions containing this string.
274 DescriptionContains(String),
275 /// Nodes that belong to this conductor group.
276 ConductorGroup(String),
277 /// Nodes with this driver.
278 Driver(String),
279 /// Nodes that have a fault of this type.
280 Fault(String),
281 /// Include nodes with a parent node.
282 IncludeChildren(bool),
283 /// Nodes leased by this project or user ID.
284 Lessee(String),
285 /// Nodes in or not in maintenance mode.
286 Maintenance(bool),
287 /// Nodes owned by this project or user ID.
288 Owner(String),
289 /// Nodes that a children of the given node.
290 ParentNode(String),
291 /// Nodes owned by this project ID.
292 Project(String),
293 /// Nodes in the given provision state.
294 ProvisionState(ProvisionState),
295 /// Nodes with this resource class.
296 ResourceClass(String),
297 /// Nodes that are retired.
298 Retired(bool),
299 /// Nodes that have the shard field populated.
300 Sharded(bool),
301 /// Nodes that belong to one of these shards.
302 ShardIn(CommaSeparated<String>),
303}
304
305impl NodeFilter {
306 /// Helper for ShardIn.
307 pub fn shard_in<I>(shards: I) -> NodeFilter
308 where
309 I: IntoIterator,
310 String: From<I::Item>,
311 {
312 NodeFilter::ShardIn(CommaSeparated(shards.into_iter().map(From::from).collect()))
313 }
314}