File: //snap/google-cloud-cli/current/lib/googlecloudsdk/command_lib/compute/reservations/flags.py
# -*- coding: utf-8 -*- #
# Copyright 2019 Google LLC. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Flags and helpers for the compute reservations commands."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.calliope import arg_parsers
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.compute.instances import flags as instance_flags
def GetDescriptionFlag(is_fr=False):
help_text = """\
An optional description of the {} to create.
""".format('future reservation' if is_fr else 'reservation')
return base.Argument(
'--description',
help=help_text)
def GetRequireSpecificAllocation():
help_text = """\
Indicates whether the reservation can be consumed by VMs with "any reservation"
defined. If enabled, then only VMs that target this reservation by name using
`--reservation-affinity=specific` can consume from this reservation.
"""
return base.Argument(
'--require-specific-reservation', action='store_true', help=help_text)
def GetVmCountFlag(required=True):
help_text = """\
The number of VM instances that are allocated to this reservation.
The value of this field must be an int in the range [1, 1000].
"""
return base.Argument(
'--vm-count', required=required, type=int, help=help_text)
def GetMinCpuPlatform():
"""Gets the --min-cpu-platform flag."""
return base.Argument(
'--min-cpu-platform',
help='Optional minimum CPU platform of the reservation to create.')
def GetLocationHint():
"""Gets the --location-hint flag."""
return base.Argument(
'--location-hint',
hidden=True,
help="""\
Used by internal tools to control sub-zone location of the instance.
""")
def GetMachineType(required=True):
"""Gets the --machine-type flag."""
help_text = """\
The type of machine (name only) that has a fixed number of vCPUs and a fixed
amount of memory. You can also specify a custom machine type by using the
pattern `custom-number_of_CPUs-amount_of_memory`-for example,
`custom-32-29440`.
"""
return base.Argument('--machine-type', required=required, help=help_text)
def GetLocalSsdFlag(custom_name=None):
"""Gets the --local-ssd flag."""
help_text = """\
Manage the size and the interface of local SSD to use. See
https://cloud.google.com/compute/docs/disks/local-ssd for more information.
*interface*::: The kind of disk interface exposed to the VM for this SSD. Valid
values are `scsi` and `nvme`. SCSI is the default and is supported by more
guest operating systems. NVME may provide higher performance.
*size*::: The size of the local SSD in base-2 GB.
"""
return base.Argument(
custom_name if custom_name else '--local-ssd',
type=arg_parsers.ArgDict(spec={
'interface': (lambda x: x.upper()),
'size': int,
}),
action='append',
help=help_text)
def GetLocalSsdFlagWithCount(custom_name=None):
"""Gets the --local-ssd flag."""
help_text = """\
Manage the size and the interface of local SSD to use. See
https://cloud.google.com/compute/docs/disks/local-ssd for more information.
*interface*::: The kind of disk interface exposed to the VM for this SSD. Valid
values are `scsi` and `nvme`. SCSI is the default and is supported by more
guest operating systems. NVME may provide higher performance.
*size*::: The size of the local SSD in base-2 GB.
*count*::: The number of local SSD to use per VM. If you don't specify this
argument, then the default value is 1.
"""
return base.Argument(
custom_name if custom_name else '--local-ssd',
type=arg_parsers.ArgDict(spec={
'interface': (lambda x: x.upper()),
'size': int,
'count': int
}),
action='append',
help=help_text)
def GetAcceleratorFlag(custom_name=None):
"""Gets the --accelerator flag."""
help_text = """\
Manage the configuration of the type and number of accelerator cards attached.
*count*::: The number of accelerators to attach to each instance in the reservation.
*type*::: The specific type (e.g. `nvidia-tesla-k80` for nVidia Tesla K80) of
accelerator to attach to instances in the reservation. Use `gcloud compute accelerator-types list`
to learn about all available accelerator types.
"""
return base.Argument(
custom_name if custom_name else '--accelerator',
type=arg_parsers.ArgDict(
spec={
'count': int,
'type': str,
}, required_keys=['count', 'type']),
action='append',
help=help_text)
def GetSharedSettingFlag(custom_name=None, support_folder_share_setting=False):
"""Gets the --share-setting flag."""
help_text = """\
The projects that can use the reservation.
"""
choices = {
'local': ('Only your project can use the reservation. This is the'
' default value.'),
'projects': """\
Your project and up to 100 other projects within your
project's organization can use the reservation. If you specify
this value, then you must also include the --share-with flag in
the command.
""",
}
if support_folder_share_setting:
choices.update({'folders': 'Any project on the specified list of folders'
' can use the reservation.'})
return base.Argument(
custom_name if custom_name else '--share-setting',
choices=choices,
help=help_text)
def GetShareWithFlag(custom_name=None, support_folder_share_setting=False):
"""Gets the --share-with flag."""
help_text = """\
If this reservation is shared (--share-setting=projects), then specify a
comma-separated list of projects to share the reservation with. List
projects using project IDs or project numbers.
"""
if support_folder_share_setting:
help_text = """\
If this reservation is shared (--share-setting=projects), then specify a
comma-separated list of projects to share the reservation with. List
projects using project IDs, project numbers, or folder IDs.
"""
return base.Argument(
custom_name if custom_name else '--share-with',
type=arg_parsers.ArgList(min_length=1),
metavar='SHARE_WITH',
help=help_text)
def GetAddShareWithFlag(custom_name=None):
"""Gets the --add-share-with flag."""
help_text = """\
If this reservation is shared (--share-setting is projects), then
specify a comma-separated list of projects to share the reservation
with. You must list the projects using project IDs or project numbers.
"""
return base.Argument(
custom_name if custom_name else '--add-share-with',
type=arg_parsers.ArgList(min_length=1),
metavar='PROJECT',
help=help_text)
def GetRemoveShareWithFlag(custom_name=None):
"""Gets the --remove-share-with flag."""
help_text = """\
A list of specific projects to remove from the list of projects that this
reservation is shared with. List must contain project IDs or project numbers.
"""
return base.Argument(
custom_name if custom_name else '--remove-share-with',
type=arg_parsers.ArgList(min_length=1),
metavar='PROJECT',
help=help_text)
def GetDeleteAtTimeFlag():
"""Gets the --delete-at-time flag."""
help_text = """\
Automatically deletes the reservation at a specific time from its creation.
The specified time must be an RFC3339 timestamp, which must be
formatted as "YYYY-MM-DDTHH:MM:SSZ" where YYYY = year, MM = month, DD = day,
HH = hours, MM = minutes, SS = seconds, and Z = time zone in
Coordinated Universal Time (UTC). For example, specify 2021-11-20T07:00:00Z.
"""
return base.Argument(
'--delete-at-time', type=arg_parsers.Datetime.Parse, help=help_text
)
def GetDeleteAfterDurationFlag():
help_text = """\
Automatically deletes the reservations after a specified number of
days, hours, minutes, or seconds from its creation. For example,
specify 30m for 30 minutes, or 1d2h3m4s for 1 day, 2 hours,
3 minutes, and 4 seconds. For more information, see $ gcloud topic datetimes.
"""
return base.Argument(
'--delete-after-duration',
type=arg_parsers.Duration(),
help=help_text,
)
def AddScopeFlags(parser):
"""Adds scope flag to the parser."""
parser.add_argument(
'--scope',
metavar='SCOPE',
type=lambda x: x.lower(),
choices={
'all': 'Perform maintenance on all hosts in the reservation.',
'running': (
'Perform maintenance only on the hosts in the reservation that'
' have running VMs.'
),
'unused': (
'Perform maintenance only on the hosts in the reservation that'
" don't have running VMs."
),
},
help='The maintenance scope to set for the reservation.',
)
def GetDisableAutoDelete():
"""Gets the --disable-auto-delete flag."""
help_text = """\
Disables the auto-delete setting for the reservation.
"""
return base.Argument(
'--disable-auto-delete', action='store_true',
help=help_text)
def GetResourcePolicyFlag(custom_name=None):
"""Gets the --resource-policies flag."""
help_text = """\
The resource policies to include in this reservation. If you omit this flag,
no resource policies are added. You can specify any string as the key, and
specify the name of a resource policy as the value.
"""
return base.Argument(
custom_name or '--resource-policies',
metavar='KEY=VALUE',
type=arg_parsers.ArgDict(),
help=help_text)
def GetSourceInstanceTemplateFlag(custom_name=None):
"""Gets the --source-instance-template flag."""
help_text = """\
The url of the instance template that will be used to populate the fields of
the reservation. Instance properties can not be defined in addition to source
instance template.
"""
return base.Argument(
custom_name or '--source-instance-template', help=help_text
)
def GetReservationSharingPolicyFlag(custom_name=None):
"""Gets the --reservation-sharing-policy flag."""
help_text = """\
The reservation sharing policy to use for this reservation.
"""
return base.Argument(
custom_name or '--reservation-sharing-policy',
type=lambda x: x.upper(),
choices={
'ALLOW_ALL': (
'The reservation can be shared with Google Cloud services.'
),
'DISALLOW_ALL': (
"The reservation won't be shared with Google Cloud services. If"
' you omit this flag during creation, the default value is'
' DISALLOW_ALL.'
),
},
help=help_text,
)
def GetTpuVersion(required=True):
"""Gets the --tpu-version flag."""
help_text = """\
The version of Cloud TPU to reserve.
"""
return base.Argument(
'--tpu-version',
type=lambda x: x.upper(),
choices={
'V5E': 'Cloud TPU v5e Lite',
'V5P': 'Cloud TPU v5p',
'V6E': 'Cloud TPU v6e',
'TPU7X': 'Cloud TPU v7x',
},
required=required,
help=help_text,
)
def GetChipCount(required=False):
"""Gets the --chip-count flag."""
help_text = """\
The number of chips to reserve.
"""
return base.Argument(
'--chip-count', type=int, required=required, help=help_text
)
def GetWorkloadType(required=False):
"""Gets the --workload-type flag."""
help_text = """\
The workload type of the TPU reservation.
"""
return base.Argument(
'--workload-type',
type=lambda x: x.upper(),
choices={
'SERVING': (
'Reserved resources will be optimized for SERVING workloads, such'
' as ML inference'
),
'BATCH': (
'Reserved resources will be optimized for BATCH workloads, such'
' as ML training.'
),
},
required=required,
help=help_text,
)
def GetAcceleratorType(required=True):
"""Gets the --accelerator-type flag."""
help_text = """\
The accelerator type to use for this reservation.
"""
return base.Argument('--accelerator-type', required=required, help=help_text)
def GetEnableEmergentMaintenanceFlag():
"""--emergent-maintenance flag."""
help_text = """\
Enables the reservation to receive notifications when urgent maintenance
for a GPU VM starts after the VM encounters a host error.
"""
return base.Argument(
'--enable-emergent-maintenance',
action=arg_parsers.StoreTrueFalseAction,
help=help_text,
)
def GetSchedulingTypeFlag():
"""--scheduling-type flag."""
help_text = """\
How Compute Engine schedules maintenance events for your reserved hosts.
"""
return base.Argument(
'--scheduling-type',
choices={
'GROUPED': (
'In GROUPED mode, maintenance is synchronized across all your'
' VMs.'
),
'INDEPENDENT': (
'In INDEPENDENT mode, your VMs have different, unsynchronized'
' maintenance schedules.'
),
},
help=help_text,
)
def AddCreateFlags(
parser,
support_fleet=False,
support_folder_share_setting=False,
support_ssd_count=False,
support_auto_delete=False,
support_reservation_sharing_policy=False,
):
"""Adds all flags needed for the create command."""
GetDescriptionFlag().AddToParser(parser)
if support_reservation_sharing_policy:
GetReservationSharingPolicyFlag().AddToParser(parser)
# create the group for all properties used in SpecificSkuReservations
specific_sku_group = base.ArgumentGroup(
'Manage the SpecificSKU reservation properties.', required=True)
specific_sku_group.AddArgument(GetRequireSpecificAllocation())
specific_sku_group.AddArgument(GetVmCountFlag())
specific_sku_group.AddArgument(GetResourcePolicyFlag())
# create the sku properties group for the SpecificSkuReservation
# this group allows instance properties XOR source instance template
# to be provided
specific_sku_properties_group = base.ArgumentGroup(
'Manage the instance properties for the SpecificSKU reservation.',
required=True,
mutex=True)
specific_sku_properties_group.AddArgument(GetSourceInstanceTemplateFlag())
# create the instance properties group for the SpecificSkuReservation
instance_properties_group = base.ArgumentGroup(
'Define the individual instance properties for the SpecificSKU'
' reservation.',
required=False,
)
instance_properties_group.AddArgument(GetMinCpuPlatform())
instance_properties_group.AddArgument(GetMachineType())
if support_ssd_count:
instance_properties_group.AddArgument(GetLocalSsdFlagWithCount())
else:
instance_properties_group.AddArgument(GetLocalSsdFlag())
instance_properties_group.AddArgument(GetAcceleratorFlag())
instance_properties_group.AddArgument(GetLocationHint())
if support_fleet:
instance_properties_group.AddArgument(
instance_flags.AddMaintenanceFreezeDuration())
instance_properties_group.AddArgument(
instance_flags.AddMaintenanceInterval())
# add all the groups to each other and the parser
specific_sku_properties_group.AddArgument(instance_properties_group)
specific_sku_group.AddArgument(specific_sku_properties_group)
specific_sku_group.AddToParser(parser)
share_group = base.ArgumentGroup(
'Manage the properties of a shared reservation.', required=False)
share_group.AddArgument(
GetSharedSettingFlag(
support_folder_share_setting=support_folder_share_setting
)
)
share_group.AddArgument(
GetShareWithFlag(
support_folder_share_setting=support_folder_share_setting
)
)
share_group.AddToParser(parser)
if support_auto_delete:
auto_delete_group = base.ArgumentGroup(
'Manage auto-delete properties for reservations.',
required=False,
mutex=True,
)
auto_delete_group.AddArgument(GetDeleteAtTimeFlag())
auto_delete_group.AddArgument(GetDeleteAfterDurationFlag())
auto_delete_group.AddToParser(parser)