Skip to content

Commit 93c9b91

Browse files
Zuulopenstack-gerrit
authored andcommitted
Merge "compute: Add missing 'server create' options"
2 parents 433ceff + 4da4b96 commit 93c9b91

3 files changed

Lines changed: 335 additions & 14 deletions

File tree

openstackclient/compute/v2/server.py

Lines changed: 94 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -772,6 +772,19 @@ def get_parser(self, prog_name):
772772
'volume.'
773773
),
774774
)
775+
disk_group.add_argument(
776+
'--snapshot',
777+
metavar='<snapshot>',
778+
help=_(
779+
'Create server using this snapshot as the boot disk (name or '
780+
'ID)\n'
781+
'This option automatically creates a block device mapping '
782+
'with a boot index of 0. On many hypervisors (libvirt/kvm '
783+
'for example) this will be device vda. Do not create a '
784+
'duplicate mapping using --block-device-mapping for this '
785+
'volume.'
786+
),
787+
)
775788
parser.add_argument(
776789
'--boot-from-volume',
777790
metavar='<volume-size>',
@@ -784,7 +797,8 @@ def get_parser(self, prog_name):
784797
'given size (in GB) from the specified image and use it '
785798
'as the root disk of the server. The root volume will not '
786799
'be deleted when the server is deleted. This option is '
787-
'mutually exclusive with the ``--volume`` option.'
800+
'mutually exclusive with the ``--volume`` and ``--snapshot`` '
801+
'options.'
788802
)
789803
)
790804
parser.add_argument(
@@ -810,6 +824,28 @@ def get_parser(self, prog_name):
810824
'(optional)\n'
811825
),
812826
)
827+
parser.add_argument(
828+
'--swap',
829+
metavar='<swap>',
830+
type=int,
831+
help=(
832+
"Create and attach a local swap block device of <swap_size> "
833+
"MiB."
834+
),
835+
)
836+
parser.add_argument(
837+
'--ephemeral',
838+
metavar='<size=size[,format=format]>',
839+
action=parseractions.MultiKeyValueAction,
840+
dest='ephemerals',
841+
default=[],
842+
required_keys=['size'],
843+
optional_keys=['format'],
844+
help=(
845+
"Create and attach a local ephemeral block device of <size> "
846+
"GiB and format it to <format>."
847+
),
848+
)
813849
parser.add_argument(
814850
'--network',
815851
metavar="<network>",
@@ -929,12 +965,14 @@ def get_parser(self, prog_name):
929965
parser.add_argument(
930966
'--availability-zone',
931967
metavar='<zone-name>',
932-
help=_('Select an availability zone for the server. '
933-
'Host and node are optional parameters. '
934-
'Availability zone in the format '
935-
'<zone-name>:<host-name>:<node-name>, '
936-
'<zone-name>::<node-name>, <zone-name>:<host-name> '
937-
'or <zone-name>'),
968+
help=_(
969+
'Select an availability zone for the server. '
970+
'Host and node are optional parameters. '
971+
'Availability zone in the format '
972+
'<zone-name>:<host-name>:<node-name>, '
973+
'<zone-name>::<node-name>, <zone-name>:<host-name> '
974+
'or <zone-name>'
975+
),
938976
)
939977
parser.add_argument(
940978
'--host',
@@ -1000,11 +1038,6 @@ def get_parser(self, prog_name):
10001038
default=1,
10011039
help=_('Maximum number of servers to launch (default=1)'),
10021040
)
1003-
parser.add_argument(
1004-
'--wait',
1005-
action='store_true',
1006-
help=_('Wait for build to complete'),
1007-
)
10081041
parser.add_argument(
10091042
'--tag',
10101043
metavar='<tag>',
@@ -1017,6 +1050,11 @@ def get_parser(self, prog_name):
10171050
'(supported by --os-compute-api-version 2.52 or above)'
10181051
),
10191052
)
1053+
parser.add_argument(
1054+
'--wait',
1055+
action='store_true',
1056+
help=_('Wait for build to complete'),
1057+
)
10201058
return parser
10211059

10221060
def take_action(self, parsed_args):
@@ -1092,7 +1130,6 @@ def _match_image(image_api, wanted_properties):
10921130
)
10931131
raise exceptions.CommandError(msg)
10941132

1095-
# Lookup parsed_args.volume
10961133
volume = None
10971134
if parsed_args.volume:
10981135
# --volume and --boot-from-volume are mutually exclusive.
@@ -1105,7 +1142,18 @@ def _match_image(image_api, wanted_properties):
11051142
parsed_args.volume,
11061143
).id
11071144

1108-
# Lookup parsed_args.flavor
1145+
snapshot = None
1146+
if parsed_args.snapshot:
1147+
# --snapshot and --boot-from-volume are mutually exclusive.
1148+
if parsed_args.boot_from_volume:
1149+
msg = _('--snapshot is not allowed with --boot-from-volume')
1150+
raise exceptions.CommandError(msg)
1151+
1152+
snapshot = utils.find_resource(
1153+
volume_client.volume_snapshots,
1154+
parsed_args.snapshot,
1155+
).id
1156+
11091157
flavor = utils.find_resource(
11101158
compute_client.flavors, parsed_args.flavor)
11111159

@@ -1156,6 +1204,14 @@ def _match_image(image_api, wanted_properties):
11561204
'source_type': 'volume',
11571205
'destination_type': 'volume'
11581206
}]
1207+
elif snapshot:
1208+
block_device_mapping_v2 = [{
1209+
'uuid': snapshot,
1210+
'boot_index': '0',
1211+
'source_type': 'snapshot',
1212+
'destination_type': 'volume',
1213+
'delete_on_termination': False
1214+
}]
11591215
elif parsed_args.boot_from_volume:
11601216
# Tell nova to create a root volume from the image provided.
11611217
block_device_mapping_v2 = [{
@@ -1168,6 +1224,30 @@ def _match_image(image_api, wanted_properties):
11681224
# If booting from volume we do not pass an image to compute.
11691225
image = None
11701226

1227+
if parsed_args.swap:
1228+
block_device_mapping_v2.append({
1229+
'boot_index': -1,
1230+
'source_type': 'blank',
1231+
'destination_type': 'local',
1232+
'guest_format': 'swap',
1233+
'volume_size': parsed_args.swap,
1234+
'delete_on_termination': True,
1235+
})
1236+
1237+
for mapping in parsed_args.ephemerals:
1238+
block_device_mapping_dict = {
1239+
'boot_index': -1,
1240+
'source_type': 'blank',
1241+
'destination_type': 'local',
1242+
'delete_on_termination': True,
1243+
'volume_size': mapping['size'],
1244+
}
1245+
1246+
if 'format' in mapping:
1247+
block_device_mapping_dict['guest_format'] = mapping['format']
1248+
1249+
block_device_mapping_v2.append(block_device_mapping_dict)
1250+
11711251
# Handle block device by device name order, like: vdb -> vdc -> vdd
11721252
for mapping in parsed_args.block_device_mapping:
11731253
if mapping['source_type'] == 'volume':

0 commit comments

Comments
 (0)