1625 lines
64 KiB
Python
1625 lines
64 KiB
Python
# -*- coding: utf-8 -*- #
|
|
# Copyright 2014 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.
|
|
"""Command for creating instance templates."""
|
|
|
|
from __future__ import absolute_import
|
|
from __future__ import division
|
|
from __future__ import unicode_literals
|
|
|
|
import collections
|
|
import json
|
|
|
|
from googlecloudsdk.api_lib.compute import base_classes
|
|
from googlecloudsdk.api_lib.compute import constants
|
|
from googlecloudsdk.api_lib.compute import image_utils
|
|
from googlecloudsdk.api_lib.compute import instance_template_utils
|
|
from googlecloudsdk.api_lib.compute import instance_utils
|
|
from googlecloudsdk.api_lib.compute import metadata_utils
|
|
from googlecloudsdk.api_lib.compute import partner_metadata_utils
|
|
from googlecloudsdk.api_lib.compute import utils
|
|
from googlecloudsdk.calliope import base
|
|
from googlecloudsdk.calliope import exceptions
|
|
from googlecloudsdk.command_lib.compute import completers
|
|
from googlecloudsdk.command_lib.compute import flags
|
|
from googlecloudsdk.command_lib.compute import resource_manager_tags_utils
|
|
from googlecloudsdk.command_lib.compute.instance_templates import flags as instance_templates_flags
|
|
from googlecloudsdk.command_lib.compute.instance_templates import mesh_util
|
|
from googlecloudsdk.command_lib.compute.instance_templates import service_proxy_aux_data
|
|
from googlecloudsdk.command_lib.compute.instances import flags as instances_flags
|
|
from googlecloudsdk.command_lib.compute.resource_policies import flags as maintenance_flags
|
|
from googlecloudsdk.command_lib.compute.sole_tenancy import flags as sole_tenancy_flags
|
|
from googlecloudsdk.command_lib.compute.sole_tenancy import util as sole_tenancy_util
|
|
from googlecloudsdk.command_lib.util.apis import arg_utils
|
|
from googlecloudsdk.command_lib.util.args import labels_util
|
|
from googlecloudsdk.core import log
|
|
import six
|
|
|
|
|
|
def _CommonArgs(
|
|
parser,
|
|
release_track,
|
|
support_source_instance,
|
|
support_local_ssd_size=False,
|
|
support_kms=False,
|
|
support_multi_writer=False,
|
|
support_mesh=False,
|
|
support_host_error_timeout_seconds=False,
|
|
support_numa_node_count=False,
|
|
support_visible_core_count=False,
|
|
support_max_run_duration=False,
|
|
support_region_instance_template=False,
|
|
support_subnet_region=False,
|
|
support_replica_zones=True,
|
|
support_local_ssd_recovery_timeout=False,
|
|
support_network_queue_count=False,
|
|
support_maintenance_interval=False,
|
|
support_specific_then_x_affinity=False,
|
|
support_graceful_shutdown=False,
|
|
support_ipv6_only=False,
|
|
support_vlan_nic=True,
|
|
support_watchdog_timer=False,
|
|
support_disk_labels=False,
|
|
support_igmp_query=False,
|
|
support_flex_start=False,
|
|
support_display_device=False,
|
|
support_skip_guest_os_shutdown=False,
|
|
support_preemption_notice_duration=False,
|
|
support_enable_vpc_scoped_dns=False,
|
|
support_workload_identity_config=False,
|
|
support_service_class_id=False,
|
|
):
|
|
"""Adding arguments applicable for creating instance templates."""
|
|
parser.display_info.AddFormat(instance_templates_flags.DEFAULT_LIST_FORMAT)
|
|
metadata_utils.AddMetadataArgs(parser)
|
|
instances_flags.AddDiskArgs(parser, enable_kms=support_kms)
|
|
instances_flags.AddCreateDiskArgs(
|
|
parser,
|
|
enable_kms=support_kms,
|
|
support_boot=True,
|
|
support_multi_writer=support_multi_writer,
|
|
support_replica_zones=support_replica_zones,
|
|
support_disk_labels=support_disk_labels,
|
|
)
|
|
if support_local_ssd_size:
|
|
instances_flags.AddLocalSsdArgsWithSize(parser)
|
|
else:
|
|
instances_flags.AddLocalSsdArgs(parser)
|
|
instances_flags.AddCanIpForwardArgs(parser)
|
|
instances_flags.AddAddressArgs(
|
|
parser,
|
|
instances=False,
|
|
support_network_queue_count=support_network_queue_count,
|
|
support_vlan_nic=support_vlan_nic,
|
|
support_ipv6_only=support_ipv6_only,
|
|
support_igmp_query=support_igmp_query,
|
|
support_enable_vpc_scoped_dns=support_enable_vpc_scoped_dns,
|
|
support_service_class_id=support_service_class_id,
|
|
)
|
|
instances_flags.AddAcceleratorArgs(parser)
|
|
instances_flags.AddMachineTypeArgs(parser)
|
|
deprecate_maintenance_policy = release_track in [base.ReleaseTrack.ALPHA]
|
|
instances_flags.AddMaintenancePolicyArgs(parser, deprecate_maintenance_policy)
|
|
instances_flags.AddNoRestartOnFailureArgs(parser)
|
|
instances_flags.AddPreemptibleVmArgs(parser)
|
|
instances_flags.AddServiceAccountAndScopeArgs(parser, False)
|
|
instances_flags.AddTagsArgs(parser)
|
|
instances_flags.AddCustomMachineTypeArgs(parser)
|
|
instances_flags.AddImageArgs(parser)
|
|
instances_flags.AddNetworkArgs(parser)
|
|
instances_flags.AddShieldedInstanceConfigArgs(parser)
|
|
labels_util.AddCreateLabelsFlags(parser)
|
|
instances_flags.AddNetworkTierArgs(parser, instance=True)
|
|
instances_flags.AddPrivateNetworkIpArgs(parser)
|
|
instances_flags.AddMinNodeCpuArg(parser)
|
|
instances_flags.AddNestedVirtualizationArgs(parser)
|
|
instances_flags.AddThreadsPerCoreArgs(parser)
|
|
instances_flags.AddEnableUefiNetworkingArgs(parser)
|
|
instances_flags.AddResourceManagerTagsArgs(parser)
|
|
if support_numa_node_count:
|
|
instances_flags.AddNumaNodeCountArgs(parser)
|
|
instances_flags.AddStackTypeArgs(parser, support_ipv6_only)
|
|
instances_flags.AddIpv6NetworkTierArgs(parser)
|
|
maintenance_flags.AddResourcePoliciesArgs(
|
|
parser, 'added to', 'instance-template'
|
|
)
|
|
instances_flags.AddProvisioningModelVmArgs(
|
|
parser,
|
|
support_flex_start=support_flex_start,
|
|
)
|
|
instances_flags.AddInstanceTerminationActionVmArgs(parser)
|
|
instances_flags.AddIPv6AddressArgs(parser)
|
|
instances_flags.AddIPv6PrefixLengthArgs(parser)
|
|
instances_flags.AddInternalIPv6AddressArgs(parser)
|
|
instances_flags.AddInternalIPv6PrefixLengthArgs(parser)
|
|
if support_watchdog_timer:
|
|
instances_flags.AddWatchdogTimerArg(parser)
|
|
|
|
if support_max_run_duration:
|
|
instances_flags.AddMaxRunDurationVmArgs(parser)
|
|
instances_flags.AddDiscardLocalSsdVmArgs(parser)
|
|
|
|
if support_preemption_notice_duration:
|
|
instances_flags.AddPreemptionNoticeDurationArgs(parser)
|
|
|
|
instance_templates_flags.AddServiceProxyConfigArgs(
|
|
parser, release_track=release_track
|
|
)
|
|
if support_mesh:
|
|
instance_templates_flags.AddMeshArgs(parser)
|
|
|
|
sole_tenancy_flags.AddNodeAffinityFlagToParser(parser)
|
|
|
|
instances_flags.AddLocationHintArg(parser)
|
|
|
|
if support_visible_core_count:
|
|
instances_flags.AddVisibleCoreCountArgs(parser)
|
|
|
|
instances_flags.AddNetworkPerformanceConfigsArgs(parser)
|
|
|
|
if support_region_instance_template:
|
|
if support_subnet_region:
|
|
parser.add_argument(
|
|
'--subnet-region', help='Specifies the region of the subnetwork.'
|
|
)
|
|
parser.add_argument(
|
|
'--instance-template-region',
|
|
help='Specifies the region of the regional instance template.',
|
|
)
|
|
|
|
flags.AddRegionFlag(
|
|
parser, resource_type='subnetwork', operation_type='attach'
|
|
)
|
|
|
|
parser.add_argument(
|
|
'--description',
|
|
help='Specifies a textual description for the instance template.',
|
|
)
|
|
|
|
Create.InstanceTemplateArg = (
|
|
instance_templates_flags.MakeInstanceTemplateArg()
|
|
)
|
|
Create.InstanceTemplateArg.AddArgument(parser, operation_type='create')
|
|
if support_source_instance:
|
|
instance_templates_flags.MakeSourceInstanceArg().AddArgument(parser)
|
|
instance_templates_flags.AddConfigureDiskArgs(parser)
|
|
|
|
instances_flags.AddReservationAffinityGroup(
|
|
parser,
|
|
group_text="""\
|
|
Specifies the reservation for instances created from this template.
|
|
""",
|
|
affinity_text="""\
|
|
The type of reservation for instances created from this template.
|
|
""",
|
|
support_specific_then_x_affinity=support_specific_then_x_affinity,
|
|
)
|
|
|
|
parser.display_info.AddCacheUpdater(completers.InstanceTemplatesCompleter)
|
|
if support_host_error_timeout_seconds:
|
|
instances_flags.AddHostErrorTimeoutSecondsArgs(parser)
|
|
|
|
if support_local_ssd_recovery_timeout:
|
|
instances_flags.AddLocalSsdRecoveryTimeoutArgs(parser)
|
|
|
|
if support_maintenance_interval:
|
|
instances_flags.AddMaintenanceIntervalArgs(parser)
|
|
|
|
if support_graceful_shutdown:
|
|
instances_flags.AddGracefulShutdownArgs(parser, is_create=True)
|
|
|
|
instances_flags.AddTurboModeArgs(parser)
|
|
if support_display_device:
|
|
instances_flags.AddDisplayDeviceArg(parser)
|
|
if support_skip_guest_os_shutdown:
|
|
instances_flags.AddSkipGuestOsShutdownArgs(parser)
|
|
if support_workload_identity_config:
|
|
instances_flags.AddWorkloadIdentityConfigArgs(parser)
|
|
|
|
|
|
def _ValidateInstancesFlags(
|
|
args, support_kms=False, support_max_run_duration=False
|
|
):
|
|
"""Validate flags for instance template that affects instance creation.
|
|
|
|
Args:
|
|
args: argparse.Namespace, An object that contains the values for the
|
|
arguments specified in the .Args() method.
|
|
support_kms: If KMS is supported.
|
|
support_max_run_duration: max-run-durrations is supported in instance
|
|
scheduling.
|
|
"""
|
|
instances_flags.ValidateDiskCommonFlags(args)
|
|
instances_flags.ValidateDiskBootFlags(args, enable_kms=support_kms)
|
|
instances_flags.ValidateCreateDiskFlags(args)
|
|
instances_flags.ValidateLocalSsdFlags(args)
|
|
instances_flags.ValidateNicFlags(args)
|
|
instances_flags.ValidateServiceAccountAndScopeArgs(args)
|
|
instances_flags.ValidateAcceleratorArgs(args)
|
|
instances_flags.ValidateReservationAffinityGroup(args)
|
|
instances_flags.ValidateNetworkPerformanceConfigsArgs(args)
|
|
instances_flags.ValidateInstanceScheduling(
|
|
args, support_max_run_duration=support_max_run_duration
|
|
)
|
|
|
|
|
|
def _AddSourceInstanceToTemplate(
|
|
compute_api, args, instance_template, support_source_instance
|
|
):
|
|
"""Set the source instance for the template."""
|
|
|
|
if not support_source_instance or not args.source_instance:
|
|
return
|
|
source_instance_arg = instance_templates_flags.MakeSourceInstanceArg()
|
|
source_instance_ref = source_instance_arg.ResolveAsResource(
|
|
args, compute_api.resources
|
|
)
|
|
instance_template.sourceInstance = source_instance_ref.SelfLink()
|
|
if args.configure_disk:
|
|
messages = compute_api.client.messages
|
|
instance_template.sourceInstanceParams = messages.SourceInstanceParams()
|
|
for disk in args.configure_disk:
|
|
disk_config = messages.DiskInstantiationConfig()
|
|
# device-name is required argument with --configure-disk
|
|
disk_config.deviceName = disk.get('device-name')
|
|
disk_config.autoDelete = disk.get('auto-delete')
|
|
instantiate_from = disk.get('instantiate-from')
|
|
if instantiate_from:
|
|
disk_config.instantiateFrom = (
|
|
messages.DiskInstantiationConfig.InstantiateFromValueValuesEnum(
|
|
disk.get('instantiate-from').upper().replace('-', '_')
|
|
)
|
|
)
|
|
disk_config.customImage = disk.get('custom-image')
|
|
instance_template.sourceInstanceParams.diskConfigs.append(disk_config)
|
|
|
|
instance_template.properties = None
|
|
|
|
|
|
def BuildShieldedInstanceConfigMessage(messages, args):
|
|
"""Common routine for creating instance template.
|
|
|
|
Build a shielded VM config message.
|
|
|
|
Args:
|
|
messages: The client messages.
|
|
args: the arguments passed to the test.
|
|
|
|
Returns:
|
|
A shielded VM config message.
|
|
"""
|
|
# Set the default values for ShieldedInstanceConfig parameters
|
|
|
|
shielded_instance_config_message = None
|
|
enable_secure_boot = None
|
|
enable_vtpm = None
|
|
enable_integrity_monitoring = None
|
|
if not (
|
|
hasattr(args, 'shielded_vm_secure_boot')
|
|
or hasattr(args, 'shielded_vm_vtpm')
|
|
or hasattr(args, 'shielded_vm_integrity_monitoring')
|
|
):
|
|
return shielded_instance_config_message
|
|
|
|
if (
|
|
not args.IsSpecified('shielded_vm_secure_boot')
|
|
and not args.IsSpecified('shielded_vm_vtpm')
|
|
and not args.IsSpecified('shielded_vm_integrity_monitoring')
|
|
):
|
|
return shielded_instance_config_message
|
|
|
|
if args.shielded_vm_secure_boot is not None:
|
|
enable_secure_boot = args.shielded_vm_secure_boot
|
|
if args.shielded_vm_vtpm is not None:
|
|
enable_vtpm = args.shielded_vm_vtpm
|
|
if args.shielded_vm_integrity_monitoring is not None:
|
|
enable_integrity_monitoring = args.shielded_vm_integrity_monitoring
|
|
# compute message for shielded VM configuration.
|
|
shielded_instance_config_message = (
|
|
instance_utils.CreateShieldedInstanceConfigMessage(
|
|
messages, enable_secure_boot, enable_vtpm, enable_integrity_monitoring
|
|
)
|
|
)
|
|
|
|
return shielded_instance_config_message
|
|
|
|
|
|
def BuildConfidentialInstanceConfigMessage(
|
|
messages, args, support_confidential_compute_type=False,
|
|
support_confidential_compute_type_tdx=False, support_snp_svsm=False):
|
|
"""Builds a confidential instance configuration message."""
|
|
return instance_utils.CreateConfidentialInstanceMessage(
|
|
messages, args, support_confidential_compute_type,
|
|
support_confidential_compute_type_tdx, support_snp_svsm)
|
|
|
|
|
|
def PackageLabels(labels_cls, labels):
|
|
# Sorted for test stability
|
|
return labels_cls(
|
|
additionalProperties=[
|
|
labels_cls.AdditionalProperty(key=key, value=value)
|
|
for key, value in sorted(six.iteritems(labels))
|
|
]
|
|
)
|
|
|
|
|
|
# Function copied from labels_util.
|
|
# Temporary fix for adoption tracking of Managed Envoy.
|
|
# TODO(b/146051298) Remove this fix when structured metadata is available.
|
|
def ParseCreateArgsWithServiceProxy(args, labels_cls, labels_dest='labels'):
|
|
"""Initializes labels based on args and the given class."""
|
|
labels = getattr(args, labels_dest)
|
|
if getattr(args, 'service_proxy', False):
|
|
if labels is None:
|
|
labels = collections.OrderedDict()
|
|
labels['gce-service-proxy'] = 'on'
|
|
|
|
if labels is None:
|
|
return None
|
|
return PackageLabels(labels_cls, labels)
|
|
|
|
|
|
def AddScopesForServiceProxy(args):
|
|
if getattr(args, 'service_proxy', False):
|
|
if args.scopes is None:
|
|
args.scopes = constants.DEFAULT_SCOPES[:]
|
|
|
|
if (
|
|
'cloud-platform' not in args.scopes
|
|
and 'https://www.googleapis.com/auth/cloud-platform' not in args.scopes
|
|
):
|
|
args.scopes.append('cloud-platform')
|
|
|
|
|
|
def AddServiceProxyArgsToMetadata(args):
|
|
"""Inserts the Service Proxy arguments provided by the user to the instance metadata.
|
|
|
|
Args:
|
|
args: argparse.Namespace, An object that contains the values for the
|
|
arguments specified in the .Args() method.
|
|
"""
|
|
if getattr(args, 'service_proxy', False):
|
|
service_proxy_config = collections.OrderedDict()
|
|
proxy_spec = collections.OrderedDict()
|
|
|
|
service_proxy_config['_disclaimer'] = service_proxy_aux_data.DISCLAIMER
|
|
service_proxy_config['api-version'] = '0.2'
|
|
|
|
# add --service-proxy flag data to metadata.
|
|
if 'serving-ports' in args.service_proxy:
|
|
# convert list of strings to list of integers.
|
|
serving_ports = list(
|
|
map(int, args.service_proxy['serving-ports'].split(';'))
|
|
)
|
|
# find unique ports by converting list of integers to set of integers.
|
|
unique_serving_ports = set(serving_ports)
|
|
# convert it back to list of integers.
|
|
# this is done to make it JSON serializable.
|
|
serving_ports = list(unique_serving_ports)
|
|
service_proxy_config['service'] = {
|
|
'serving-ports': serving_ports,
|
|
}
|
|
|
|
if 'proxy-port' in args.service_proxy:
|
|
proxy_spec['proxy-port'] = args.service_proxy['proxy-port']
|
|
|
|
if 'tracing' in args.service_proxy:
|
|
proxy_spec['tracing'] = args.service_proxy['tracing']
|
|
|
|
if 'access-log' in args.service_proxy:
|
|
proxy_spec['access-log'] = args.service_proxy['access-log']
|
|
|
|
proxy_spec['network'] = args.service_proxy.get('network', '')
|
|
|
|
if 'scope' in args.service_proxy:
|
|
proxy_spec['scope'] = args.service_proxy['scope']
|
|
|
|
if 'mesh' in args.service_proxy:
|
|
proxy_spec['mesh'] = args.service_proxy['mesh']
|
|
|
|
if 'project-number' in args.service_proxy:
|
|
proxy_spec['project-number'] = args.service_proxy['project-number']
|
|
|
|
if 'source' in args.service_proxy:
|
|
proxy_spec['primary-source'] = args.service_proxy['source']
|
|
proxy_spec['secondary-source'] = args.service_proxy['source']
|
|
|
|
traffic_interception = collections.OrderedDict()
|
|
if 'intercept-all-outbound-traffic' in args.service_proxy:
|
|
traffic_interception['intercept-all-outbound'] = True
|
|
if 'exclude-outbound-ip-ranges' in args.service_proxy:
|
|
traffic_interception['exclude-outbound-ip-ranges'] = args.service_proxy[
|
|
'exclude-outbound-ip-ranges'
|
|
].split(';')
|
|
if 'exclude-outbound-port-ranges' in args.service_proxy:
|
|
traffic_interception['exclude-outbound-port-ranges'] = (
|
|
args.service_proxy['exclude-outbound-port-ranges'].split(';')
|
|
)
|
|
if 'intercept-dns' in args.service_proxy:
|
|
traffic_interception['intercept-dns'] = True
|
|
if traffic_interception:
|
|
service_proxy_config['traffic-interception'] = traffic_interception
|
|
|
|
if getattr(args, 'service_proxy_xds_version', False):
|
|
proxy_spec['xds-version'] = args.service_proxy_xds_version
|
|
|
|
# add --service-proxy-labels flag data to metadata.
|
|
if getattr(args, 'service_proxy_labels', False):
|
|
service_proxy_config['labels'] = args.service_proxy_labels
|
|
|
|
args.metadata['enable-osconfig'] = 'true'
|
|
gce_software_declaration = collections.OrderedDict()
|
|
service_proxy_agent_recipe = collections.OrderedDict()
|
|
|
|
service_proxy_agent_recipe['name'] = 'install-gce-service-proxy-agent'
|
|
service_proxy_agent_recipe['desired_state'] = 'INSTALLED'
|
|
|
|
if getattr(args, 'service_proxy_agent_location', False):
|
|
service_proxy_agent_recipe['installSteps'] = [{
|
|
'scriptRun': {
|
|
'script': (
|
|
service_proxy_aux_data.startup_script_with_location_template
|
|
% args.service_proxy_agent_location
|
|
)
|
|
}
|
|
}]
|
|
else:
|
|
service_proxy_agent_recipe['installSteps'] = [
|
|
{'scriptRun': {'script': service_proxy_aux_data.startup_script}}
|
|
]
|
|
|
|
gce_software_declaration['softwareRecipes'] = [service_proxy_agent_recipe]
|
|
|
|
args.metadata['gce-software-declaration'] = json.dumps(
|
|
gce_software_declaration
|
|
)
|
|
args.metadata['enable-guest-attributes'] = 'TRUE'
|
|
|
|
if proxy_spec:
|
|
service_proxy_config['proxy-spec'] = proxy_spec
|
|
|
|
args.metadata['gce-service-proxy'] = json.dumps(service_proxy_config)
|
|
|
|
|
|
def ConfigureMeshTemplate(args, instance_template_ref, network_interfaces):
|
|
"""Adds Anthos Service Mesh configuration into the instance template.
|
|
|
|
Args:
|
|
args: argparse.Namespace, An object that contains the values for the
|
|
arguments specified in the .Args() method.
|
|
instance_template_ref: Reference to the current instance template to be
|
|
created.
|
|
network_interfaces: network interfaces configured for the instance
|
|
template.
|
|
"""
|
|
|
|
if getattr(args, 'mesh', False):
|
|
# Add the required scopes.
|
|
if args.scopes is None:
|
|
args.scopes = constants.DEFAULT_SCOPES[:]
|
|
if (
|
|
'cloud-platform' not in args.scopes
|
|
and 'https://www.googleapis.com/auth/cloud-platform' not in args.scopes
|
|
):
|
|
args.scopes.append('cloud-platform')
|
|
|
|
workload_namespace, workload_name = mesh_util.ParseWorkload(
|
|
args.mesh['workload']
|
|
)
|
|
with mesh_util.KubernetesClient(
|
|
gke_cluster=args.mesh['gke-cluster']
|
|
) as kube_client:
|
|
log.status.Print(
|
|
'Verifying GKE cluster and Anthos Service Mesh installation...'
|
|
)
|
|
namespaces = ['default', 'istio-system', workload_namespace]
|
|
if kube_client.NamespacesExist(
|
|
*namespaces
|
|
) and kube_client.HasNamespaceReaderPermissions(*namespaces):
|
|
membership_manifest = kube_client.GetMembershipCR()
|
|
# Verify Identity Provider CR existence only.
|
|
_ = kube_client.GetIdentityProviderCR()
|
|
|
|
namespace_manifest = kube_client.GetNamespace(workload_namespace)
|
|
workload_manifest = kube_client.GetWorkloadGroupCR(
|
|
workload_namespace, workload_name
|
|
)
|
|
mesh_util.VerifyWorkloadSetup(workload_manifest)
|
|
|
|
asm_revision = mesh_util.RetrieveWorkloadRevision(namespace_manifest)
|
|
mesh_config = kube_client.RetrieveMeshConfig(asm_revision)
|
|
|
|
log.status.Print(
|
|
'Configuring the instance template for Anthos Service Mesh...'
|
|
)
|
|
project_id = instance_template_ref.project
|
|
mesh_util.ConfigureInstanceTemplate(
|
|
args,
|
|
kube_client,
|
|
project_id,
|
|
network_interfaces[0].network,
|
|
workload_namespace,
|
|
workload_name,
|
|
workload_manifest,
|
|
membership_manifest,
|
|
asm_revision,
|
|
mesh_config,
|
|
)
|
|
|
|
|
|
def _RunCreate(
|
|
compute_api,
|
|
args,
|
|
support_source_instance,
|
|
support_kms=False,
|
|
support_post_key_revocation_action_type=False,
|
|
support_multi_writer=False,
|
|
support_mesh=False,
|
|
support_host_error_timeout_seconds=False,
|
|
support_numa_node_count=False,
|
|
support_visible_core_count=False,
|
|
support_max_run_duration=False,
|
|
support_region_instance_template=False,
|
|
support_subnet_region=False,
|
|
support_confidential_compute_type=False,
|
|
support_confidential_compute_type_tdx=False,
|
|
support_snp_svsm=False,
|
|
support_ipv6_reservation=False,
|
|
support_internal_ipv6_reservation=False,
|
|
support_replica_zones=True,
|
|
support_local_ssd_recovery_timeout=False,
|
|
support_performance_monitoring_unit=False,
|
|
support_partner_metadata=False,
|
|
support_maintenance_interval=False,
|
|
support_specific_then_x_affinity=False,
|
|
support_graceful_shutdown=False,
|
|
support_watchdog_timer=False,
|
|
support_disk_labels=False,
|
|
support_display_device=False,
|
|
support_skip_guest_os_shutdown=False,
|
|
support_preemption_notice_duration=False,
|
|
support_enable_vpc_scoped_dns=False,
|
|
support_workload_identity_config=False,
|
|
support_service_class_id=False,
|
|
):
|
|
"""Common routine for creating instance template.
|
|
|
|
This is shared between various release tracks.
|
|
|
|
Args:
|
|
compute_api: The compute api.
|
|
args: argparse.Namespace, An object that contains the values for the
|
|
arguments specified in the .Args() method.
|
|
support_source_instance: indicates whether source instance is supported.
|
|
support_kms: Indicate whether KMS is integrated or not.
|
|
support_post_key_revocation_action_type: Indicate whether
|
|
post_key_revocation_action_type is supported.
|
|
support_multi_writer: Indicates whether a disk can have multiple writers.
|
|
support_mesh: Indicates whether adding VM to a Anthos Service Mesh is
|
|
supported.
|
|
support_host_error_timeout_seconds: Indicate the timeout in seconds for
|
|
host error detection.
|
|
support_numa_node_count: Indicates whether setting NUMA node count is
|
|
supported.
|
|
support_visible_core_count: Indicates whether setting a custom visible
|
|
support_max_run_duration: Indicate whether max-run-duration or
|
|
termination-time is supported.
|
|
support_region_instance_template: Indicate whether create region instance
|
|
template is supported.
|
|
support_subnet_region: Indicate whether subnet_region flag enhancement
|
|
should be supported.
|
|
support_confidential_compute_type: Indicate what confidential compute type
|
|
is used.
|
|
support_confidential_compute_type_tdx: Indicate if confidential compute
|
|
type 'TDX' is supported.
|
|
support_snp_svsm: Indicate whether Secure VM Service Module (SVSM) is
|
|
supported on AMD SEV-SNP VMs.
|
|
support_ipv6_reservation: Indicate the external IPv6 address is supported.
|
|
support_internal_ipv6_reservation: Indicate the internal IPv6 address is
|
|
supported.
|
|
support_replica_zones: Indicate the replicaZones param is supported for
|
|
create-on-create disk.
|
|
support_local_ssd_recovery_timeout: Indicate whether the local SSD
|
|
recovery timeout is set.
|
|
support_performance_monitoring_unit: Indicate whether the PMU is
|
|
supported.
|
|
support_partner_metadata: Indicate whether partner metadata is supported.
|
|
support_maintenance_interval: Indicate whether maintenance interval was
|
|
set.
|
|
support_specific_then_x_affinity: Indicate whether specific_then_x was
|
|
set.
|
|
support_graceful_shutdown: Indicate whether graceful shutdown is
|
|
supported.
|
|
support_watchdog_timer: Indicate whether the watchdog timer is supported.
|
|
support_disk_labels: Indicate whether disk labels are supported.
|
|
support_display_device: Indicate whether display device is supported.
|
|
support_skip_guest_os_shutdown: Indicate whether skip guest os shutdown is
|
|
supported.
|
|
support_preemption_notice_duration: Indicate whether preemption notice
|
|
duration is supported.
|
|
support_enable_vpc_scoped_dns: Indicate whether enable-vpc-scoped-dns is
|
|
supported.
|
|
support_workload_identity_config: Indicate whether workload identity
|
|
config is supported.
|
|
support_service_class_id: Indicate whether service class id is supported.
|
|
|
|
Returns:
|
|
A resource object dispatched by display.Displayer().
|
|
"""
|
|
_ValidateInstancesFlags(
|
|
args,
|
|
support_kms=support_kms,
|
|
support_max_run_duration=support_max_run_duration,
|
|
)
|
|
instances_flags.ValidateNetworkTierArgs(args)
|
|
|
|
instance_templates_flags.ValidateServiceProxyFlags(args)
|
|
if support_source_instance:
|
|
instance_templates_flags.ValidateSourceInstanceFlags(args)
|
|
if support_mesh:
|
|
instance_templates_flags.ValidateMeshFlag(args)
|
|
|
|
if support_region_instance_template:
|
|
subnet_region_flag = 'region'
|
|
if support_subnet_region:
|
|
subnet_region_flag = 'subnet_region'
|
|
instance_template_region = getattr(args, 'instance_template_region', None)
|
|
subnet_region = getattr(args, subnet_region_flag, None)
|
|
if (subnet_region is not None
|
|
and instance_template_region is not None
|
|
and instance_template_region != subnet_region):
|
|
raise exceptions.InvalidArgumentException(
|
|
'--instance-template-region',
|
|
'Values of `--instance-template-region` and `--{}` must match'.format(
|
|
subnet_region_flag))
|
|
|
|
client = compute_api.client
|
|
|
|
boot_disk_size_gb = utils.BytesToGb(args.boot_disk_size)
|
|
utils.WarnIfDiskSizeIsTooSmall(boot_disk_size_gb, args.boot_disk_type)
|
|
|
|
instance_template_ref = Create.InstanceTemplateArg.ResolveAsResource(
|
|
args, compute_api.resources
|
|
)
|
|
|
|
AddScopesForServiceProxy(args)
|
|
AddServiceProxyArgsToMetadata(args)
|
|
|
|
if hasattr(args, 'network_interface') and args.network_interface:
|
|
if support_subnet_region:
|
|
subnet_region = getattr(args, 'subnet_region', None)
|
|
else:
|
|
subnet_region = getattr(args, 'region', None)
|
|
network_interfaces = (
|
|
instance_template_utils.CreateNetworkInterfaceMessages
|
|
)(
|
|
resources=compute_api.resources,
|
|
scope_lister=flags.GetDefaultScopeLister(client),
|
|
messages=client.messages,
|
|
network_interface_arg=args.network_interface,
|
|
subnet_region=subnet_region,
|
|
support_enable_vpc_scoped_dns=support_enable_vpc_scoped_dns,
|
|
support_service_class_id=support_service_class_id,
|
|
)
|
|
else:
|
|
network_tier = getattr(args, 'network_tier', None)
|
|
stack_type = getattr(args, 'stack_type', None)
|
|
ipv6_network_tier = getattr(args, 'ipv6_network_tier', None)
|
|
external_ipv6_address = getattr(args, 'external_ipv6_address', None)
|
|
external_ipv6_prefix_length = getattr(
|
|
args, 'external_ipv6_prefix_length', None
|
|
)
|
|
ipv6_address = None
|
|
ipv6_prefix_length = None
|
|
internal_ipv6_address = None
|
|
internal_ipv6_prefix_length = None
|
|
|
|
if support_subnet_region:
|
|
subnet_region = getattr(args, 'subnet_region', None)
|
|
else:
|
|
subnet_region = getattr(args, 'region', None)
|
|
|
|
if support_ipv6_reservation:
|
|
ipv6_address = getattr(args, 'ipv6_address', None)
|
|
ipv6_prefix_length = getattr(args, 'ipv6_prefix_length', None)
|
|
|
|
if support_internal_ipv6_reservation:
|
|
internal_ipv6_address = getattr(args, 'internal_ipv6_address', None)
|
|
internal_ipv6_prefix_length = getattr(
|
|
args, 'internal_ipv6_prefix_length', None
|
|
)
|
|
|
|
network_interfaces = [
|
|
instance_template_utils.CreateNetworkInterfaceMessage(
|
|
resources=compute_api.resources,
|
|
scope_lister=flags.GetDefaultScopeLister(client),
|
|
messages=client.messages,
|
|
network=args.network,
|
|
private_ip=args.private_network_ip,
|
|
subnet_region=subnet_region,
|
|
subnet=args.subnet,
|
|
address=(
|
|
instance_template_utils.EPHEMERAL_ADDRESS
|
|
if not args.no_address and not args.address
|
|
else args.address
|
|
),
|
|
network_tier=network_tier,
|
|
stack_type=stack_type,
|
|
ipv6_network_tier=ipv6_network_tier,
|
|
ipv6_address=ipv6_address,
|
|
ipv6_prefix_length=ipv6_prefix_length,
|
|
external_ipv6_address=external_ipv6_address,
|
|
external_ipv6_prefix_length=external_ipv6_prefix_length,
|
|
internal_ipv6_address=internal_ipv6_address,
|
|
internal_ipv6_prefix_length=internal_ipv6_prefix_length,
|
|
)
|
|
]
|
|
|
|
if support_mesh:
|
|
ConfigureMeshTemplate(args, instance_template_ref, network_interfaces)
|
|
|
|
metadata = metadata_utils.ConstructMetadataMessage(
|
|
client.messages,
|
|
metadata=args.metadata,
|
|
metadata_from_file=args.metadata_from_file,
|
|
)
|
|
|
|
# Compute the shieldedInstanceConfig message.
|
|
shieldedinstance_config_message = BuildShieldedInstanceConfigMessage(
|
|
messages=client.messages, args=args
|
|
)
|
|
|
|
confidential_instance_config_message = BuildConfidentialInstanceConfigMessage(
|
|
messages=client.messages,
|
|
args=args,
|
|
support_confidential_compute_type=support_confidential_compute_type,
|
|
support_confidential_compute_type_tdx=(
|
|
support_confidential_compute_type_tdx
|
|
),
|
|
support_snp_svsm=support_snp_svsm,
|
|
)
|
|
|
|
node_affinities = sole_tenancy_util.GetSchedulingNodeAffinityListFromArgs(
|
|
args, client.messages
|
|
)
|
|
|
|
location_hint = None
|
|
if args.IsSpecified('location_hint'):
|
|
location_hint = args.location_hint
|
|
|
|
provisioning_model = None
|
|
if hasattr(args, 'provisioning_model') and args.IsSpecified(
|
|
'provisioning_model'
|
|
):
|
|
provisioning_model = args.provisioning_model
|
|
|
|
termination_action = None
|
|
if hasattr(args, 'instance_termination_action') and args.IsSpecified(
|
|
'instance_termination_action'
|
|
):
|
|
termination_action = args.instance_termination_action
|
|
|
|
max_run_duration = None
|
|
if hasattr(args, 'max_run_duration') and args.IsSpecified('max_run_duration'):
|
|
max_run_duration = args.max_run_duration
|
|
|
|
termination_time = None
|
|
if hasattr(args, 'termination_time') and args.IsSpecified('termination_time'):
|
|
termination_time = args.termination_time
|
|
|
|
discard_local_ssds_at_termination_timestamp = None
|
|
if hasattr(
|
|
args, 'discard_local_ssds_at_termination_timestamp'
|
|
) and args.IsSpecified('discard_local_ssds_at_termination_timestamp'):
|
|
discard_local_ssds_at_termination_timestamp = (
|
|
args.discard_local_ssds_at_termination_timestamp
|
|
)
|
|
|
|
host_error_timeout_seconds = None
|
|
if support_host_error_timeout_seconds and args.IsSpecified(
|
|
'host_error_timeout_seconds'
|
|
):
|
|
host_error_timeout_seconds = args.host_error_timeout_seconds
|
|
|
|
local_ssd_recovery_timeout = None
|
|
if support_local_ssd_recovery_timeout and args.IsSpecified(
|
|
'local_ssd_recovery_timeout'
|
|
):
|
|
local_ssd_recovery_timeout = args.local_ssd_recovery_timeout
|
|
|
|
should_set_maintenance_interval = (
|
|
support_maintenance_interval and args.IsSpecified('maintenance_interval')
|
|
)
|
|
maintenance_interval = (
|
|
args.maintenance_interval if should_set_maintenance_interval else None
|
|
)
|
|
|
|
graceful_shutdown = instance_utils.ExtractGracefulShutdownFromArgs(
|
|
args, support_graceful_shutdown
|
|
)
|
|
|
|
skip_guest_os_shutdown = None
|
|
if (
|
|
support_skip_guest_os_shutdown
|
|
and args.IsKnownAndSpecified('skip_guest_os_shutdown')
|
|
):
|
|
skip_guest_os_shutdown = args.skip_guest_os_shutdown
|
|
|
|
preemption_notice_duration = None
|
|
if support_preemption_notice_duration and args.IsSpecified(
|
|
'preemption_notice_duration'
|
|
):
|
|
preemption_notice_duration = args.preemption_notice_duration
|
|
|
|
scheduling = instance_utils.CreateSchedulingMessage(
|
|
messages=client.messages,
|
|
maintenance_policy=args.maintenance_policy,
|
|
preemptible=args.preemptible,
|
|
restart_on_failure=args.restart_on_failure,
|
|
node_affinities=node_affinities,
|
|
min_node_cpu=args.min_node_cpu,
|
|
location_hint=location_hint,
|
|
provisioning_model=provisioning_model,
|
|
instance_termination_action=termination_action,
|
|
host_error_timeout_seconds=host_error_timeout_seconds,
|
|
max_run_duration=max_run_duration,
|
|
termination_time=termination_time,
|
|
local_ssd_recovery_timeout=local_ssd_recovery_timeout,
|
|
maintenance_interval=maintenance_interval,
|
|
graceful_shutdown=graceful_shutdown,
|
|
discard_local_ssds_at_termination_timestamp=discard_local_ssds_at_termination_timestamp,
|
|
skip_guest_os_shutdown=skip_guest_os_shutdown,
|
|
preemption_notice_duration=preemption_notice_duration,
|
|
)
|
|
|
|
if args.no_service_account:
|
|
service_account = None
|
|
else:
|
|
service_account = args.service_account
|
|
service_accounts = instance_utils.CreateServiceAccountMessages(
|
|
messages=client.messages,
|
|
scopes=[] if args.no_scopes else args.scopes,
|
|
service_account=service_account,
|
|
)
|
|
|
|
# create boot disk through args.boot_disk_device_name
|
|
create_boot_disk = not (
|
|
instance_utils.UseExistingBootDisk(
|
|
(args.disk or []) + (args.create_disk or [])
|
|
)
|
|
)
|
|
if create_boot_disk:
|
|
image_expander = image_utils.ImageExpander(client, compute_api.resources)
|
|
try:
|
|
image_uri, _ = image_expander.ExpandImageFlag(
|
|
user_project=instance_template_ref.project,
|
|
image=args.image,
|
|
image_family=args.image_family,
|
|
image_project=args.image_project,
|
|
return_image_resource=True,
|
|
)
|
|
except utils.ImageNotFoundError as e:
|
|
if args.IsSpecified('image_project'):
|
|
raise e
|
|
image_uri, _ = image_expander.ExpandImageFlag(
|
|
user_project=instance_template_ref.project,
|
|
image=args.image,
|
|
image_family=args.image_family,
|
|
image_project=args.image_project,
|
|
return_image_resource=False,
|
|
)
|
|
raise utils.ImageNotFoundError(
|
|
'The resource [{}] was not found. Is the image located in another '
|
|
'project? Use the --image-project flag to specify the '
|
|
'project where the image is located.'.format(image_uri)
|
|
)
|
|
else:
|
|
image_uri = None
|
|
|
|
if args.tags:
|
|
tags = client.messages.Tags(items=args.tags)
|
|
else:
|
|
tags = None
|
|
|
|
disks = instance_template_utils.CreateDiskMessages(
|
|
args,
|
|
client,
|
|
compute_api.resources,
|
|
instance_template_ref.project,
|
|
image_uri,
|
|
boot_disk_size_gb=boot_disk_size_gb,
|
|
create_boot_disk=create_boot_disk,
|
|
support_kms=support_kms,
|
|
support_multi_writer=support_multi_writer,
|
|
support_replica_zones=support_replica_zones,
|
|
support_disk_labels=support_disk_labels,
|
|
)
|
|
|
|
machine_type = instance_utils.InterpretMachineType(
|
|
machine_type=args.machine_type,
|
|
custom_cpu=args.custom_cpu,
|
|
custom_memory=args.custom_memory,
|
|
ext=getattr(args, 'custom_extensions', None),
|
|
vm_type=getattr(args, 'custom_vm_type', None),
|
|
)
|
|
|
|
guest_accelerators = instance_template_utils.CreateAcceleratorConfigMessages(
|
|
client.messages, getattr(args, 'accelerator', None)
|
|
)
|
|
|
|
workload_identity_config = instance_utils.CreateWorkloadIdentityConfigMessage(
|
|
args, client.messages, support_workload_identity_config
|
|
)
|
|
|
|
if support_region_instance_template and args.IsSpecified(
|
|
'instance_template_region'
|
|
):
|
|
instance_template = client.messages.InstanceTemplate(
|
|
properties=client.messages.InstanceProperties(
|
|
machineType=machine_type,
|
|
disks=disks,
|
|
canIpForward=args.can_ip_forward,
|
|
metadata=metadata,
|
|
minCpuPlatform=args.min_cpu_platform,
|
|
networkInterfaces=network_interfaces,
|
|
serviceAccounts=service_accounts,
|
|
scheduling=scheduling,
|
|
tags=tags,
|
|
guestAccelerators=guest_accelerators,
|
|
),
|
|
description=args.description,
|
|
name=instance_template_ref.Name(),
|
|
region=getattr(args, 'instance_template_region', None),
|
|
)
|
|
else:
|
|
instance_template = client.messages.InstanceTemplate(
|
|
properties=client.messages.InstanceProperties(
|
|
machineType=machine_type,
|
|
disks=disks,
|
|
canIpForward=args.can_ip_forward,
|
|
metadata=metadata,
|
|
minCpuPlatform=args.min_cpu_platform,
|
|
networkInterfaces=network_interfaces,
|
|
serviceAccounts=service_accounts,
|
|
scheduling=scheduling,
|
|
tags=tags,
|
|
guestAccelerators=guest_accelerators,
|
|
),
|
|
description=args.description,
|
|
name=instance_template_ref.Name(),
|
|
)
|
|
|
|
if support_workload_identity_config and workload_identity_config:
|
|
instance_template.properties.workloadIdentityConfig = (
|
|
workload_identity_config
|
|
)
|
|
|
|
instance_template.properties.shieldedInstanceConfig = (
|
|
shieldedinstance_config_message
|
|
)
|
|
|
|
instance_template.properties.reservationAffinity = (
|
|
instance_utils.GetReservationAffinity(
|
|
args, client, support_specific_then_x_affinity
|
|
)
|
|
)
|
|
|
|
instance_template.properties.confidentialInstanceConfig = (
|
|
confidential_instance_config_message
|
|
)
|
|
|
|
if args.IsSpecified('network_performance_configs'):
|
|
instance_template.properties.networkPerformanceConfig = (
|
|
instance_utils.GetNetworkPerformanceConfig(args, client)
|
|
)
|
|
|
|
if args.IsSpecified('resource_policies'):
|
|
instance_template.properties.resourcePolicies = getattr(
|
|
args, 'resource_policies', []
|
|
)
|
|
|
|
if support_post_key_revocation_action_type and args.IsSpecified(
|
|
'post_key_revocation_action_type'
|
|
):
|
|
instance_template.properties.postKeyRevocationActionType = arg_utils.ChoiceToEnum(
|
|
args.post_key_revocation_action_type,
|
|
client.messages.InstanceProperties.PostKeyRevocationActionTypeValueValuesEnum,
|
|
)
|
|
|
|
if args.IsSpecified('key_revocation_action_type'):
|
|
instance_template.properties.keyRevocationActionType = arg_utils.ChoiceToEnum(
|
|
args.key_revocation_action_type,
|
|
client.messages.InstanceProperties.KeyRevocationActionTypeValueValuesEnum,
|
|
)
|
|
|
|
if args.private_ipv6_google_access_type is not None:
|
|
instance_template.properties.privateIpv6GoogleAccess = (
|
|
instances_flags.GetPrivateIpv6GoogleAccessTypeFlagMapperForTemplate(
|
|
client.messages
|
|
).GetEnumForChoice(args.private_ipv6_google_access_type)
|
|
)
|
|
|
|
# Create an AdvancedMachineFeatures message if any of the features requiring
|
|
# one have been specified.
|
|
has_visible_core_count = (
|
|
support_visible_core_count and args.visible_core_count is not None
|
|
)
|
|
if (
|
|
args.enable_nested_virtualization is not None
|
|
or args.threads_per_core is not None
|
|
or (support_numa_node_count and args.numa_node_count is not None)
|
|
or has_visible_core_count
|
|
or args.enable_uefi_networking is not None
|
|
or (
|
|
support_performance_monitoring_unit
|
|
and args.performance_monitoring_unit
|
|
)
|
|
or (support_watchdog_timer and (args.enable_watchdog_timer is not None))
|
|
or (args.turbo_mode is not None)
|
|
):
|
|
visible_core_count = (
|
|
args.visible_core_count if has_visible_core_count else None
|
|
)
|
|
|
|
instance_template.properties.advancedMachineFeatures = (
|
|
instance_utils.CreateAdvancedMachineFeaturesMessage(
|
|
client.messages,
|
|
args.enable_nested_virtualization,
|
|
args.threads_per_core,
|
|
args.numa_node_count if support_numa_node_count else None,
|
|
visible_core_count,
|
|
args.enable_uefi_networking,
|
|
args.performance_monitoring_unit
|
|
if support_performance_monitoring_unit
|
|
else None,
|
|
enable_watchdog_timer=args.enable_watchdog_timer
|
|
if support_watchdog_timer
|
|
else None,
|
|
turbo_mode=args.turbo_mode,
|
|
)
|
|
)
|
|
|
|
if args.resource_manager_tags:
|
|
ret_resource_manager_tags = (
|
|
resource_manager_tags_utils.GetResourceManagerTags(
|
|
args.resource_manager_tags
|
|
)
|
|
)
|
|
if ret_resource_manager_tags is not None:
|
|
properties = client.messages.InstanceProperties
|
|
instance_template.properties.resourceManagerTags = (
|
|
properties.ResourceManagerTagsValue(
|
|
additionalProperties=[
|
|
properties.ResourceManagerTagsValue.AdditionalProperty(
|
|
key=key, value=value)
|
|
for key, value in sorted(
|
|
six.iteritems(ret_resource_manager_tags))])
|
|
)
|
|
|
|
if support_partner_metadata and (
|
|
args.partner_metadata or args.partner_metadata_from_file
|
|
):
|
|
properties = client.messages.InstanceProperties
|
|
partner_metadata_dict = partner_metadata_utils.CreatePartnerMetadataDict(
|
|
args
|
|
)
|
|
partner_metadata_utils.ValidatePartnerMetadata(partner_metadata_dict)
|
|
partner_metadata_message = properties.PartnerMetadataValue()
|
|
for namespace, structured_entries in partner_metadata_dict.items():
|
|
partner_metadata_message.additionalProperties.append(
|
|
properties.PartnerMetadataValue.AdditionalProperty(
|
|
key=namespace,
|
|
value=partner_metadata_utils.ConvertStructuredEntries(
|
|
structured_entries, client.messages
|
|
),
|
|
)
|
|
)
|
|
instance_template.properties.partnerMetadata = partner_metadata_message
|
|
|
|
if support_display_device and args.IsSpecified('enable_display_device'):
|
|
instance_template.properties.displayDevice = (
|
|
client.messages.DisplayDevice(enableDisplay=args.enable_display_device)
|
|
)
|
|
|
|
request = client.messages.ComputeInstanceTemplatesInsertRequest(
|
|
instanceTemplate=instance_template, project=instance_template_ref.project
|
|
)
|
|
|
|
if support_region_instance_template and args.IsSpecified(
|
|
'instance_template_region'
|
|
):
|
|
request = client.messages.ComputeRegionInstanceTemplatesInsertRequest(
|
|
instanceTemplate=instance_template,
|
|
project=instance_template_ref.project,
|
|
region=instance_template.region,
|
|
)
|
|
|
|
request.instanceTemplate.properties.labels = ParseCreateArgsWithServiceProxy(
|
|
args, client.messages.InstanceProperties.LabelsValue
|
|
)
|
|
|
|
_AddSourceInstanceToTemplate(
|
|
compute_api, args, instance_template, support_source_instance
|
|
)
|
|
|
|
if support_region_instance_template and args.IsSpecified(
|
|
'instance_template_region'
|
|
):
|
|
return client.MakeRequests(
|
|
[(client.apitools_client.regionInstanceTemplates, 'Insert', request)]
|
|
)
|
|
else:
|
|
return client.MakeRequests(
|
|
[(client.apitools_client.instanceTemplates, 'Insert', request)]
|
|
)
|
|
|
|
|
|
# TODO(b/305707695):Change @base.DefaultUniverseOnly to
|
|
# @base.UniverseCompatible once b/305707695 is fixed.
|
|
# See go/gcloud-cli-running-tpc-tests.
|
|
@base.DefaultUniverseOnly
|
|
@base.ReleaseTracks(base.ReleaseTrack.GA)
|
|
class Create(base.CreateCommand):
|
|
"""Create a Compute Engine virtual machine instance template.
|
|
|
|
*{command}* facilitates the creation of Compute Engine
|
|
virtual machine instance templates. For example, running:
|
|
|
|
$ {command} INSTANCE-TEMPLATE
|
|
|
|
will create one instance templates called 'INSTANCE-TEMPLATE'.
|
|
|
|
Instance templates are global resources, and can be used to create
|
|
instances in any zone.
|
|
"""
|
|
|
|
# TODO(b/445859137): clean up flags which are true in all tracks.
|
|
_support_source_instance = True
|
|
_support_kms = True
|
|
_support_post_key_revocation_action_type = False
|
|
_support_multi_writer = False
|
|
_support_mesh = False
|
|
_support_numa_node_count = False
|
|
_support_visible_core_count = True
|
|
_support_max_run_duration = True
|
|
_support_region_instance_template = True
|
|
_support_subnet_region = False
|
|
_support_confidential_compute_type = True
|
|
_support_confidential_compute_type_tdx = True
|
|
_support_snp_svsm = False
|
|
_support_replica_zones = True
|
|
_support_local_ssd_size = True
|
|
_support_network_queue_count = True
|
|
_support_performance_monitoring_unit = True
|
|
_support_internal_ipv6_reservation = True
|
|
_support_partner_metadata = False
|
|
_support_local_ssd_recovery_timeout = True
|
|
_support_specific_then_x_affinity = False
|
|
_support_graceful_shutdown = False
|
|
_support_vlan_nic = True
|
|
_support_watchdog_timer = False
|
|
_support_disk_labels = False
|
|
_support_ipv6_only = True
|
|
_support_igmp_query = False
|
|
_support_host_error_timeout_seconds = True
|
|
_support_flex_start = True
|
|
_support_display_device = False
|
|
_support_skip_guest_os_shutdown = True
|
|
_support_preemption_notice_duration = False
|
|
_support_enable_vpc_scoped_dns = False
|
|
_support_workload_identity_config = False
|
|
|
|
@classmethod
|
|
def Args(cls, parser):
|
|
_CommonArgs(
|
|
parser,
|
|
release_track=base.ReleaseTrack.GA,
|
|
support_source_instance=cls._support_source_instance,
|
|
support_kms=cls._support_kms,
|
|
support_multi_writer=cls._support_multi_writer,
|
|
support_mesh=cls._support_mesh,
|
|
support_numa_node_count=cls._support_numa_node_count,
|
|
support_visible_core_count=cls._support_visible_core_count,
|
|
support_max_run_duration=cls._support_max_run_duration,
|
|
support_region_instance_template=cls._support_region_instance_template,
|
|
support_subnet_region=cls._support_subnet_region,
|
|
support_replica_zones=cls._support_replica_zones,
|
|
support_local_ssd_size=cls._support_local_ssd_size,
|
|
support_network_queue_count=cls._support_network_queue_count,
|
|
support_local_ssd_recovery_timeout=cls._support_local_ssd_recovery_timeout,
|
|
support_specific_then_x_affinity=cls._support_specific_then_x_affinity,
|
|
support_graceful_shutdown=cls._support_graceful_shutdown,
|
|
support_vlan_nic=cls._support_vlan_nic,
|
|
support_watchdog_timer=cls._support_watchdog_timer,
|
|
support_disk_labels=cls._support_disk_labels,
|
|
support_ipv6_only=cls._support_ipv6_only,
|
|
support_igmp_query=cls._support_igmp_query,
|
|
support_host_error_timeout_seconds=cls._support_host_error_timeout_seconds,
|
|
support_flex_start=cls._support_flex_start,
|
|
support_display_device=cls._support_display_device,
|
|
support_skip_guest_os_shutdown=cls._support_skip_guest_os_shutdown,
|
|
support_preemption_notice_duration=cls._support_preemption_notice_duration,
|
|
support_enable_vpc_scoped_dns=cls._support_enable_vpc_scoped_dns,
|
|
support_workload_identity_config=cls._support_workload_identity_config,
|
|
)
|
|
instances_flags.AddMinCpuPlatformArgs(parser, base.ReleaseTrack.GA)
|
|
instances_flags.AddPrivateIpv6GoogleAccessArgForTemplate(
|
|
parser, utils.COMPUTE_GA_API_VERSION
|
|
)
|
|
instances_flags.AddConfidentialComputeArgs(
|
|
parser,
|
|
support_confidential_compute_type=cls._support_confidential_compute_type,
|
|
support_confidential_compute_type_tdx=cls._support_confidential_compute_type_tdx,
|
|
support_snp_svsm=cls._support_snp_svsm,
|
|
)
|
|
instance_templates_flags.AddKeyRevocationActionTypeArgs(parser)
|
|
instances_flags.AddPerformanceMonitoringUnitArgs(parser)
|
|
|
|
def Run(self, args):
|
|
"""Creates and runs an InstanceTemplates.Insert request.
|
|
|
|
Args:
|
|
args: argparse.Namespace, An object that contains the values for the
|
|
arguments specified in the .Args() method.
|
|
|
|
Returns:
|
|
A resource object dispatched by display.Displayer().
|
|
"""
|
|
return _RunCreate(
|
|
base_classes.ComputeApiHolder(base.ReleaseTrack.GA),
|
|
args,
|
|
support_source_instance=self._support_source_instance,
|
|
support_kms=self._support_kms,
|
|
support_post_key_revocation_action_type=self._support_post_key_revocation_action_type,
|
|
support_multi_writer=self._support_multi_writer,
|
|
support_mesh=self._support_mesh,
|
|
support_numa_node_count=self._support_numa_node_count,
|
|
support_visible_core_count=self._support_visible_core_count,
|
|
support_max_run_duration=self._support_max_run_duration,
|
|
support_region_instance_template=self._support_region_instance_template,
|
|
support_subnet_region=self._support_subnet_region,
|
|
support_confidential_compute_type=self._support_confidential_compute_type,
|
|
support_confidential_compute_type_tdx=self._support_confidential_compute_type_tdx,
|
|
support_snp_svsm=self._support_snp_svsm,
|
|
support_replica_zones=self._support_replica_zones,
|
|
support_performance_monitoring_unit=self._support_performance_monitoring_unit,
|
|
support_internal_ipv6_reservation=self._support_internal_ipv6_reservation,
|
|
support_partner_metadata=self._support_partner_metadata,
|
|
support_local_ssd_recovery_timeout=self._support_local_ssd_recovery_timeout,
|
|
support_specific_then_x_affinity=self._support_specific_then_x_affinity,
|
|
support_graceful_shutdown=self._support_graceful_shutdown,
|
|
support_watchdog_timer=self._support_watchdog_timer,
|
|
support_disk_labels=self._support_disk_labels,
|
|
support_host_error_timeout_seconds=self._support_host_error_timeout_seconds,
|
|
support_display_device=self._support_display_device,
|
|
support_skip_guest_os_shutdown=self._support_skip_guest_os_shutdown,
|
|
support_preemption_notice_duration=self._support_preemption_notice_duration,
|
|
support_enable_vpc_scoped_dns=self._support_enable_vpc_scoped_dns,
|
|
support_workload_identity_config=self._support_workload_identity_config,
|
|
)
|
|
|
|
|
|
@base.ReleaseTracks(base.ReleaseTrack.BETA)
|
|
class CreateBeta(Create):
|
|
"""Create a Compute Engine virtual machine instance template.
|
|
|
|
*{command}* facilitates the creation of Compute Engine
|
|
virtual machine instance templates. For example, running:
|
|
|
|
$ {command} INSTANCE-TEMPLATE
|
|
|
|
will create one instance templates called 'INSTANCE-TEMPLATE'.
|
|
|
|
Instance templates are global resources, and can be used to create
|
|
instances in any zone.
|
|
"""
|
|
|
|
_support_source_instance = True
|
|
_support_kms = True
|
|
_support_post_key_revocation_action_type = True
|
|
_support_multi_writer = True
|
|
_support_mesh = True
|
|
_support_host_error_timeout_seconds = True
|
|
_support_numa_node_count = False
|
|
_support_visible_core_count = True
|
|
_support_max_run_duration = True
|
|
_support_region_instance_template = True
|
|
_support_subnet_region = False
|
|
_support_confidential_compute_type = True
|
|
_support_confidential_compute_type_tdx = True
|
|
_support_snp_svsm = False
|
|
_support_replica_zones = True
|
|
_support_local_ssd_recovery_timeout = True
|
|
_support_local_ssd_size = True
|
|
_support_network_queue_count = True
|
|
_support_performance_monitoring_unit = True
|
|
_support_internal_ipv6_reservation = True
|
|
_support_partner_metadata = True
|
|
_support_maintenance_interval = True
|
|
_support_specific_then_x_affinity = True
|
|
_support_graceful_shutdown = True
|
|
_support_vlan_nic = True
|
|
_support_watchdog_timer = False
|
|
_support_disk_labels = True
|
|
_support_ipv6_only = True
|
|
_support_igmp_query = False
|
|
_support_flex_start = True
|
|
_support_display_device = True
|
|
_support_skip_guest_os_shutdown = True
|
|
_support_preemption_notice_duration = False
|
|
_support_enable_vpc_scoped_dns = False
|
|
_support_workload_identity_config = False
|
|
|
|
@classmethod
|
|
def Args(cls, parser):
|
|
_CommonArgs(
|
|
parser,
|
|
release_track=base.ReleaseTrack.BETA,
|
|
support_local_ssd_size=cls._support_local_ssd_size,
|
|
support_source_instance=cls._support_source_instance,
|
|
support_kms=cls._support_kms,
|
|
support_multi_writer=cls._support_multi_writer,
|
|
support_mesh=cls._support_mesh,
|
|
support_host_error_timeout_seconds=cls._support_host_error_timeout_seconds,
|
|
support_visible_core_count=cls._support_visible_core_count,
|
|
support_max_run_duration=cls._support_max_run_duration,
|
|
support_region_instance_template=cls._support_region_instance_template,
|
|
support_subnet_region=cls._support_subnet_region,
|
|
support_replica_zones=cls._support_replica_zones,
|
|
support_local_ssd_recovery_timeout=cls._support_local_ssd_recovery_timeout,
|
|
support_network_queue_count=cls._support_network_queue_count,
|
|
support_maintenance_interval=cls._support_maintenance_interval,
|
|
support_specific_then_x_affinity=cls._support_specific_then_x_affinity,
|
|
support_graceful_shutdown=cls._support_graceful_shutdown,
|
|
support_vlan_nic=cls._support_vlan_nic,
|
|
support_watchdog_timer=cls._support_watchdog_timer,
|
|
support_disk_labels=cls._support_disk_labels,
|
|
support_ipv6_only=cls._support_ipv6_only,
|
|
support_igmp_query=cls._support_igmp_query,
|
|
support_flex_start=cls._support_flex_start,
|
|
support_display_device=cls._support_display_device,
|
|
support_skip_guest_os_shutdown=cls._support_skip_guest_os_shutdown,
|
|
support_preemption_notice_duration=cls._support_preemption_notice_duration,
|
|
support_enable_vpc_scoped_dns=cls._support_enable_vpc_scoped_dns,
|
|
support_workload_identity_config=cls._support_workload_identity_config,
|
|
)
|
|
instances_flags.AddMinCpuPlatformArgs(parser, base.ReleaseTrack.BETA)
|
|
instances_flags.AddPrivateIpv6GoogleAccessArgForTemplate(
|
|
parser, utils.COMPUTE_BETA_API_VERSION
|
|
)
|
|
instances_flags.AddConfidentialComputeArgs(
|
|
parser,
|
|
support_confidential_compute_type=cls
|
|
._support_confidential_compute_type,
|
|
support_confidential_compute_type_tdx=cls
|
|
._support_confidential_compute_type_tdx, support_snp_svsm=cls._support_snp_svsm)
|
|
instances_flags.AddPostKeyRevocationActionTypeArgs(parser)
|
|
instance_templates_flags.AddKeyRevocationActionTypeArgs(parser)
|
|
instances_flags.AddPerformanceMonitoringUnitArgs(parser)
|
|
partner_metadata_utils.AddPartnerMetadataArgs(parser)
|
|
|
|
def Run(self, args):
|
|
"""Creates and runs an InstanceTemplates.Insert request.
|
|
|
|
Args:
|
|
args: argparse.Namespace, An object that contains the values for the
|
|
arguments specified in the .Args() method.
|
|
|
|
Returns:
|
|
A resource object dispatched by display.Displayer().
|
|
"""
|
|
return _RunCreate(
|
|
base_classes.ComputeApiHolder(base.ReleaseTrack.BETA),
|
|
args=args,
|
|
support_source_instance=self._support_source_instance,
|
|
support_kms=self._support_kms,
|
|
support_post_key_revocation_action_type=self._support_post_key_revocation_action_type,
|
|
support_multi_writer=self._support_multi_writer,
|
|
support_mesh=self._support_mesh,
|
|
support_host_error_timeout_seconds=self._support_host_error_timeout_seconds,
|
|
support_numa_node_count=self._support_numa_node_count,
|
|
support_visible_core_count=self._support_visible_core_count,
|
|
support_max_run_duration=self._support_max_run_duration,
|
|
support_region_instance_template=self._support_region_instance_template,
|
|
support_subnet_region=self._support_subnet_region,
|
|
support_confidential_compute_type=self._support_confidential_compute_type,
|
|
support_confidential_compute_type_tdx=self._support_confidential_compute_type_tdx,
|
|
support_snp_svsm=self._support_snp_svsm,
|
|
support_replica_zones=self._support_replica_zones,
|
|
support_local_ssd_recovery_timeout=self._support_local_ssd_recovery_timeout,
|
|
support_performance_monitoring_unit=self._support_performance_monitoring_unit,
|
|
support_internal_ipv6_reservation=self._support_internal_ipv6_reservation,
|
|
support_partner_metadata=self._support_partner_metadata,
|
|
support_maintenance_interval=self._support_maintenance_interval,
|
|
support_specific_then_x_affinity=self._support_specific_then_x_affinity,
|
|
support_graceful_shutdown=self._support_graceful_shutdown,
|
|
support_watchdog_timer=self._support_watchdog_timer,
|
|
support_disk_labels=self._support_disk_labels,
|
|
support_display_device=self._support_display_device,
|
|
support_skip_guest_os_shutdown=self._support_skip_guest_os_shutdown,
|
|
support_preemption_notice_duration=self._support_preemption_notice_duration,
|
|
support_enable_vpc_scoped_dns=self._support_enable_vpc_scoped_dns,
|
|
support_workload_identity_config=self._support_workload_identity_config,
|
|
)
|
|
|
|
|
|
@base.ReleaseTracks(base.ReleaseTrack.ALPHA)
|
|
class CreateAlpha(Create):
|
|
"""Create a Compute Engine virtual machine instance template.
|
|
|
|
*{command}* facilitates the creation of Compute Engine
|
|
virtual machine instance templates. For example, running:
|
|
|
|
$ {command} INSTANCE-TEMPLATE
|
|
|
|
will create one instance templates called 'INSTANCE-TEMPLATE'.
|
|
|
|
Instance templates are global resources, and can be used to create
|
|
instances in any zone.
|
|
"""
|
|
|
|
_support_source_instance = True
|
|
_support_kms = True
|
|
_support_post_key_revocation_action_type = True
|
|
_support_multi_writer = True
|
|
_support_mesh = True
|
|
_support_host_error_timeout_seconds = True
|
|
_support_numa_node_count = True
|
|
_support_visible_core_count = True
|
|
_support_max_run_duration = True
|
|
_support_region_instance_template = True
|
|
_support_subnet_region = True
|
|
_support_confidential_compute_type = True
|
|
_support_confidential_compute_type_tdx = True
|
|
_support_snp_svsm = True
|
|
_support_replica_zones = True
|
|
_support_local_ssd_recovery_timeout = True
|
|
_support_network_queue_count = True
|
|
_support_local_ssd_size = True
|
|
_support_performance_monitoring_unit = True
|
|
_support_internal_ipv6_reservation = True
|
|
_support_partner_metadata = True
|
|
_support_maintenance_interval = True
|
|
_support_specific_then_x_affinity = True
|
|
_support_graceful_shutdown = True
|
|
_support_vlan_nic = True
|
|
_support_ipv6_only = True
|
|
_support_watchdog_timer = True
|
|
_support_disk_labels = True
|
|
_support_igmp_query = True
|
|
_support_flex_start = True
|
|
_support_display_device = True
|
|
_support_skip_guest_os_shutdown = True
|
|
_support_preemption_notice_duration = True
|
|
_support_enable_vpc_scoped_dns = True
|
|
_support_workload_identity_config = True
|
|
_support_service_class_id = True
|
|
|
|
@classmethod
|
|
def Args(cls, parser):
|
|
_CommonArgs(
|
|
parser,
|
|
release_track=base.ReleaseTrack.ALPHA,
|
|
support_local_ssd_size=cls._support_local_ssd_size,
|
|
support_source_instance=cls._support_source_instance,
|
|
support_kms=cls._support_kms,
|
|
support_multi_writer=cls._support_multi_writer,
|
|
support_mesh=cls._support_mesh,
|
|
support_host_error_timeout_seconds=cls._support_host_error_timeout_seconds,
|
|
support_numa_node_count=cls._support_numa_node_count,
|
|
support_visible_core_count=cls._support_visible_core_count,
|
|
support_max_run_duration=cls._support_max_run_duration,
|
|
support_region_instance_template=cls._support_region_instance_template,
|
|
support_subnet_region=cls._support_subnet_region,
|
|
support_replica_zones=cls._support_replica_zones,
|
|
support_local_ssd_recovery_timeout=cls._support_local_ssd_recovery_timeout,
|
|
support_network_queue_count=cls._support_network_queue_count,
|
|
support_maintenance_interval=cls._support_maintenance_interval,
|
|
support_specific_then_x_affinity=cls._support_specific_then_x_affinity,
|
|
support_graceful_shutdown=cls._support_graceful_shutdown,
|
|
support_ipv6_only=cls._support_ipv6_only,
|
|
support_vlan_nic=cls._support_vlan_nic,
|
|
support_watchdog_timer=cls._support_watchdog_timer,
|
|
support_disk_labels=cls._support_disk_labels,
|
|
support_igmp_query=cls._support_igmp_query,
|
|
support_flex_start=cls._support_flex_start,
|
|
support_display_device=cls._support_display_device,
|
|
support_skip_guest_os_shutdown=cls._support_skip_guest_os_shutdown,
|
|
support_preemption_notice_duration=cls._support_preemption_notice_duration,
|
|
support_enable_vpc_scoped_dns=cls._support_enable_vpc_scoped_dns,
|
|
support_workload_identity_config=cls._support_workload_identity_config,
|
|
support_service_class_id=cls._support_service_class_id,
|
|
)
|
|
instances_flags.AddLocalNvdimmArgs(parser)
|
|
instances_flags.AddMinCpuPlatformArgs(parser, base.ReleaseTrack.ALPHA)
|
|
instances_flags.AddConfidentialComputeArgs(
|
|
parser,
|
|
support_confidential_compute_type=cls._support_confidential_compute_type,
|
|
support_confidential_compute_type_tdx=cls._support_confidential_compute_type_tdx,
|
|
support_snp_svsm=cls._support_snp_svsm,
|
|
)
|
|
instances_flags.AddPrivateIpv6GoogleAccessArgForTemplate(
|
|
parser, utils.COMPUTE_ALPHA_API_VERSION
|
|
)
|
|
instances_flags.AddPostKeyRevocationActionTypeArgs(parser)
|
|
instances_flags.AddIPv6AddressAlphaArgs(parser)
|
|
instances_flags.AddIPv6PrefixLengthAlphaArgs(parser)
|
|
instance_templates_flags.AddKeyRevocationActionTypeArgs(parser)
|
|
instances_flags.AddPerformanceMonitoringUnitArgs(parser)
|
|
partner_metadata_utils.AddPartnerMetadataArgs(parser)
|
|
|
|
def Run(self, args):
|
|
"""Creates and runs an InstanceTemplates.Insert request.
|
|
|
|
Args:
|
|
args: argparse.Namespace, An object that contains the values for the
|
|
arguments specified in the .Args() method.
|
|
|
|
Returns:
|
|
A resource object dispatched by display.Displayer().
|
|
"""
|
|
return _RunCreate(
|
|
base_classes.ComputeApiHolder(base.ReleaseTrack.ALPHA),
|
|
args=args,
|
|
support_source_instance=self._support_source_instance,
|
|
support_kms=self._support_kms,
|
|
support_post_key_revocation_action_type=self._support_post_key_revocation_action_type,
|
|
support_multi_writer=self._support_multi_writer,
|
|
support_mesh=self._support_mesh,
|
|
support_host_error_timeout_seconds=self._support_host_error_timeout_seconds,
|
|
support_numa_node_count=self._support_numa_node_count,
|
|
support_visible_core_count=self._support_visible_core_count,
|
|
support_max_run_duration=self._support_max_run_duration,
|
|
support_region_instance_template=self._support_region_instance_template,
|
|
support_subnet_region=self._support_subnet_region,
|
|
support_confidential_compute_type=self._support_confidential_compute_type,
|
|
support_confidential_compute_type_tdx=self._support_confidential_compute_type_tdx,
|
|
support_snp_svsm=self._support_snp_svsm,
|
|
support_replica_zones=self._support_replica_zones,
|
|
support_local_ssd_recovery_timeout=self._support_local_ssd_recovery_timeout,
|
|
support_performance_monitoring_unit=self._support_performance_monitoring_unit,
|
|
support_internal_ipv6_reservation=self._support_internal_ipv6_reservation,
|
|
support_partner_metadata=self._support_partner_metadata,
|
|
support_maintenance_interval=self._support_maintenance_interval,
|
|
support_specific_then_x_affinity=self._support_specific_then_x_affinity,
|
|
support_graceful_shutdown=self._support_graceful_shutdown,
|
|
support_watchdog_timer=self._support_watchdog_timer,
|
|
support_disk_labels=self._support_disk_labels,
|
|
support_display_device=self._support_display_device,
|
|
support_skip_guest_os_shutdown=self._support_skip_guest_os_shutdown,
|
|
support_preemption_notice_duration=self._support_preemption_notice_duration,
|
|
support_enable_vpc_scoped_dns=self._support_enable_vpc_scoped_dns,
|
|
support_workload_identity_config=self._support_workload_identity_config,
|
|
support_service_class_id=True,
|
|
)
|
|
|
|
|
|
DETAILED_HELP = {
|
|
'brief': 'Create a Compute Engine virtual machine instance template.',
|
|
'DESCRIPTION': (
|
|
'*{command}* facilitates the creation of Compute Engine '
|
|
'virtual machine instance templates. Instance '
|
|
'templates are global resources, and can be used to create '
|
|
'instances in any zone.'
|
|
),
|
|
'EXAMPLES': """\
|
|
To create an instance template named 'INSTANCE-TEMPLATE' with the 'n2'
|
|
vm type, '9GB' memory, and 2 CPU cores, run:
|
|
|
|
$ {command} INSTANCE-TEMPLATE --custom-vm-type=n2 --custom-cpu=2 --custom-memory=9GB
|
|
""",
|
|
}
|
|
|
|
Create.detailed_help = DETAILED_HELP
|