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}