openstack_cli_block_storage/v3/volume/
create_30.rs1use 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_30;
34use openstack_types::block_storage::v3::volume::response;
35use serde_json::Value;
36
37#[derive(Args)]
43pub struct VolumeCommand {
44 #[command(flatten)]
46 query: QueryParameters,
47
48 #[command(flatten)]
50 path: PathParameters,
51
52 #[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 #[command(flatten)]
58 volume: Volume,
59}
60
61#[derive(Args)]
63struct QueryParameters {}
64
65#[derive(Args)]
67struct PathParameters {}
68#[derive(Args, Clone)]
70struct Volume {
71 #[arg(help_heading = "Body parameters", long)]
73 availability_zone: Option<String>,
74
75 #[arg(help_heading = "Body parameters", long, action = clap::ArgAction::SetTrue, conflicts_with = "availability_zone")]
77 no_availability_zone: bool,
78
79 #[arg(help_heading = "Body parameters", long)]
81 consistencygroup_id: Option<String>,
82
83 #[arg(help_heading = "Body parameters", long, action = clap::ArgAction::SetTrue, conflicts_with = "consistencygroup_id")]
85 no_consistencygroup_id: bool,
86
87 #[arg(help_heading = "Body parameters", long)]
89 description: Option<String>,
90
91 #[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 #[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 #[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 image_id: Option<String>,
111
112 #[arg(help_heading = "Body parameters", long, action = clap::ArgAction::SetTrue, conflicts_with = "image_id")]
114 no_image_id: bool,
115
116 #[arg(help_heading = "Body parameters", long)]
126 image_ref: Option<String>,
127
128 #[arg(help_heading = "Body parameters", long, action = clap::ArgAction::SetTrue, conflicts_with = "image_ref")]
130 no_image_ref: bool,
131
132 #[arg(help_heading = "Body parameters", long, value_name="key=value", value_parser=parse_key_val::<String, String>)]
135 metadata: Option<Vec<(String, String)>>,
136
137 #[arg(action=clap::ArgAction::Set, help_heading = "Body parameters", long)]
138 multiattach: Option<Option<bool>>,
139
140 #[arg(help_heading = "Body parameters", long)]
142 name: Option<String>,
143
144 #[arg(help_heading = "Body parameters", long, action = clap::ArgAction::SetTrue, conflicts_with = "name")]
146 no_name: bool,
147
148 #[arg(help_heading = "Body parameters", long)]
150 size: Option<Option<i32>>,
151
152 #[arg(help_heading = "Body parameters", long)]
154 snapshot_id: Option<String>,
155
156 #[arg(help_heading = "Body parameters", long, action = clap::ArgAction::SetTrue, conflicts_with = "snapshot_id")]
158 no_snapshot_id: bool,
159
160 #[arg(help_heading = "Body parameters", long)]
162 source_volid: Option<String>,
163
164 #[arg(help_heading = "Body parameters", long, action = clap::ArgAction::SetTrue, conflicts_with = "source_volid")]
166 no_source_volid: bool,
167
168 #[arg(help_heading = "Body parameters", long)]
179 volume_type: Option<String>,
180
181 #[arg(help_heading = "Body parameters", long, action = clap::ArgAction::SetTrue, conflicts_with = "volume_type")]
183 no_volume_type: bool,
184}
185
186impl VolumeCommand {
187 pub async fn take_action<C: CliArgs>(
189 &self,
190 parsed_args: &C,
191 client: &mut AsyncOpenStack,
192 ) -> Result<(), OpenStackCliError> {
193 info!("Create Volume");
194
195 let op =
196 OutputProcessor::from_args(parsed_args, Some("block-storage.volume"), Some("create"));
197 op.validate_args(parsed_args)?;
198
199 let mut ep_builder = create_30::Request::builder();
200 ep_builder.header(
201 http::header::HeaderName::from_static("openstack-api-version"),
202 http::header::HeaderValue::from_static("volume 3.0"),
203 );
204
205 if let Some(arg) = &self.os_sch_hnt_scheduler_hints {
208 ep_builder.os_sch_hnt_scheduler_hints(arg.iter().cloned());
209 }
210
211 let args = &self.volume;
213 let mut volume_builder = create_30::VolumeBuilder::default();
214 if let Some(val) = &args.availability_zone {
215 volume_builder.availability_zone(Some(val.into()));
216 } else if args.no_availability_zone {
217 volume_builder.availability_zone(None);
218 }
219
220 if let Some(val) = &args.consistencygroup_id {
221 volume_builder.consistencygroup_id(Some(val.into()));
222 } else if args.no_consistencygroup_id {
223 volume_builder.consistencygroup_id(None);
224 }
225
226 if let Some(val) = &args.description {
227 volume_builder.description(Some(val.into()));
228 } else if args.no_description {
229 volume_builder.description(None);
230 }
231
232 if let Some(val) = &args.display_description {
233 volume_builder.display_description(Some(val.into()));
234 } else if args.no_display_description {
235 volume_builder.display_description(None);
236 }
237
238 if let Some(val) = &args.display_name {
239 volume_builder.display_name(Some(val.into()));
240 } else if args.no_display_name {
241 volume_builder.display_name(None);
242 }
243
244 if let Some(val) = &args.image_ref {
245 volume_builder.image_ref(Some(val.into()));
246 } else if args.no_image_ref {
247 volume_builder.image_ref(None);
248 }
249
250 if let Some(val) = &args.image_id {
251 volume_builder.image_id(Some(val.into()));
252 } else if args.no_image_id {
253 volume_builder.image_id(None);
254 }
255
256 if let Some(val) = &args.metadata {
257 volume_builder.metadata(val.iter().cloned());
258 }
259
260 if let Some(val) = &args.multiattach {
261 volume_builder.multiattach(*val);
262 }
263
264 if let Some(val) = &args.name {
265 volume_builder.name(Some(val.into()));
266 } else if args.no_name {
267 volume_builder.name(None);
268 }
269
270 if let Some(val) = &args.size {
271 volume_builder.size(*val);
272 }
273
274 if let Some(val) = &args.snapshot_id {
275 volume_builder.snapshot_id(Some(val.into()));
276 } else if args.no_snapshot_id {
277 volume_builder.snapshot_id(None);
278 }
279
280 if let Some(val) = &args.source_volid {
281 volume_builder.source_volid(Some(val.into()));
282 } else if args.no_source_volid {
283 volume_builder.source_volid(None);
284 }
285
286 if let Some(val) = &args.volume_type {
287 volume_builder.volume_type(Some(val.into()));
288 } else if args.no_volume_type {
289 volume_builder.volume_type(None);
290 }
291
292 ep_builder.volume(
293 volume_builder
294 .build()
295 .wrap_err("error preparing the request data")?,
296 );
297
298 let ep = ep_builder
299 .build()
300 .map_err(|x| OpenStackCliError::EndpointBuild(x.to_string()))?;
301
302 let data: serde_json::Value = ep.query_async(client).await?;
303
304 op.output_single::<response::create::VolumeResponse>(data.clone())?;
305 op.show_command_hint()?;
307 Ok(())
308 }
309}