Skip to main content

openstack_cli_block_storage/v3/volume_manage/
create_316.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 VolumeManage command [microversion = 3.16]
19//!
20//! Wraps invoking of the `v3/os-volume-manage` 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_manage::create_316;
34use serde_json::Value;
35
36/// Instruct Cinder to manage a storage object.
37///
38/// Manages an existing backend storage object (e.g. a Linux logical volume or
39/// a SAN disk) by creating the Cinder objects required to manage it, and
40/// possibly renaming the backend storage object (driver dependent)
41///
42/// From an API perspective, this operation behaves very much like a volume
43/// creation operation, except that properties such as image, snapshot and
44/// volume references don't make sense, because we are taking an existing
45/// storage object into Cinder management.
46///
47/// Required HTTP Body:
48///
49/// ```text
50/// {
51///   "volume": {
52///     "host": "<Cinder host on which the existing storage resides>",
53///     "cluster": "<Cinder cluster on which the storage resides>",
54///     "ref": "<Driver-specific reference to existing storage object>"
55///   }
56/// }
57/// ```
58///
59/// See the appropriate Cinder drivers' implementations of the manage_volume
60/// method to find out the accepted format of 'ref'.
61///
62/// This API call will return with an error if any of the above elements are
63/// missing from the request, or if the 'host' element refers to a cinder host
64/// that is not registered.
65///
66/// The volume will later enter the error state if it is discovered that 'ref'
67/// is bad.
68///
69/// Optional elements to 'volume' are:
70///
71/// ```text
72/// name               A name for the new volume.
73/// description        A description for the new volume.
74/// volume_type        ID or name of a volume type to associate with
75///                    the new Cinder volume. Does not necessarily
76///                    guarantee that the managed volume will have the
77///                    properties described in the volume_type. The
78///                    driver may choose to fail if it identifies that
79///                    the specified volume_type is not compatible with
80///                    the backend storage object.
81/// metadata           Key/value pairs to be associated with the new
82///                    volume.
83/// availability_zone  The availability zone to associate with the new
84///                    volume.
85/// bootable           If set to True, marks the volume as bootable.
86/// ```
87#[derive(Args)]
88pub struct VolumeManageCommand {
89    /// Request Query parameters
90    #[command(flatten)]
91    query: QueryParameters,
92
93    /// Path parameters
94    #[command(flatten)]
95    path: PathParameters,
96
97    #[command(flatten)]
98    volume: Volume,
99}
100
101/// Query parameters
102#[derive(Args)]
103struct QueryParameters {}
104
105/// Path parameters
106#[derive(Args)]
107struct PathParameters {}
108/// Volume Body data
109#[derive(Args, Clone)]
110struct Volume {
111    #[arg(help_heading = "Body parameters", long)]
112    availability_zone: Option<String>,
113
114    /// Set explicit NULL for the availability_zone
115    #[arg(help_heading = "Body parameters", long, action = clap::ArgAction::SetTrue, conflicts_with = "availability_zone")]
116    no_availability_zone: bool,
117
118    #[arg(action=clap::ArgAction::Set, help_heading = "Body parameters", long)]
119    bootable: Option<bool>,
120
121    #[arg(help_heading = "Body parameters", long)]
122    cluster: Option<String>,
123
124    /// Set explicit NULL for the cluster
125    #[arg(help_heading = "Body parameters", long, action = clap::ArgAction::SetTrue, conflicts_with = "cluster")]
126    no_cluster: bool,
127
128    #[arg(help_heading = "Body parameters", long)]
129    description: Option<String>,
130
131    /// Set explicit NULL for the description
132    #[arg(help_heading = "Body parameters", long, action = clap::ArgAction::SetTrue, conflicts_with = "description")]
133    no_description: bool,
134
135    #[arg(help_heading = "Body parameters", long)]
136    host: Option<String>,
137
138    /// Set explicit NULL for the host
139    #[arg(help_heading = "Body parameters", long, action = clap::ArgAction::SetTrue, conflicts_with = "host")]
140    no_host: bool,
141
142    #[arg(help_heading = "Body parameters", long, value_name="key=value", value_parser=parse_key_val::<String, String>)]
143    metadata: Option<Vec<(String, String)>>,
144
145    #[arg(help_heading = "Body parameters", long)]
146    name: Option<String>,
147
148    /// Set explicit NULL for the name
149    #[arg(help_heading = "Body parameters", long, action = clap::ArgAction::SetTrue, conflicts_with = "name")]
150    no_name: bool,
151
152    #[arg(help_heading = "Body parameters", long, value_name="JSON", value_parser=openstack_cli_core::common::parse_json)]
153    _ref: Value,
154
155    #[arg(help_heading = "Body parameters", long)]
156    volume_type: Option<String>,
157
158    /// Set explicit NULL for the volume_type
159    #[arg(help_heading = "Body parameters", long, action = clap::ArgAction::SetTrue, conflicts_with = "volume_type")]
160    no_volume_type: bool,
161}
162
163impl VolumeManageCommand {
164    /// Perform command action
165    pub async fn take_action<C: CliArgs>(
166        &self,
167        parsed_args: &C,
168        client: &mut AsyncOpenStack,
169    ) -> Result<(), OpenStackCliError> {
170        info!("Create VolumeManage");
171
172        let op = OutputProcessor::from_args(
173            parsed_args,
174            Some("block-storage.volume_manage"),
175            Some("create"),
176        );
177        op.validate_args(parsed_args)?;
178
179        let mut ep_builder = create_316::Request::builder();
180        ep_builder.header(
181            http::header::HeaderName::from_static("openstack-api-version"),
182            http::header::HeaderValue::from_static("volume 3.16"),
183        );
184
185        // Set body parameters
186        // Set Request.volume data
187        let args = &self.volume;
188        let mut volume_builder = create_316::VolumeBuilder::default();
189        if let Some(val) = &args.availability_zone {
190            volume_builder.availability_zone(Some(val.into()));
191        } else if args.no_availability_zone {
192            volume_builder.availability_zone(None);
193        }
194
195        if let Some(val) = &args.bootable {
196            volume_builder.bootable(*val);
197        }
198
199        if let Some(val) = &args.cluster {
200            volume_builder.cluster(Some(val.into()));
201        } else if args.no_cluster {
202            volume_builder.cluster(None);
203        }
204
205        if let Some(val) = &args.description {
206            volume_builder.description(Some(val.into()));
207        } else if args.no_description {
208            volume_builder.description(None);
209        }
210
211        if let Some(val) = &args.host {
212            volume_builder.host(Some(val.into()));
213        } else if args.no_host {
214            volume_builder.host(None);
215        }
216
217        if let Some(val) = &args.metadata {
218            volume_builder.metadata(val.iter().cloned());
219        }
220
221        if let Some(val) = &args.name {
222            volume_builder.name(Some(val.into()));
223        } else if args.no_name {
224            volume_builder.name(None);
225        }
226
227        volume_builder._ref(args._ref.clone());
228
229        if let Some(val) = &args.volume_type {
230            volume_builder.volume_type(Some(val.into()));
231        } else if args.no_volume_type {
232            volume_builder.volume_type(None);
233        }
234
235        ep_builder.volume(
236            volume_builder
237                .build()
238                .wrap_err("error preparing the request data")?,
239        );
240
241        let ep = ep_builder
242            .build()
243            .map_err(|x| OpenStackCliError::EndpointBuild(x.to_string()))?;
244        openstack_sdk::api::ignore(ep).query_async(client).await?;
245        // Show command specific hints
246        op.show_command_hint()?;
247        Ok(())
248    }
249}