Skip to main content

openstack_cli_block_storage/v3/volume/
create_313.rs

1// Licensed under the Apache License, Version 2.0 (the "License");
2// you may not use this file except in compliance with the License.
3// You may obtain a copy of the License at
4//
5//     http://www.apache.org/licenses/LICENSE-2.0
6//
7// Unless required by applicable law or agreed to in writing, software
8// distributed under the License is distributed on an "AS IS" BASIS,
9// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10// See the License for the specific language governing permissions and
11// limitations under the License.
12//
13// SPDX-License-Identifier: Apache-2.0
14//
15// WARNING: This file is automatically generated from OpenAPI schema using
16// `openstack-codegenerator`.
17
18//! Create Volume command [microversion = 3.13]
19//!
20//! Wraps invoking of the `v3/volumes` with `POST` method
21
22use clap::Args;
23use eyre::WrapErr;
24use tracing::info;
25
26use openstack_cli_core::cli::CliArgs;
27use openstack_cli_core::error::OpenStackCliError;
28use openstack_cli_core::output::OutputProcessor;
29use openstack_sdk::AsyncOpenStack;
30
31use openstack_cli_core::common::parse_key_val;
32use openstack_sdk::api::QueryAsync;
33use openstack_sdk::api::block_storage::v3::volume::create_313;
34use openstack_types::block_storage::v3::volume::response;
35use serde_json::Value;
36
37/// Creates a new volume.
38///
39/// | | | | --- | --- | | param req: | the request | | param body: | the
40/// request body | | returns: | dict -- the new volume dictionary | | raises
41/// HTTPNotFound, HTTPBadRequest: | | | | |
42#[derive(Args)]
43pub struct VolumeCommand {
44    /// Request Query parameters
45    #[command(flatten)]
46    query: QueryParameters,
47
48    /// Path parameters
49    #[command(flatten)]
50    path: PathParameters,
51
52    /// The dictionary of data to send to the scheduler.
53    #[arg(help_heading = "Body parameters", long, value_name="key=value", value_parser=parse_key_val::<String, Value>)]
54    os_sch_hnt_scheduler_hints: Option<Vec<(String, Value)>>,
55
56    /// A `volume` object.
57    #[command(flatten)]
58    volume: Volume,
59}
60
61/// Query parameters
62#[derive(Args)]
63struct QueryParameters {}
64
65/// Path parameters
66#[derive(Args)]
67struct PathParameters {}
68/// Volume Body data
69#[derive(Args, Clone)]
70struct Volume {
71    /// The name of the availability zone.
72    #[arg(help_heading = "Body parameters", long)]
73    availability_zone: Option<String>,
74
75    /// Set explicit NULL for the availability_zone
76    #[arg(help_heading = "Body parameters", long, action = clap::ArgAction::SetTrue, conflicts_with = "availability_zone")]
77    no_availability_zone: bool,
78
79    /// The UUID of the consistency group.
80    #[arg(help_heading = "Body parameters", long)]
81    consistencygroup_id: Option<String>,
82
83    /// Set explicit NULL for the consistencygroup_id
84    #[arg(help_heading = "Body parameters", long, action = clap::ArgAction::SetTrue, conflicts_with = "consistencygroup_id")]
85    no_consistencygroup_id: bool,
86
87    /// The volume description.
88    #[arg(help_heading = "Body parameters", long)]
89    description: Option<String>,
90
91    /// Set explicit NULL for the description
92    #[arg(help_heading = "Body parameters", long, action = clap::ArgAction::SetTrue, conflicts_with = "description")]
93    no_description: bool,
94
95    #[arg(help_heading = "Body parameters", long)]
96    display_description: Option<String>,
97
98    /// Set explicit NULL for the display_description
99    #[arg(help_heading = "Body parameters", long, action = clap::ArgAction::SetTrue, conflicts_with = "display_description")]
100    no_display_description: bool,
101
102    #[arg(help_heading = "Body parameters", long)]
103    display_name: Option<String>,
104
105    /// Set explicit NULL for the display_name
106    #[arg(help_heading = "Body parameters", long, action = clap::ArgAction::SetTrue, conflicts_with = "display_name")]
107    no_display_name: bool,
108
109    #[arg(help_heading = "Body parameters", long)]
110    group_id: Option<String>,
111
112    /// Set explicit NULL for the group_id
113    #[arg(help_heading = "Body parameters", long, action = clap::ArgAction::SetTrue, conflicts_with = "group_id")]
114    no_group_id: bool,
115
116    #[arg(help_heading = "Body parameters", long)]
117    image_id: Option<String>,
118
119    /// Set explicit NULL for the image_id
120    #[arg(help_heading = "Body parameters", long, action = clap::ArgAction::SetTrue, conflicts_with = "image_id")]
121    no_image_id: bool,
122
123    /// The UUID of the image from which you want to create the volume.
124    /// Required to create a bootable volume.
125    ///
126    /// **New in version 3.46**: Instead of directly consuming a zero-byte
127    /// image that has been created by the Compute service when an instance
128    /// snapshot was requested, the Block Storage service will use the
129    /// `snapshot_id` contained in the `block_device_mapping` image property to
130    /// locate the volume snapshot, and will use that to create the volume
131    /// instead.
132    #[arg(help_heading = "Body parameters", long)]
133    image_ref: Option<String>,
134
135    /// Set explicit NULL for the image_ref
136    #[arg(help_heading = "Body parameters", long, action = clap::ArgAction::SetTrue, conflicts_with = "image_ref")]
137    no_image_ref: bool,
138
139    /// One or more metadata key and value pairs to be associated with the new
140    /// volume.
141    #[arg(help_heading = "Body parameters", long, value_name="key=value", value_parser=parse_key_val::<String, String>)]
142    metadata: Option<Vec<(String, String)>>,
143
144    #[arg(action=clap::ArgAction::Set, help_heading = "Body parameters", long)]
145    multiattach: Option<Option<bool>>,
146
147    /// The volume name.
148    #[arg(help_heading = "Body parameters", long)]
149    name: Option<String>,
150
151    /// Set explicit NULL for the name
152    #[arg(help_heading = "Body parameters", long, action = clap::ArgAction::SetTrue, conflicts_with = "name")]
153    no_name: bool,
154
155    /// The size of the volume, in gibibytes (GiB).
156    #[arg(help_heading = "Body parameters", long)]
157    size: Option<Option<i32>>,
158
159    /// The UUID of the consistency group.
160    #[arg(help_heading = "Body parameters", long)]
161    snapshot_id: Option<String>,
162
163    /// Set explicit NULL for the snapshot_id
164    #[arg(help_heading = "Body parameters", long, action = clap::ArgAction::SetTrue, conflicts_with = "snapshot_id")]
165    no_snapshot_id: bool,
166
167    /// The UUID of the consistency group.
168    #[arg(help_heading = "Body parameters", long)]
169    source_volid: Option<String>,
170
171    /// Set explicit NULL for the source_volid
172    #[arg(help_heading = "Body parameters", long, action = clap::ArgAction::SetTrue, conflicts_with = "source_volid")]
173    no_source_volid: bool,
174
175    /// The volume type (either name or ID). To create an environment with
176    /// multiple-storage back ends, you must specify a volume type. Block
177    /// Storage volume back ends are spawned as children to `cinder- volume`,
178    /// and they are keyed from a unique queue. They are named
179    /// `cinder- volume.HOST.BACKEND`. For example,
180    /// `cinder- volume.ubuntu.lvmdriver`. When a volume is created, the
181    /// scheduler chooses an appropriate back end to handle the request based
182    /// on the volume type. Default is `None`. For information about how to use
183    /// volume types to create multiple- storage back ends, see
184    /// [Configure multiple-storage back ends](https://docs.openstack.org/cinder/latest/admin/blockstorage-multi-backend.html).
185    #[arg(help_heading = "Body parameters", long)]
186    volume_type: Option<String>,
187
188    /// Set explicit NULL for the volume_type
189    #[arg(help_heading = "Body parameters", long, action = clap::ArgAction::SetTrue, conflicts_with = "volume_type")]
190    no_volume_type: bool,
191}
192
193impl VolumeCommand {
194    /// Perform command action
195    pub async fn take_action<C: CliArgs>(
196        &self,
197        parsed_args: &C,
198        client: &mut AsyncOpenStack,
199    ) -> Result<(), OpenStackCliError> {
200        info!("Create Volume");
201
202        let op =
203            OutputProcessor::from_args(parsed_args, Some("block-storage.volume"), Some("create"));
204        op.validate_args(parsed_args)?;
205
206        let mut ep_builder = create_313::Request::builder();
207        ep_builder.header(
208            http::header::HeaderName::from_static("openstack-api-version"),
209            http::header::HeaderValue::from_static("volume 3.13"),
210        );
211
212        // Set body parameters
213        // Set Request.os_sch_hnt_scheduler_hints data
214        if let Some(arg) = &self.os_sch_hnt_scheduler_hints {
215            ep_builder.os_sch_hnt_scheduler_hints(arg.iter().cloned());
216        }
217
218        // Set Request.volume data
219        let args = &self.volume;
220        let mut volume_builder = create_313::VolumeBuilder::default();
221        if let Some(val) = &args.availability_zone {
222            volume_builder.availability_zone(Some(val.into()));
223        } else if args.no_availability_zone {
224            volume_builder.availability_zone(None);
225        }
226
227        if let Some(val) = &args.consistencygroup_id {
228            volume_builder.consistencygroup_id(Some(val.into()));
229        } else if args.no_consistencygroup_id {
230            volume_builder.consistencygroup_id(None);
231        }
232
233        if let Some(val) = &args.description {
234            volume_builder.description(Some(val.into()));
235        } else if args.no_description {
236            volume_builder.description(None);
237        }
238
239        if let Some(val) = &args.display_description {
240            volume_builder.display_description(Some(val.into()));
241        } else if args.no_display_description {
242            volume_builder.display_description(None);
243        }
244
245        if let Some(val) = &args.display_name {
246            volume_builder.display_name(Some(val.into()));
247        } else if args.no_display_name {
248            volume_builder.display_name(None);
249        }
250
251        if let Some(val) = &args.group_id {
252            volume_builder.group_id(Some(val.into()));
253        } else if args.no_group_id {
254            volume_builder.group_id(None);
255        }
256
257        if let Some(val) = &args.image_ref {
258            volume_builder.image_ref(Some(val.into()));
259        } else if args.no_image_ref {
260            volume_builder.image_ref(None);
261        }
262
263        if let Some(val) = &args.image_id {
264            volume_builder.image_id(Some(val.into()));
265        } else if args.no_image_id {
266            volume_builder.image_id(None);
267        }
268
269        if let Some(val) = &args.metadata {
270            volume_builder.metadata(val.iter().cloned());
271        }
272
273        if let Some(val) = &args.multiattach {
274            volume_builder.multiattach(*val);
275        }
276
277        if let Some(val) = &args.name {
278            volume_builder.name(Some(val.into()));
279        } else if args.no_name {
280            volume_builder.name(None);
281        }
282
283        if let Some(val) = &args.size {
284            volume_builder.size(*val);
285        }
286
287        if let Some(val) = &args.snapshot_id {
288            volume_builder.snapshot_id(Some(val.into()));
289        } else if args.no_snapshot_id {
290            volume_builder.snapshot_id(None);
291        }
292
293        if let Some(val) = &args.source_volid {
294            volume_builder.source_volid(Some(val.into()));
295        } else if args.no_source_volid {
296            volume_builder.source_volid(None);
297        }
298
299        if let Some(val) = &args.volume_type {
300            volume_builder.volume_type(Some(val.into()));
301        } else if args.no_volume_type {
302            volume_builder.volume_type(None);
303        }
304
305        ep_builder.volume(
306            volume_builder
307                .build()
308                .wrap_err("error preparing the request data")?,
309        );
310
311        let ep = ep_builder
312            .build()
313            .map_err(|x| OpenStackCliError::EndpointBuild(x.to_string()))?;
314
315        let data: serde_json::Value = ep.query_async(client).await?;
316
317        op.output_single::<response::create::VolumeResponse>(data.clone())?;
318        // Show command specific hints
319        op.show_command_hint()?;
320        Ok(())
321    }
322}