File: //snap/google-cloud-cli/current/lib/surface/immersive_stream/xr/instances/create.py
# -*- coding: utf-8 -*- #
# Copyright 2022 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 to create an Immersive Stream for XR service instance."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.immersive_stream.xr import api_util
from googlecloudsdk.api_lib.immersive_stream.xr import instances
from googlecloudsdk.api_lib.util import waiter
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.immersive_stream.xr import flags
from googlecloudsdk.command_lib.immersive_stream.xr import resource_args
from googlecloudsdk.core import log
from googlecloudsdk.core import properties
from googlecloudsdk.core import resources
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.GA)
class Create(base.CreateCommand):
"""Create an Immersive Stream for XR service instance."""
detailed_help = {
'DESCRIPTION': 'Create an Immersive Stream for XR service instance.',
'EXAMPLES': """
To create a service instance called `my-instance` serving content
`my-content` with version `my-version` that has availablilty for 2
concurent sessions in us-west1 region and 3 concurrent sessions in
us-east4 region, run:
$ {command} my-instance --content=my-content --version=my-version --add-region=region=us-west1,capacity=2 --add-region=region=us-east4,capacity=3
Optionally, a fallback url may be specified. Users will be redirected
to this fallback url when the service instance is unable to provide
the streaming experience.
To create a service instance called `my-instance` serving content
`my-content` with version `my-version` that has availablilty for 2
concurent sessions in us-west1 and uses fallback url
`https://www.google.com` run:
$ {command} my-instance --content=my-content --version=my-version --add-region=region=us-west1,capacity=2 --fallback-url="https://www.google.com"
By default, the instance is created with mode=ar, which supports both
3D and AR experiences. Instances can also be configured to use
3D-only mode. This configuration cannot be updated later.
To use 3D-only mode, include:
--mode=3d
By default, the instance is created with gpu-class=t4. This uses the
NVIDIA T4 GPU for the instance. Instances can also be configured to
use NVIDIA L4 GPUs at creation. Note that only certain regions are
available for L4, and only 3D-only mode is supported. This
configuration cannot be updated later.
To use NVIDIA L4 GPU for the instance, include:
--gpu-class=l4
""",
}
@staticmethod
def __ValidateArgs(args):
return flags.ValidateRegionConfigArgs(args.add_region, 'add')
@staticmethod
def Args(parser):
resource_args.AddContentResourceArg(
parser, verb='served by the instance', positional=False
)
parser.add_argument('instance', help='Name of the instance to be created')
parser.add_argument(
'--version',
required=True,
help='Build version tag of the content served by this instance',
)
parser.add_argument(
'--fallback-url',
help=(
'Fallback url to redirect users to when this service instance is'
' unable to provide the streaming experience'
),
required=False,
)
parser.add_argument(
'--mode',
help='The rendering mode that is supported by this service instance',
required=False,
)
parser.add_argument(
'--gpu-class',
help='The class of GPU that is used by this service instance',
required=False,
)
flags.AddRegionConfigArg('--add-region', parser)
base.ASYNC_FLAG.AddToParser(parser)
def Run(self, args):
if not Create.__ValidateArgs(args):
return
region_configs = args.add_region
content_ref = args.CONCEPTS.content.Parse()
content_name = content_ref.RelativeName()
location = content_ref.locationsId
instance_name = args.instance
version = args.version
fallback_url = args.fallback_url
mode = args.mode
gpu_class = args.gpu_class
if fallback_url and not flags.ValidateUrl(fallback_url):
return
if mode and not flags.ValidateMode(mode):
return
if gpu_class and not flags.ValidateGpuClass(gpu_class, mode):
return
client = api_util.GetClient(self.ReleaseTrack())
target_location_configs = instances.GenerateTargetLocationConfigs(
self.ReleaseTrack(),
add_region_configs=region_configs,
update_region_configs=None,
remove_regions=None,
current_instance=None,
)
result_operation = instances.Create(
self.ReleaseTrack(),
instance_name,
content_name,
location,
version,
target_location_configs,
fallback_url,
mode,
gpu_class,
)
log.status.Print('Create request issued for: [{}]'.format(instance_name))
if args.async_:
log.status.Print(
'Check operation [{}] for status.\n'.format(result_operation.name)
)
return result_operation
operation_resource = resources.REGISTRY.Parse(
result_operation.name,
api_version=api_util.GetApiVersion(self.ReleaseTrack()),
collection='stream.projects.locations.operations',
)
created_instance = waiter.WaitFor(
waiter.CloudOperationPoller(
client.projects_locations_streamInstances,
client.projects_locations_operations,
),
operation_resource,
'Waiting for operation [{}] to complete'.format(result_operation.name),
)
instance_resource = resources.REGISTRY.Parse(
None,
collection='stream.projects.locations.streamInstances',
api_version=api_util.GetApiVersion(self.ReleaseTrack()),
params={
'projectsId': properties.VALUES.core.project.Get(required=True),
'locationsId': 'global',
'streamInstancesId': instance_name,
},
)
log.CreatedResource(instance_resource)
return created_instance