Skip to main content

openstack_cli_compute/v2/server/
create_274.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 Server command [microversion = 2.74]
19//!
20//! Wraps invoking of the `v2.1/servers` 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 clap::ValueEnum;
32use openstack_cli_core::common::parse_key_val;
33use openstack_sdk::api::QueryAsync;
34use openstack_sdk::api::compute::v2::server::create_274;
35use openstack_types::compute::v2::server::response;
36use serde_json::Value;
37
38/// Creates a server.
39///
40/// The progress of this operation depends on the location of the requested
41/// image, network I/O, host load, selected flavor, and other factors.
42///
43/// To check the progress of the request, make a `GET /servers/{id}` request.
44/// This call returns a progress attribute, which is a percentage value from 0
45/// to 100.
46///
47/// The `Location` header returns the full URL to the newly created server and
48/// is available as a `self` and `bookmark` link in the server representation.
49///
50/// When you create a server, the response shows only the server ID, its links,
51/// and the admin password. You can get additional attributes through
52/// subsequent `GET` requests on the server.
53///
54/// Include the `block_device_mapping_v2` parameter in the create request body
55/// to boot a server from a volume.
56///
57/// Include the `key_name` parameter in the create request body to add a
58/// keypair to the server when you create it. To create a keypair, make a
59/// [create keypair](https://docs.openstack.org/api-ref/compute/#create-or-import-keypair)
60/// request.
61///
62/// **Preconditions**
63///
64/// **Asynchronous postconditions**
65///
66/// **Troubleshooting**
67///
68/// Normal response codes: 202
69///
70/// Error response codes: badRequest(400), unauthorized(401), forbidden(403),
71/// itemNotFound(404), conflict(409)
72#[derive(Args)]
73#[command(about = "Create Server (microversion = 2.74)")]
74pub struct ServerCommand {
75    /// Request Query parameters
76    #[command(flatten)]
77    query: QueryParameters,
78
79    /// Path parameters
80    #[command(flatten)]
81    path: PathParameters,
82
83    /// The dictionary of data to send to the scheduler. Alternatively, you can
84    /// specify `OS-SCH-HNT:scheduler_hints` as the key in the request body.
85    ///
86    /// Note
87    ///
88    /// This is a top-level key in the request body, not part of the server
89    /// portion of the request body.
90    ///
91    /// There are a few caveats with scheduler hints:
92    ///
93    /// - The request validation schema is per hint. For example, some require
94    ///   a single string value, and some accept a list of values.
95    /// - Hints are only used based on the cloud scheduler configuration, which
96    ///   varies per deployment.
97    /// - Hints are pluggable per deployment, meaning that a cloud can have
98    ///   custom hints which may not be available in another cloud.
99    ///
100    /// For these reasons, it is important to consult each cloud’s user
101    /// documentation to know what is available for scheduler hints.
102    #[command(flatten)]
103    os_scheduler_hints: Option<OsSchedulerHints>,
104
105    /// A `server` object.
106    #[command(flatten)]
107    server: Server,
108}
109
110/// Query parameters
111#[derive(Args)]
112struct QueryParameters {}
113
114/// Path parameters
115#[derive(Args)]
116struct PathParameters {}
117/// OsSchedulerHints Body data
118#[derive(Args, Clone)]
119struct OsSchedulerHints {
120    /// Schedule the server on a host in the network specified with this
121    /// parameter and a cidr (`os:scheduler_hints.cidr`). It is available when
122    /// `SimpleCIDRAffinityFilter` is available on cloud side.
123    #[arg(help_heading = "Body parameters", long)]
124    build_near_host_ip: Option<String>,
125
126    /// Schedule the server on a host in the network specified with an IP
127    /// address (`os:scheduler_hints:build_near_host_ip`) and this parameter.
128    /// If `os:scheduler_hints:build_near_host_ip` is specified and this
129    /// parameter is omitted, `/24` is used. It is available when
130    /// `SimpleCIDRAffinityFilter` is available on cloud side.
131    #[arg(help_heading = "Body parameters", long)]
132    cidr: Option<String>,
133
134    /// A list of cell routes or a cell route (string). Schedule the server in
135    /// a cell that is not specified. It is available when
136    /// `DifferentCellFilter` is available on cloud side that is cell v1
137    /// environment.
138    ///
139    /// Parameter is an array, may be provided multiple times.
140    #[arg(action=clap::ArgAction::Append, help_heading = "Body parameters", long)]
141    different_cell: Option<Vec<String>>,
142
143    /// A list of server UUIDs or a server UUID. Schedule the server on a
144    /// different host from a set of servers. It is available when
145    /// `DifferentHostFilter` is available on cloud side.
146    ///
147    /// Parameter is an array, may be provided multiple times.
148    #[arg(action=clap::ArgAction::Append, help_heading = "Body parameters", long)]
149    different_host: Option<Vec<String>>,
150
151    /// The server group UUID. Schedule the server according to a policy of the
152    /// server group (`anti-affinity`, `affinity`, `soft-anti-affinity` or
153    /// `soft-affinity`). It is available when `ServerGroupAffinityFilter`,
154    /// `ServerGroupAntiAffinityFilter`, `ServerGroupSoftAntiAffinityWeigher`,
155    /// `ServerGroupSoftAffinityWeigher` are available on cloud side.
156    ///
157    /// Parameter is an array, may be provided multiple times.
158    #[arg(action=clap::ArgAction::Append, help_heading = "Body parameters", long)]
159    group: Option<Vec<String>>,
160
161    /// Schedule the server by using a custom filter in JSON format. For
162    /// example:
163    ///
164    /// ```text
165    /// "query": "[\">=\",\"$free_ram_mb\",1024]"
166    /// ```
167    ///
168    /// It is available when `JsonFilter` is available on cloud side.
169    #[arg(help_heading = "Body parameters", long, value_name="JSON", value_parser=openstack_cli_core::common::parse_json)]
170    query: Option<Value>,
171
172    /// A list of server UUIDs or a server UUID. Schedule the server on the
173    /// same host as another server in a set of servers. It is available when
174    /// `SameHostFilter` is available on cloud side.
175    ///
176    /// Parameter is an array, may be provided multiple times.
177    #[arg(action=clap::ArgAction::Append, help_heading = "Body parameters", long)]
178    same_host: Option<Vec<String>>,
179
180    /// A target cell name. Schedule the server in a host in the cell
181    /// specified. It is available when `TargetCellFilter` is available on
182    /// cloud side that is cell v1 environment.
183    #[arg(help_heading = "Body parameters", long)]
184    target_cell: Option<String>,
185}
186
187#[derive(Clone, Eq, Ord, PartialEq, PartialOrd, ValueEnum)]
188enum OsDcfDiskConfig {
189    Auto,
190    Manual,
191}
192
193#[derive(Clone, Eq, Ord, PartialEq, PartialOrd, ValueEnum)]
194enum NetworksStringEnum {
195    Auto,
196    None,
197}
198
199/// ServerNetworks Body data
200#[derive(Args, Clone)]
201#[group(required = true, multiple = false)]
202struct ServerNetworks {
203    #[arg(action=clap::ArgAction::SetTrue, help_heading = "Body parameters", long, required=false)]
204    auto_networks: bool,
205
206    /// Parameter is an array, may be provided multiple times.
207    #[arg(action=clap::ArgAction::Append, help_heading = "Body parameters", long, value_name="JSON", value_parser=openstack_cli_core::common::parse_json)]
208    networks: Option<Vec<Value>>,
209
210    #[arg(action=clap::ArgAction::SetTrue, help_heading = "Body parameters", long, required=false)]
211    none_networks: bool,
212}
213
214/// Server Body data
215#[derive(Args, Clone)]
216struct Server {
217    /// IPv4 address that should be used to access this server.
218    #[arg(help_heading = "Body parameters", long)]
219    access_ipv4: Option<String>,
220
221    /// IPv6 address that should be used to access this server.
222    #[arg(help_heading = "Body parameters", long)]
223    access_ipv6: Option<String>,
224
225    /// The administrative password of the server. If you omit this parameter,
226    /// the operation generates a new password.
227    #[arg(help_heading = "Body parameters", long)]
228    admin_pass: Option<String>,
229
230    /// A target cell name. Schedule the server in a host in the cell
231    /// specified. It is available when `TargetCellFilter` is available on
232    /// cloud side that is cell v1 environment.
233    #[arg(help_heading = "Body parameters", long)]
234    availability_zone: Option<String>,
235
236    /// Parameter is an array, may be provided multiple times.
237    #[arg(action=clap::ArgAction::Append, help_heading = "Body parameters", long, value_name="JSON", value_parser=openstack_cli_core::common::parse_json)]
238    block_device_mapping: Option<Vec<Value>>,
239
240    /// Enables fine grained control of the block device mapping for an
241    /// instance. This is typically used for booting servers from volumes. An
242    /// example format would look as follows:
243    ///
244    /// > ```text
245    /// > "block_device_mapping_v2": [{
246    /// >     "boot_index": "0",
247    /// >     "uuid": "ac408821-c95a-448f-9292-73986c790911",
248    /// >     "source_type": "image",
249    /// >     "volume_size": "25",
250    /// >     "destination_type": "volume",
251    /// >     "delete_on_termination": true,
252    /// >     "tag": "disk1",
253    /// >     "disk_bus": "scsi"}]
254    /// > ```
255    ///
256    /// In microversion 2.32, `tag` is an optional string attribute that can be
257    /// used to assign a tag to the block device. This tag is then exposed to
258    /// the guest in the metadata API and the config drive and is associated to
259    /// hardware metadata for that block device, such as bus (ex: SCSI), bus
260    /// address (ex: 1:0:2:0), and serial.
261    ///
262    /// A bug has caused the `tag` attribute to no longer be accepted starting
263    /// with version 2.33. It has been restored in version 2.42.
264    ///
265    /// Parameter is an array, may be provided multiple times.
266    #[arg(action=clap::ArgAction::Append, help_heading = "Body parameters", long, value_name="JSON", value_parser=openstack_cli_core::common::parse_json)]
267    block_device_mapping_v2: Option<Vec<Value>>,
268
269    /// Indicates whether a config drive enables metadata injection. The
270    /// config_drive setting provides information about a drive that the
271    /// instance can mount at boot time. The instance reads files from the
272    /// drive to get information that is normally available through the
273    /// metadata service. This metadata is different from the user data. Not
274    /// all cloud providers enable the `config_drive`. Read more in the
275    /// [OpenStack End User Guide](https://docs.openstack.org/nova/latest/user/config-drive.html).
276    #[arg(action=clap::ArgAction::Set, help_heading = "Body parameters", long)]
277    config_drive: Option<bool>,
278
279    /// A free form description of the server. Limited to 255 characters in
280    /// length. Before microversion 2.19 this was set to the server name.
281    ///
282    /// **New in version 2.19**
283    #[arg(help_heading = "Body parameters", long)]
284    description: Option<String>,
285
286    /// Set explicit NULL for the description
287    #[arg(help_heading = "Body parameters", long, action = clap::ArgAction::SetTrue, conflicts_with = "description")]
288    no_description: bool,
289
290    /// The flavor reference, as an ID (including a UUID) or full URL, for the
291    /// flavor for your server instance.
292    #[arg(help_heading = "Body parameters", long)]
293    flavor_ref: String,
294
295    /// The hostname of the hypervisor on which the server is to be created.
296    /// The API will return 400 if no hypervisors are found with the given
297    /// hostname. By default, it can be specified by administrators only.
298    ///
299    /// **New in version 2.74**
300    #[arg(help_heading = "Body parameters", long)]
301    host: Option<String>,
302
303    /// The hostname of the hypervisor on which the server is to be created.
304    /// The API will return 400 if no hypervisors are found with the given
305    /// hostname. By default, it can be specified by administrators only.
306    ///
307    /// **New in version 2.74**
308    #[arg(help_heading = "Body parameters", long)]
309    hypervisor_hostname: Option<String>,
310
311    /// The UUID of the image to use for your server instance. This is not
312    /// required in case of boot from volume. In all other cases it is required
313    /// and must be a valid UUID otherwise API will return 400.
314    #[arg(help_heading = "Body parameters", long)]
315    image_ref: Option<String>,
316
317    /// A target cell name. Schedule the server in a host in the cell
318    /// specified. It is available when `TargetCellFilter` is available on
319    /// cloud side that is cell v1 environment.
320    #[arg(help_heading = "Body parameters", long)]
321    key_name: Option<String>,
322
323    #[arg(help_heading = "Body parameters", long)]
324    max_count: Option<i32>,
325
326    /// Metadata key and value pairs. The maximum size of the metadata key and
327    /// value is 255 bytes each.
328    #[arg(help_heading = "Body parameters", long, value_name="key=value", value_parser=parse_key_val::<String, String>)]
329    metadata: Option<Vec<(String, String)>>,
330
331    #[arg(help_heading = "Body parameters", long)]
332    min_count: Option<i32>,
333
334    /// A target cell name. Schedule the server in a host in the cell
335    /// specified. It is available when `TargetCellFilter` is available on
336    /// cloud side that is cell v1 environment.
337    #[arg(help_heading = "Body parameters", long)]
338    name: String,
339
340    /// A list of `network` object. Required parameter when there are multiple
341    /// networks defined for the tenant. When you do not specify the networks
342    /// parameter, the server attaches to the only network created for the
343    /// current tenant. Optionally, you can create one or more NICs on the
344    /// server. To provision the server instance with a NIC for a network,
345    /// specify the UUID of the network in the `uuid` attribute in a `networks`
346    /// object. To provision the server instance with a NIC for an already
347    /// existing port, specify the port-id in the `port` attribute in a
348    /// `networks` object.
349    ///
350    /// If multiple networks are defined, the order in which they appear in the
351    /// guest operating system will not necessarily reflect the order in which
352    /// they are given in the server boot request. Guests should therefore not
353    /// depend on device order to deduce any information about their network
354    /// devices. Instead, device role tags should be used: introduced in 2.32,
355    /// broken in 2.37, and re-introduced and fixed in 2.42, the `tag` is an
356    /// optional, string attribute that can be used to assign a tag to a
357    /// virtual network interface. This tag is then exposed to the guest in the
358    /// metadata API and the config drive and is associated to hardware
359    /// metadata for that network interface, such as bus (ex: PCI), bus address
360    /// (ex: 0000:00:02.0), and MAC address.
361    ///
362    /// A bug has caused the `tag` attribute to no longer be accepted starting
363    /// with version 2.37. Therefore, network interfaces could only be tagged
364    /// in versions 2.32 to 2.36 inclusively. Version 2.42 has restored the
365    /// `tag` attribute.
366    ///
367    /// Starting with microversion 2.37, this field is required and the special
368    /// string values *auto* and *none* can be specified for networks. *auto*
369    /// tells the Compute service to use a network that is available to the
370    /// project, if one exists. If one does not exist, the Compute service will
371    /// attempt to automatically allocate a network for the project (if
372    /// possible). *none* tells the Compute service to not allocate a network
373    /// for the instance. The *auto* and *none* values cannot be used with any
374    /// other network values, including other network uuids, ports, fixed IPs
375    /// or device tags. These are requested as strings for the networks value,
376    /// not in a list. See the associated example.
377    #[command(flatten)]
378    networks: ServerNetworks,
379
380    /// Controls how the API partitions the disk when you create, rebuild, or
381    /// resize servers. A server inherits the `OS-DCF:diskConfig` value from
382    /// the image from which it was created, and an image inherits the
383    /// `OS-DCF:diskConfig` value from the server from which it was created. To
384    /// override the inherited setting, you can include this attribute in the
385    /// request body of a server create, rebuild, or resize request. If the
386    /// `OS-DCF:diskConfig` value for an image is `MANUAL`, you cannot create a
387    /// server from that image and set its `OS-DCF:diskConfig` value to `AUTO`.
388    /// A valid value is:
389    ///
390    /// - `AUTO`. The API builds the server with a single partition the size of
391    ///   the target flavor disk. The API automatically adjusts the file system
392    ///   to fit the entire partition.
393    /// - `MANUAL`. The API builds the server by using whatever partition
394    ///   scheme and file system is in the source image. If the target flavor
395    ///   disk is larger, the API does not partition the remaining disk space.
396    #[arg(help_heading = "Body parameters", long)]
397    os_dcf_disk_config: Option<OsDcfDiskConfig>,
398
399    /// Indicates whether a config drive enables metadata injection. The
400    /// config_drive setting provides information about a drive that the
401    /// instance can mount at boot time. The instance reads files from the
402    /// drive to get information that is normally available through the
403    /// metadata service. This metadata is different from the user data. Not
404    /// all cloud providers enable the `config_drive`. Read more in the
405    /// [OpenStack End User Guide](https://docs.openstack.org/nova/latest/user/config-drive.html).
406    #[arg(action=clap::ArgAction::Set, help_heading = "Body parameters", long)]
407    return_reservation_id: Option<bool>,
408
409    /// One or more security groups. Specify the name of the security group in
410    /// the `name` attribute. If you omit this attribute, the API creates the
411    /// server in the `default` security group. Requested security groups are
412    /// not applied to pre-existing ports.
413    ///
414    /// Parameter is an array, may be provided multiple times.
415    #[arg(action=clap::ArgAction::Append, help_heading = "Body parameters", long)]
416    security_groups: Option<Vec<String>>,
417
418    /// A list of tags. Tags have the following restrictions:
419    ///
420    /// - Tag is a Unicode bytestring no longer than 60 characters.
421    /// - Tag is a non-empty string.
422    /// - ‘/’ is not allowed to be in a tag name
423    /// - Comma is not allowed to be in a tag name in order to simplify
424    ///   requests that specify lists of tags
425    /// - All other characters are allowed to be in a tag name
426    /// - Each server can have up to 50 tags.
427    ///
428    /// **New in version 2.52**
429    ///
430    /// Parameter is an array, may be provided multiple times.
431    #[arg(action=clap::ArgAction::Append, help_heading = "Body parameters", long)]
432    tags: Option<Vec<String>>,
433
434    /// A list of trusted certificate IDs, which are used during image
435    /// signature verification to verify the signing certificate. The list is
436    /// restricted to a maximum of 50 IDs. This parameter is optional in server
437    /// create requests if allowed by policy, and is not supported for
438    /// volume-backed instances.
439    ///
440    /// **New in version 2.63**
441    ///
442    /// Parameter is an array, may be provided multiple times.
443    #[arg(action=clap::ArgAction::Append, help_heading = "Body parameters", long)]
444    trusted_image_certificates: Option<Vec<String>>,
445
446    /// Configuration information or scripts to use upon launch. Must be Base64
447    /// encoded. Restricted to 65535 bytes.
448    ///
449    /// Note
450    ///
451    /// The `null` value allowed in Nova legacy v2 API, but due to the strict
452    /// input validation, it isn’t allowed in Nova v2.1 API.
453    #[arg(help_heading = "Body parameters", long)]
454    user_data: Option<String>,
455}
456
457impl ServerCommand {
458    /// Perform command action
459    pub async fn take_action<C: CliArgs>(
460        &self,
461        parsed_args: &C,
462        client: &mut AsyncOpenStack,
463    ) -> Result<(), OpenStackCliError> {
464        info!("Create Server");
465
466        let op = OutputProcessor::from_args(parsed_args, Some("compute.server"), Some("create"));
467        op.validate_args(parsed_args)?;
468
469        let mut ep_builder = create_274::Request::builder();
470        ep_builder.header(
471            http::header::HeaderName::from_static("openstack-api-version"),
472            http::header::HeaderValue::from_static("compute 2.74"),
473        );
474
475        // Set body parameters
476        // Set Request.os_scheduler_hints data
477        if let Some(args) = &self.os_scheduler_hints {
478            let mut os_scheduler_hints_builder = create_274::OsSchedulerHintsBuilder::default();
479            if let Some(val) = &args.build_near_host_ip {
480                os_scheduler_hints_builder.build_near_host_ip(val);
481            }
482
483            if let Some(val) = &args.cidr {
484                os_scheduler_hints_builder.cidr(val);
485            }
486
487            if let Some(val) = &args.different_cell {
488                os_scheduler_hints_builder
489                    .different_cell(val.iter().map(Into::into).collect::<Vec<_>>());
490            }
491
492            if let Some(val) = &args.different_host {
493                os_scheduler_hints_builder
494                    .different_host(val.iter().map(Into::into).collect::<Vec<_>>());
495            }
496
497            if let Some(val) = &args.group {
498                os_scheduler_hints_builder.group(val.iter().map(Into::into).collect::<Vec<_>>());
499            }
500
501            if let Some(val) = &args.query {
502                os_scheduler_hints_builder.query(val.clone());
503            }
504
505            if let Some(val) = &args.same_host {
506                os_scheduler_hints_builder
507                    .same_host(val.iter().map(Into::into).collect::<Vec<_>>());
508            }
509
510            if let Some(val) = &args.target_cell {
511                os_scheduler_hints_builder.target_cell(val);
512            }
513
514            ep_builder.os_scheduler_hints(
515                os_scheduler_hints_builder
516                    .build()
517                    .wrap_err("error preparing the request data")?,
518            );
519        }
520
521        // Set Request.server data
522        let args = &self.server;
523        let mut server_builder = create_274::ServerBuilder::default();
524        if let Some(val) = &args.os_dcf_disk_config {
525            let tmp = match val {
526                OsDcfDiskConfig::Auto => create_274::OsDcfDiskConfig::Auto,
527                OsDcfDiskConfig::Manual => create_274::OsDcfDiskConfig::Manual,
528            };
529            server_builder.os_dcf_disk_config(tmp);
530        }
531
532        if let Some(val) = &args.access_ipv4 {
533            server_builder.access_ipv4(val);
534        }
535
536        if let Some(val) = &args.access_ipv6 {
537            server_builder.access_ipv6(val);
538        }
539
540        if let Some(val) = &args.admin_pass {
541            server_builder.admin_pass(val);
542        }
543
544        if let Some(val) = &args.availability_zone {
545            server_builder.availability_zone(val);
546        }
547
548        if let Some(val) = &args.block_device_mapping {
549            let block_device_mapping_builder: Vec<create_274::BlockDeviceMapping> = val
550                .iter()
551                .flat_map(|v| {
552                    serde_json::from_value::<create_274::BlockDeviceMapping>(v.to_owned())
553                })
554                .collect::<Vec<create_274::BlockDeviceMapping>>();
555            server_builder.block_device_mapping(block_device_mapping_builder);
556        }
557
558        if let Some(val) = &args.block_device_mapping_v2 {
559            let block_device_mapping_v2_builder: Vec<create_274::BlockDeviceMappingV2> = val
560                .iter()
561                .flat_map(|v| {
562                    serde_json::from_value::<create_274::BlockDeviceMappingV2>(v.to_owned())
563                })
564                .collect::<Vec<create_274::BlockDeviceMappingV2>>();
565            server_builder.block_device_mapping_v2(block_device_mapping_v2_builder);
566        }
567
568        if let Some(val) = &args.config_drive {
569            server_builder.config_drive(*val);
570        }
571
572        if let Some(val) = &args.description {
573            server_builder.description(Some(val.into()));
574        } else if args.no_description {
575            server_builder.description(None);
576        }
577
578        server_builder.flavor_ref(&args.flavor_ref);
579
580        if let Some(val) = &args.host {
581            server_builder.host(val);
582        }
583
584        if let Some(val) = &args.hypervisor_hostname {
585            server_builder.hypervisor_hostname(val);
586        }
587
588        if let Some(val) = &args.image_ref {
589            server_builder.image_ref(val);
590        }
591
592        if let Some(val) = &args.key_name {
593            server_builder.key_name(val);
594        }
595
596        if let Some(val) = &args.max_count {
597            server_builder.max_count(*val);
598        }
599
600        if let Some(val) = &args.metadata {
601            server_builder.metadata(val.iter().cloned());
602        }
603
604        if let Some(val) = &args.min_count {
605            server_builder.min_count(*val);
606        }
607
608        server_builder.name(&args.name);
609
610        if args.networks.auto_networks {
611            server_builder.networks(create_274::ServerNetworks::F2(
612                create_274::NetworksStringEnum::Auto,
613            ));
614        }
615
616        if let Some(data) = &args.networks.networks {
617            let networks_builder: Vec<create_274::Networks> = data
618                .iter()
619                .flat_map(|v| serde_json::from_value::<create_274::Networks>(v.to_owned()))
620                .collect();
621            server_builder.networks(create_274::ServerNetworks::F1(networks_builder));
622        }
623        if args.networks.none_networks {
624            server_builder.networks(create_274::ServerNetworks::F2(
625                create_274::NetworksStringEnum::None,
626            ));
627        }
628
629        if let Some(val) = &args.return_reservation_id {
630            server_builder.return_reservation_id(*val);
631        }
632
633        if let Some(val) = &args.security_groups {
634            let security_groups_builder: Vec<create_274::SecurityGroups> = val
635                .iter()
636                .flat_map(|v| create_274::SecurityGroupsBuilder::default().name(v).build())
637                .collect();
638            server_builder.security_groups(security_groups_builder);
639        }
640
641        if let Some(val) = &args.tags {
642            server_builder.tags(val.iter().map(Into::into).collect::<Vec<_>>());
643        }
644
645        if let Some(val) = &args.trusted_image_certificates {
646            server_builder
647                .trusted_image_certificates(val.iter().map(Into::into).collect::<Vec<_>>());
648        }
649
650        if let Some(val) = &args.user_data {
651            server_builder.user_data(val);
652        }
653
654        ep_builder.server(
655            server_builder
656                .build()
657                .wrap_err("error preparing the request data")?,
658        );
659
660        let ep = ep_builder
661            .build()
662            .map_err(|x| OpenStackCliError::EndpointBuild(x.to_string()))?;
663
664        let data: serde_json::Value = ep.query_async(client).await?;
665
666        op.output_single::<response::create_a::ServerResponse>(data.clone())
667            .or_else(|_| op.output_single::<response::create_b::ServerResponse>(data.clone()))?;
668        // Show command specific hints
669        op.show_command_hint()?;
670        Ok(())
671    }
672}