feat: Add new gcloud commands, API clients, and third-party libraries across various services.

This commit is contained in:
2026-01-01 20:26:35 +01:00
parent 5e23cbece0
commit a19e592eb7
25221 changed files with 8324611 additions and 0 deletions

View File

@@ -0,0 +1,20 @@
# -*- 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.
"""Cloud NetApp API lib helper files."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals

View File

@@ -0,0 +1,21 @@
# -*- 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.
"""Cloud NetApp Files Active Directory API client library helper files."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals

View File

@@ -0,0 +1,393 @@
# -*- 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.
"""Commands for interacting with the Cloud NetApp Files Active Directory API resource."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from apitools.base.py import list_pager
from googlecloudsdk.api_lib.netapp import constants
from googlecloudsdk.api_lib.netapp import util as netapp_api_util
from googlecloudsdk.api_lib.util import waiter
from googlecloudsdk.calliope import base
from googlecloudsdk.core import log
from googlecloudsdk.core import resources
class ActiveDirectoriesClient(object):
"""Wrapper for working with Active Directories in the Cloud NetApp Files API Client."""
def __init__(self, release_track=base.ReleaseTrack.ALPHA):
if release_track == base.ReleaseTrack.ALPHA:
self._adapter = AlphaActiveDirectoriesAdapter()
elif release_track == base.ReleaseTrack.BETA:
self._adapter = BetaActiveDirectoriesAdapter()
elif release_track == base.ReleaseTrack.GA:
self._adapter = ActiveDirectoriesAdapter()
else:
raise ValueError('[{}] is not a valid API version.'.format(
netapp_api_util.VERSION_MAP[release_track]))
@property
def client(self):
return self._adapter.client
@property
def messages(self):
return self._adapter.messages
def WaitForOperation(self, operation_ref):
"""Waits on the long-running operation until the done field is True.
Args:
operation_ref: the operation reference.
Raises:
waiter.OperationError: if the operation contains an error.
Returns:
the 'response' field of the Operation.
"""
return waiter.WaitFor(
waiter.CloudOperationPollerNoResources(
self.client.projects_locations_operations), operation_ref,
'Waiting for [{0}] to finish'.format(operation_ref.Name()))
def ParseActiveDirectoryConfig(
self,
name=None,
domain=None,
site=None,
dns=None,
net_bios_prefix=None,
organizational_unit=None,
aes_encryption=None,
username=None,
password=None,
backup_operators=None,
security_operators=None,
administrators=None,
kdc_hostname=None,
kdc_ip=None,
nfs_users_with_ldap=None,
ldap_signing=None,
encrypt_dc_connections=None,
description=None,
labels=None,
):
"""Parses the command line arguments for Create Active Directory into a config.
Args:
name: the name of the Active Directory
domain: the domain name of the Active Directory
site: the site of the Active Directory
dns: the DNS server IP addresses for the Active Directory domain
net_bios_prefix: the NetBIOS prefix name of the server
organizational_unit: The organizational unit within the AD the user
belongs to
aes_encryption: Bool, if enabled, AES encryption will be enabled for SMB
communication
username: Username of the AD domain admin
password: Password of the AD domain admin
backup_operators: The backup operators AD group users list
security_operators: Security operators AD domain users list
administrators: Built-in administrators AD group users list
kdc_hostname: Name of the AD machine
kdc_ip: KDC Server IP address for the AD machine
nfs_users_with_ldap: Bool, if enabled, will allow access to local users
and LDAP users. Disable, if only needed for LDAP users
ldap_signing: Bool that specifies whether or not LDAP traffic needs to be
signed
encrypt_dc_connections: Bool, if enabled, traffic between SMB server and
DC will be encrypted
description: the description of the Active Directory
labels: the labels for the Active Directory
Returns:
The configuration that will be used as the request body for creating a
Cloud NetApp Active Directory.
"""
active_directory = self.messages.ActiveDirectory()
active_directory.name = name
active_directory.domain = domain
active_directory.site = site
active_directory.dns = dns
active_directory.netBiosPrefix = net_bios_prefix
active_directory.organizationalUnit = organizational_unit
active_directory.aesEncryption = aes_encryption
active_directory.username = username
active_directory.password = password
active_directory.backupOperators = (
backup_operators if backup_operators else []
)
active_directory.securityOperators = (
security_operators if security_operators else []
)
active_directory.administrators = (
administrators if administrators else []
)
active_directory.nfsUsersWithLdap = nfs_users_with_ldap
active_directory.kdcHostname = kdc_hostname
active_directory.kdcIp = kdc_ip
active_directory.ldapSigning = ldap_signing
active_directory.encryptDcConnections = encrypt_dc_connections
active_directory.description = description
active_directory.labels = labels
return active_directory
def CreateActiveDirectory(self, activedirectory_ref, async_, config):
"""Create a Cloud NetApp Active Directory."""
request = (
self.messages.NetappProjectsLocationsActiveDirectoriesCreateRequest(
parent=activedirectory_ref.Parent().RelativeName(),
activeDirectoryId=activedirectory_ref.Name(),
activeDirectory=config,
)
)
create_op = self.client.projects_locations_activeDirectories.Create(request)
if async_:
return create_op
operation_ref = resources.REGISTRY.ParseRelativeName(
create_op.name, collection=constants.OPERATIONS_COLLECTION)
return self.WaitForOperation(operation_ref)
def ListActiveDirectories(self, location_ref, limit=None):
"""Make API calls to List active Cloud NetApp Active Directories.
Args:
location_ref: The parsed location of the listed NetApp Active Directories.
limit: The number of Cloud NetApp Active Directories
to limit the results to. This limit is passed to
the server and the server does the limiting.
Returns:
Generator that yields the Cloud NetApp Active Directories.
"""
request = self.messages.NetappProjectsLocationsActiveDirectoriesListRequest(
parent=location_ref)
# Check for unreachable locations.
response = self.client.projects_locations_activeDirectories.List(request)
for location in response.unreachable:
log.warning('Location {} may be unreachable.'.format(location))
return list_pager.YieldFromList(
self.client.projects_locations_activeDirectories,
request,
field=constants.ACTIVE_DIRECTORY_RESOURCE,
limit=limit,
batch_size_attribute='pageSize')
def GetActiveDirectory(self, activedirectory_ref):
"""Get Cloud NetApp Active Directory information."""
request = self.messages.NetappProjectsLocationsActiveDirectoriesGetRequest(
name=activedirectory_ref.RelativeName())
return self.client.projects_locations_activeDirectories.Get(request)
def DeleteActiveDirectory(self, activedirectory_ref, async_):
"""Deletes an existing Cloud NetApp Active Directory."""
request = (
self.messages.NetappProjectsLocationsActiveDirectoriesDeleteRequest(
name=activedirectory_ref.RelativeName()
)
)
return self._DeleteActiveDirectory(async_, request)
def _DeleteActiveDirectory(self, async_, request):
delete_op = self.client.projects_locations_activeDirectories.Delete(request)
if async_:
return delete_op
operation_ref = resources.REGISTRY.ParseRelativeName(
delete_op.name, collection=constants.OPERATIONS_COLLECTION)
return self.WaitForOperation(operation_ref)
def ParseUpdatedActiveDirectoryConfig(self,
activedirectory_config,
domain=None,
site=None,
dns=None,
net_bios_prefix=None,
organizational_unit=None,
aes_encryption=None,
username=None,
password=None,
backup_operators=None,
security_operators=None,
administrators=None,
kdc_hostname=None,
kdc_ip=None,
nfs_users_with_ldap=None,
ldap_signing=None,
encrypt_dc_connections=None,
description=None,
labels=None):
"""Parses updates into an active directory config."""
return self._adapter.ParseUpdatedActiveDirectoryConfig(
activedirectory_config,
domain=domain,
site=site,
dns=dns,
net_bios_prefix=net_bios_prefix,
organizational_unit=organizational_unit,
aes_encryption=aes_encryption,
username=username,
password=password,
backup_operators=backup_operators,
security_operators=security_operators,
administrators=administrators,
kdc_hostname=kdc_hostname,
kdc_ip=kdc_ip,
nfs_users_with_ldap=nfs_users_with_ldap,
ldap_signing=ldap_signing,
encrypt_dc_connections=encrypt_dc_connections,
description=description,
labels=labels)
def UpdateActiveDirectory(self, activedirectory_ref, activedirectory_config,
update_mask, async_):
"""Updates an Active Directory.
Args:
activedirectory_ref: the reference to the active directory.
activedirectory_config: Active Directory config, the updated active
directory.
update_mask: str, a comma-separated list of updated fields.
async_: bool, if False, wait for the operation to complete.
Returns:
An Operation or Active Directory config.
"""
update_op = self._adapter.UpdateActiveDirectory(activedirectory_ref,
activedirectory_config,
update_mask)
if async_:
return update_op
operation_ref = resources.REGISTRY.ParseRelativeName(
update_op.name, collection=constants.OPERATIONS_COLLECTION)
return self.WaitForOperation(operation_ref)
class ActiveDirectoriesAdapter(object):
"""Adapter for the Cloud NetApp Files API for Active Directories."""
def __init__(self):
self.release_track = base.ReleaseTrack.GA
self.client = netapp_api_util.GetClientInstance(
release_track=self.release_track
)
self.messages = netapp_api_util.GetMessagesModule(
release_track=self.release_track
)
def ParseUpdatedActiveDirectoryConfig(
self,
activedirectory_config,
domain=None,
site=None,
dns=None,
net_bios_prefix=None,
organizational_unit=None,
aes_encryption=None,
username=None,
password=None,
backup_operators=None,
security_operators=None,
administrators=None,
kdc_hostname=None,
kdc_ip=None,
nfs_users_with_ldap=None,
ldap_signing=None,
encrypt_dc_connections=None,
description=None,
labels=None,
):
"""Parses updates into an active directory config."""
if domain is not None:
activedirectory_config.domain = domain
if site is not None:
activedirectory_config.site = site
if dns is not None:
activedirectory_config.dns = dns
if net_bios_prefix is not None:
activedirectory_config.netBiosPrefix = net_bios_prefix
if organizational_unit is not None:
activedirectory_config.organizationalUnit = organizational_unit
if aes_encryption is not None:
activedirectory_config.aesEncryption = aes_encryption
if username is not None:
activedirectory_config.username = username
if password is not None:
activedirectory_config.password = password
if backup_operators is not None:
activedirectory_config.backupOperators = backup_operators
if security_operators is not None:
activedirectory_config.securityOperators = security_operators
if administrators is not None:
activedirectory_config.administrators = administrators
if kdc_hostname is not None:
activedirectory_config.kdcHostname = kdc_hostname
if kdc_ip is not None:
activedirectory_config.kdcIp = kdc_ip
if nfs_users_with_ldap is not None:
activedirectory_config.nfsUsersWithLdap = nfs_users_with_ldap
if ldap_signing is not None:
activedirectory_config.ldapSigning = ldap_signing
if encrypt_dc_connections is not None:
activedirectory_config.encryptDcConnections = encrypt_dc_connections
if description is not None:
activedirectory_config.description = description
if labels is not None:
activedirectory_config.labels = labels
return activedirectory_config
def UpdateActiveDirectory(self, activedirectory_ref, activedirectory_config,
update_mask):
"""Send a Patch request for the Cloud NetApp Active Directory."""
update_request = (
self.messages.NetappProjectsLocationsActiveDirectoriesPatchRequest(
activeDirectory=activedirectory_config,
name=activedirectory_ref.RelativeName(),
updateMask=update_mask))
update_op = self.client.projects_locations_activeDirectories.Patch(
update_request)
return update_op
class BetaActiveDirectoriesAdapter(ActiveDirectoriesAdapter):
"""Adapter for the Beta Cloud NetApp Files API for Active Directories."""
def __init__(self):
super(BetaActiveDirectoriesAdapter, self).__init__()
self.release_track = base.ReleaseTrack.BETA
self.client = netapp_api_util.GetClientInstance(
release_track=self.release_track
)
self.messages = netapp_api_util.GetMessagesModule(
release_track=self.release_track
)
class AlphaActiveDirectoriesAdapter(BetaActiveDirectoriesAdapter):
"""Adapter for the Alpha Cloud NetApp Files API for Active Directories."""
def __init__(self):
super(AlphaActiveDirectoriesAdapter, self).__init__()
self.release_track = base.ReleaseTrack.ALPHA
self.client = netapp_api_util.GetClientInstance(
release_track=self.release_track
)
self.messages = netapp_api_util.GetMessagesModule(
release_track=self.release_track
)

View File

@@ -0,0 +1,21 @@
# -*- coding: utf-8 -*- #
# Copyright 2023 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.
"""Cloud NetApp Files Backup Policies API client library helper files."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals

View File

@@ -0,0 +1,269 @@
# -*- coding: utf-8 -*- #
# Copyright 2023 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.
"""Commands for interacting with the Cloud NetApp Files Backup Policy API resource."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from apitools.base.py import list_pager
from googlecloudsdk.api_lib.netapp import constants
from googlecloudsdk.api_lib.netapp import util as netapp_util
from googlecloudsdk.api_lib.util import waiter
from googlecloudsdk.calliope import base
from googlecloudsdk.core import log
from googlecloudsdk.core import resources
class BackupPoliciesClient(object):
"""Wrapper for working with Backup Policies in the Cloud NetApp Files API Client."""
def __init__(self, release_track=base.ReleaseTrack.BETA):
if release_track == base.ReleaseTrack.BETA:
self._adapter = BetaBackupPoliciesAdapter()
elif release_track == base.ReleaseTrack.GA:
self._adapter = BackupPoliciesAdapter()
else:
raise ValueError('[{}] is not a valid API version.'.format(
netapp_util.VERSION_MAP[release_track]))
@property
def client(self):
return self._adapter.client
@property
def messages(self):
return self._adapter.messages
def WaitForOperation(self, operation_ref):
"""Waits on the long-running operation until the done field is True.
Args:
operation_ref: the operation reference.
Raises:
waiter.OperationError: if the operation contains an error.
Returns:
the 'response' field of the Operation.
"""
return waiter.WaitFor(
waiter.CloudOperationPollerNoResources(
self.client.projects_locations_operations
),
operation_ref,
'Waiting for [{0}] to finish'.format(operation_ref.Name()),
)
def CreateBackupPolicy(self, backuppolicy_ref, async_, backup_policy):
"""Create a Cloud NetApp Backup Policy."""
request = self.messages.NetappProjectsLocationsBackupPoliciesCreateRequest(
parent=backuppolicy_ref.Parent().RelativeName(),
backupPolicyId=backuppolicy_ref.Name(),
backupPolicy=backup_policy,
)
create_op = self.client.projects_locations_backupPolicies.Create(request)
if async_:
return create_op
operation_ref = resources.REGISTRY.ParseRelativeName(
create_op.name, collection=constants.OPERATIONS_COLLECTION
)
return self.WaitForOperation(operation_ref)
def ParseBackupPolicy(
self,
name=None,
enabled=None,
daily_backup_limit=None,
weekly_backup_limit=None,
monthly_backup_limit=None,
description=None,
labels=None
):
"""Parses the command line arguments for Create Backup Policy into a message.
Args:
name: the name of the Backup Policy
enabled: the Boolean value indicating whether or not backups are made
automatically according to schedule.
daily_backup_limit: the number of daily backups to keep.
weekly_backup_limit: the number of weekly backups to keep.
monthly_backup_limit: the number of monthly backups to keep.
description: the description of the Backup Policy.
labels: the parsed labels value
Returns:
The configuration that will be used as the request body for creating a
Cloud NetApp Backup Policy.
"""
backup_policy = self.messages.BackupPolicy()
backup_policy.name = name
backup_policy.enabled = enabled
backup_policy.dailyBackupLimit = daily_backup_limit
backup_policy.weeklyBackupLimit = weekly_backup_limit
backup_policy.monthlyBackupLimit = monthly_backup_limit
backup_policy.description = description
backup_policy.labels = labels
return backup_policy
def ListBackupPolicies(self, location_ref, limit=None):
"""Make API calls to List Cloud NetApp Backup Policies.
Args:
location_ref: The parsed location of the listed NetApp Backup Policies.
limit: The number of Cloud NetApp Backup Policies
to limit the results to. This limit is passed to
the server and the server does the limiting.
Returns:
Generator that yields the Cloud NetApp Backup Policies.
"""
request = self.messages.NetappProjectsLocationsBackupPoliciesListRequest(
parent=location_ref)
# Check for unreachable locations.
response = self.client.projects_locations_backupPolicies.List(request)
for location in response.unreachable:
log.warning('Location {} may be unreachable.'.format(location))
return list_pager.YieldFromList(
self.client.projects_locations_backupPolicies,
request,
field=constants.BACKUP_POLICY_RESOURCE,
limit=limit,
batch_size_attribute='pageSize')
def GetBackupPolicy(self, backuppolicy_ref):
"""Get Cloud NetApp Backup Policy information."""
request = self.messages.NetappProjectsLocationsBackupPoliciesGetRequest(
name=backuppolicy_ref.RelativeName())
return self.client.projects_locations_backupPolicies.Get(request)
def DeleteBackupPolicy(self, backuppolicy_ref, async_):
"""Deletes an existing Cloud NetApp Backup Policy."""
request = (
self.messages.NetappProjectsLocationsBackupPoliciesDeleteRequest(
name=backuppolicy_ref.RelativeName()
)
)
return self._DeleteBackupPolicy(async_, request)
def _DeleteBackupPolicy(self, async_, request):
delete_op = self.client.projects_locations_backupPolicies.Delete(request)
if async_:
return delete_op
operation_ref = resources.REGISTRY.ParseRelativeName(
delete_op.name, collection=constants.OPERATIONS_COLLECTION
)
return self.WaitForOperation(operation_ref)
def UpdateBackupPolicy(
self, backuppolicy_ref, backup_policy, update_mask, async_
):
"""Updates a Backup Policy.
Args:
backuppolicy_ref: the reference to the Backup Policy.
backup_policy: Backup Policy message, the updated Backup Policy.
update_mask: str, a comma-separated list of updated fields.
async_: bool, if False, wait for the operation to complete.
Returns:
an Operation or Backup Policy message.
"""
update_op = self._adapter.UpdateBackupPolicy(
backuppolicy_ref, backup_policy, update_mask
)
if async_:
return update_op
operation_ref = resources.REGISTRY.ParseRelativeName(
update_op.name, collection=constants.OPERATIONS_COLLECTION
)
return self.WaitForOperation(operation_ref)
def ParseUpdatedBackupPolicy(
self,
backup_policy,
enabled=None,
daily_backup_limit=None,
weekly_backup_limit=None,
monthly_backup_limit=None,
description=None,
labels=None,
):
"""Parses updates into an Backup Policy."""
return self._adapter.ParseUpdatedBackupPolicy(
backup_policy=backup_policy,
enabled=enabled,
daily_backup_limit=daily_backup_limit,
weekly_backup_limit=weekly_backup_limit,
monthly_backup_limit=monthly_backup_limit,
description=description,
labels=labels,
)
class BackupPoliciesAdapter(object):
"""Adapter for the GA Cloud NetApp Files API for Backup Policies."""
def __init__(self):
self.release_track = base.ReleaseTrack.GA
self.client = netapp_util.GetClientInstance(
release_track=self.release_track
)
self.messages = netapp_util.GetMessagesModule(
release_track=self.release_track
)
def ParseUpdatedBackupPolicy(
self, backup_policy, daily_backup_limit=None, weekly_backup_limit=None,
monthly_backup_limit=None, enabled=None, description=None, labels=None
):
"""Parses updates into a new Backup Policy."""
if enabled is not None:
backup_policy.enabled = enabled
if daily_backup_limit is not None:
backup_policy.dailyBackupLimit = daily_backup_limit
if weekly_backup_limit is not None:
backup_policy.weeklyBackupLimit = weekly_backup_limit
if monthly_backup_limit is not None:
backup_policy.monthlyBackupLimit = monthly_backup_limit
if description is not None:
backup_policy.description = description
if labels is not None:
backup_policy.labels = labels
return backup_policy
def UpdateBackupPolicy(self, backuppolicy_ref, backup_policy, update_mask):
"""Send a Patch request for the Cloud NetApp Backup Policy."""
update_request = (
self.messages.NetappProjectsLocationsBackupPoliciesPatchRequest(
backupPolicy=backup_policy,
name=backuppolicy_ref.RelativeName(),
updateMask=update_mask))
update_op = self.client.projects_locations_backupPolicies.Patch(
update_request)
return update_op
class BetaBackupPoliciesAdapter(BackupPoliciesAdapter):
"""Adapter for the Beta Cloud NetApp Files API for Backup Policies."""
def __init__(self):
super(BetaBackupPoliciesAdapter, self).__init__()
self.release_track = base.ReleaseTrack.BETA
self.client = netapp_util.GetClientInstance(
release_track=self.release_track
)
self.messages = netapp_util.GetMessagesModule(
release_track=self.release_track
)

View File

@@ -0,0 +1,21 @@
# -*- coding: utf-8 -*- #
# Copyright 2023 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.
"""Cloud NetApp Files Backup Vaults API client library helper files."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals

View File

@@ -0,0 +1,21 @@
# -*- coding: utf-8 -*- #
# Copyright 2023 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.
"""Cloud NetApp Files Backups API client library helper files."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals

View File

@@ -0,0 +1,261 @@
# -*- coding: utf-8 -*- #
# Copyright 2023 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.
"""Commands for interacting with the Cloud NetApp Files Backups API resource."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from apitools.base.py import list_pager
from googlecloudsdk.api_lib.netapp import constants
from googlecloudsdk.api_lib.netapp import util as netapp_util
from googlecloudsdk.api_lib.util import waiter
from googlecloudsdk.calliope import base
from googlecloudsdk.core import log
from googlecloudsdk.core import resources
class BackupsClient(object):
"""Wrapper for working with Backups in the Cloud NetApp Files API Client."""
def __init__(self, release_track=base.ReleaseTrack.BETA):
if release_track == base.ReleaseTrack.BETA:
self._adapter = BetaBackupsAdapter()
elif release_track == base.ReleaseTrack.GA:
self._adapter = BackupsAdapter()
else:
raise ValueError('[{}] is not a valid API version.'.format(
netapp_util.VERSION_MAP[release_track]))
@property
def client(self):
return self._adapter.client
@property
def messages(self):
return self._adapter.messages
def WaitForOperation(self, operation_ref):
"""Waits on the long-running operation until the done field is True.
Args:
operation_ref: The operation reference.
Returns:
The 'response' field of the Operation.
Raises:
waiter.OperationError: If the operation contains an error.
"""
return waiter.WaitFor(
waiter.CloudOperationPollerNoResources(
self.client.projects_locations_operations
),
operation_ref,
'Waiting for [{0}] to finish'.format(operation_ref.Name()),
)
def CreateBackup(self, backup_ref, async_, backup):
"""Create a Cloud NetApp Backup."""
request = (
self.messages.NetappProjectsLocationsBackupVaultsBackupsCreateRequest(
parent=backup_ref.Parent().RelativeName(),
backupId=backup_ref.Name(),
backup=backup,
)
)
create_op = self.client.projects_locations_backupVaults_backups.Create(
request
)
if async_:
return create_op
operation_ref = resources.REGISTRY.ParseRelativeName(
create_op.name, collection=constants.OPERATIONS_COLLECTION
)
return self.WaitForOperation(operation_ref)
def ParseBackup(
self,
name=None,
source_snapshot=None,
source_volume=None,
description=None,
labels=None,
):
"""Parses the command line arguments for Create Backup into a message.
Args:
name: The name of the Backup.
source_snapshot: The Source Snapshot of the Backup.
source_volume: The Source Volume of the Backup.
description: The description of the Backup.
labels: The parsed labels value.
Returns:
The configuration that will be used ass the request body for creating a
Cloud NetApp Backup.
"""
backup = self.messages.Backup()
backup.name = name
backup.sourceSnapshot = source_snapshot
backup.sourceVolume = source_volume
backup.description = description
backup.labels = labels
return backup
def ListBackups(self, backupvault_ref, limit=None):
"""Make API calls to List Cloud NetApp Backups.
Args:
backupvault_ref: The parsed Backup Vault of the listed NetApp Backups.
limit: The number of Cloud NetApp Backups to limit the results to.
This limit is passed to the server and the server does the limiting.
Returns:
Generator that yields the Cloud NetApp Backups.
"""
request = (
self.messages.NetappProjectsLocationsBackupVaultsBackupsListRequest(
parent=backupvault_ref
)
)
# Check for unreachable locations.
response = self.client.projects_locations_backupVaults_backups.List(request)
for location in response.unreachable:
log.warning('Location {} may be unreachable.'.format(location))
return list_pager.YieldFromList(
self.client.projects_locations_backupVaults_backups,
request,
field=constants.BACKUP_RESOURCE,
limit=limit,
batch_size_attribute='pageSize',
)
def GetBackup(self, backup_ref):
"""Get Cloud NetApp Backup information."""
request = (
self.messages.NetappProjectsLocationsBackupVaultsBackupsGetRequest(
name=backup_ref.RelativeName()
)
)
return self.client.projects_locations_backupVaults_backups.Get(request)
def DeleteBackup(self, backup_ref, async_):
"""Deletes an existing Cloud NetApp Backup."""
request = (
self.messages.NetappProjectsLocationsBackupVaultsBackupsDeleteRequest(
name=backup_ref.RelativeName()
)
)
return self._DeleteBackup(async_, request)
def _DeleteBackup(self, async_, request):
delete_op = self.client.projects_locations_backupVaults_backups.Delete(
request
)
if async_:
return delete_op
operation_ref = resources.REGISTRY.ParseRelativeName(
delete_op.name, collection=constants.OPERATIONS_COLLECTION
)
return self.WaitForOperation(operation_ref)
def UpdateBackup(
self, backup_ref, backup, update_mask, async_
):
"""Updates a Backup.
Args:
backup_ref: The reference to the Backup.
backup: Backup message, the updated Backup.
update_mask: str, a comma-separated list of updated fields.
async_: bool, if False, wait for the operation to complete.
Returns:
an Operation or Backup Vault message.
"""
update_op = self._adapter.UpdateBackup(
backup_ref, backup, update_mask
)
if async_:
return update_op
operation_ref = resources.REGISTRY.ParseRelativeName(
update_op.name, collection=constants.OPERATIONS_COLLECTION
)
return self.WaitForOperation(operation_ref)
def ParseUpdatedBackup(
self,
backup,
description=None,
labels=None,
):
"""Parses updates into a Backup."""
return self._adapter.ParseUpdatedBackup(
backup,
description=description,
labels=labels,
)
class BackupsAdapter(object):
"""Adapter for the GA Cloud NetApp Files API for Backups."""
def __init__(self):
self.release_track = base.ReleaseTrack.GA
self.client = netapp_util.GetClientInstance(
release_track=self.release_track
)
self.messages = netapp_util.GetMessagesModule(
release_track=self.release_track
)
def ParseUpdatedBackup(
self,
backup,
description=None,
labels=None,
):
"""Parses updates into a new Backup."""
if description is not None:
backup.description = description
if labels is not None:
backup.labels = labels
return backup
def UpdateBackup(self, backup_ref, backup, update_mask):
"""Send a Patch request for the Cloud NetApp Backup."""
update_request = (
self.messages.NetappProjectsLocationsBackupVaultsBackupsPatchRequest(
backup=backup,
name=backup_ref.RelativeName(),
updateMask=update_mask))
update_op = self.client.projects_locations_backupVaults_backups.Patch(
update_request)
return update_op
class BetaBackupsAdapter(BackupsAdapter):
"""Adapter for the Beta Cloud NetApp Files API for Backups."""
def __init__(self):
super(BetaBackupsAdapter, self).__init__()
self.release_track = base.ReleaseTrack.BETA
self.client = netapp_util.GetClientInstance(
release_track=self.release_track
)
self.messages = netapp_util.GetMessagesModule(
release_track=self.release_track
)

View File

@@ -0,0 +1,307 @@
# -*- coding: utf-8 -*- #
# Copyright 2023 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.
"""Commands for interacting with the Cloud NetApp Files Backup Vaults API resource."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from apitools.base.py import list_pager
from googlecloudsdk.api_lib.netapp import constants
from googlecloudsdk.api_lib.netapp import util as netapp_util
from googlecloudsdk.api_lib.util import waiter
from googlecloudsdk.calliope import base
from googlecloudsdk.core import log
from googlecloudsdk.core import resources
class BackupVaultsClient(object):
"""Wrapper for working with Backup Vaults in the Cloud NetApp Files API Client."""
def __init__(self, release_track=base.ReleaseTrack.BETA):
if release_track == base.ReleaseTrack.BETA:
self._adapter = BetaBackupVaultsAdapter()
elif release_track == base.ReleaseTrack.GA:
self._adapter = BackupVaultsAdapter()
else:
raise ValueError('[{}] is not a valid API version.'.format(
netapp_util.VERSION_MAP[release_track]))
@property
def client(self):
return self._adapter.client
@property
def messages(self):
return self._adapter.messages
def WaitForOperation(self, operation_ref):
"""Waits on the long-running operation until the done field is True.
Args:
operation_ref: The operation reference.
Raises:
waiter.OperationError: If the operation contains an error.
Returns:
The 'response' field of the Operation.
"""
return waiter.WaitFor(
waiter.CloudOperationPollerNoResources(
self.client.projects_locations_operations
),
operation_ref,
'Waiting for [{0}] to finish'.format(operation_ref.Name()),
)
def CreateBackupVault(self, backupvault_ref, async_, backup_vault):
"""Create a Cloud NetApp Backup Vault."""
request = self.messages.NetappProjectsLocationsBackupVaultsCreateRequest(
parent=backupvault_ref.Parent().RelativeName(),
backupVaultId=backupvault_ref.Name(),
backupVault=backup_vault,
)
create_op = self.client.projects_locations_backupVaults.Create(request)
if async_:
return create_op
operation_ref = resources.REGISTRY.ParseRelativeName(
create_op.name, collection=constants.OPERATIONS_COLLECTION
)
return self.WaitForOperation(operation_ref)
def ParseBackupVault(
self,
name=None,
backup_vault_type=None,
backup_region=None,
description=None,
labels=None,
backup_retention_policy=None,
kms_config=None,
):
"""Parses the command line arguments for Create BackupVault into a message.
Args:
name: The name of the Backup Vault.
backup_vault_type: The type of the Backup Vault.
backup_region: The location of the Backup Vault.
description: The description of the Backup Vault.
labels: The parsed labels value.
backup_retention_policy: The backup retention policy of the Backup Vault.
kms_config: The KMS Config resource name for CMEK.
Returns:
The configuration that will be used ass the request body for creating a
Cloud NetApp Backup Vault.
"""
backup_vault = self.messages.BackupVault()
backup_vault.name = name
if backup_vault_type is not None:
backup_vault.backupVaultType = backup_vault_type
if backup_region is not None:
backup_vault.backupRegion = backup_region
backup_vault.description = description
backup_vault.labels = labels
if backup_retention_policy is not None:
backup_vault.backupRetentionPolicy = self.ParseBackupRetentionPolicy(
backup_retention_policy
)
if kms_config is not None:
backup_vault.kmsConfig = kms_config
return backup_vault
def ListBackupVaults(self, location_ref, limit=None):
"""Make API calls to List Cloud NetApp Backup Vaults.
Args:
location_ref: The parsed location of the listed NetApp Backup Vaults.
limit: The number of Cloud NetApp Backup Vaults to limit the results to.
This limit is passed to the server and the server does the limiting.
Returns:
Generator that yields the Cloud NetApp Backup Vaults.
"""
request = self.messages.NetappProjectsLocationsBackupVaultsListRequest(
parent=location_ref)
# Check for unreachable locations.
response = self.client.projects_locations_backupVaults.List(request)
for location in response.unreachable:
log.warning('Location {} may be unreachable.'.format(location))
return list_pager.YieldFromList(
self.client.projects_locations_backupVaults,
request,
field=constants.BACKUP_VAULT_RESOURCE,
limit=limit,
batch_size_attribute='pageSize')
def GetBackupVault(self, backupvault_ref):
"""Get Cloud NetApp Backup Vault information."""
request = self.messages.NetappProjectsLocationsBackupVaultsGetRequest(
name=backupvault_ref.RelativeName())
return self.client.projects_locations_backupVaults.Get(request)
def DeleteBackupVault(self, backupvault_ref, async_):
"""Deletes an existing Cloud NetApp Backup Vault."""
request = (
self.messages.NetappProjectsLocationsBackupVaultsDeleteRequest(
name=backupvault_ref.RelativeName()
)
)
return self._DeleteBackupVault(async_, request)
def _DeleteBackupVault(self, async_, request):
delete_op = self.client.projects_locations_backupVaults.Delete(request)
if async_:
return delete_op
operation_ref = resources.REGISTRY.ParseRelativeName(
delete_op.name, collection=constants.OPERATIONS_COLLECTION
)
return self.WaitForOperation(operation_ref)
def UpdateBackupVault(
self, backupvault_ref, backup_vault, update_mask, async_
):
"""Updates a Backup Vault.
Args:
backupvault_ref: The reference to the backup vault.
backup_vault: Backup Vault message, the updated backup vault.
update_mask: A comma-separated list of updated fields.
async_: If False, wait for the operation to complete.
Returns:
An Operation or Backup Vault message.
"""
update_op = self._adapter.UpdateBackupVault(
backupvault_ref, backup_vault, update_mask
)
if async_:
return update_op
operation_ref = resources.REGISTRY.ParseRelativeName(
update_op.name, collection=constants.OPERATIONS_COLLECTION
)
return self.WaitForOperation(operation_ref)
def ParseUpdatedBackupVault(
self,
backup_vault,
description=None,
labels=None,
backup_retention_policy=None,
):
"""Parses updates into a kms config."""
return self._adapter.ParseUpdatedBackupVault(
backup_vault=backup_vault,
description=description,
labels=labels,
backup_retention_policy=backup_retention_policy,
)
def ParseBackupRetentionPolicy(self, backup_retention_policy):
"""Parses the command line arguments for Backup Vault Policy into a message."""
backup_retention_policy_message = self.messages.BackupRetentionPolicy()
backup_retention_policy_message.backupMinimumEnforcedRetentionDays = (
backup_retention_policy.get('backup-minimum-enforced-retention-days')
)
backup_retention_policy_message.dailyBackupImmutable = (
backup_retention_policy.get('daily-backup-immutable')
)
backup_retention_policy_message.weeklyBackupImmutable = (
backup_retention_policy.get('weekly-backup-immutable')
)
backup_retention_policy_message.monthlyBackupImmutable = (
backup_retention_policy.get('monthly-backup-immutable')
)
backup_retention_policy_message.manualBackupImmutable = (
backup_retention_policy.get('manual-backup-immutable')
)
return backup_retention_policy_message
class BackupVaultsAdapter(object):
"""Adapter for the GA Cloud NetApp Files API for Backup Vaults."""
def __init__(self):
self.release_track = base.ReleaseTrack.GA
self.client = netapp_util.GetClientInstance(
release_track=self.release_track
)
self.messages = netapp_util.GetMessagesModule(
release_track=self.release_track
)
def ParseUpdatedBackupVault(
self,
backup_vault,
description=None,
labels=None,
backup_retention_policy=None,
):
"""Parses updates into a new Backup Vault."""
if description is not None:
backup_vault.description = description
if labels is not None:
backup_vault.labels = labels
if backup_retention_policy is not None:
backup_vault.backupRetentionPolicy = self.ParseBackupRetentionPolicy(
backup_retention_policy
)
return backup_vault
def UpdateBackupVault(self, backupvault_ref, backup_vault, update_mask):
"""Send a Patch request for the Cloud NetApp Backup Vault."""
update_request = (
self.messages.NetappProjectsLocationsBackupVaultsPatchRequest(
backupVault=backup_vault,
name=backupvault_ref.RelativeName(),
updateMask=update_mask))
return self.client.projects_locations_backupVaults.Patch(
update_request
)
def ParseBackupRetentionPolicy(self, backup_retention_policy):
"""Parses the command line arguments for Backup Vault Policy into a message."""
backup_retention_policy_message = self.messages.BackupRetentionPolicy()
backup_retention_policy_message.backupMinimumEnforcedRetentionDays = (
backup_retention_policy.get('backup-minimum-enforced-retention-days')
)
backup_retention_policy_message.dailyBackupImmutable = (
backup_retention_policy.get('daily-backup-immutable')
)
backup_retention_policy_message.weeklyBackupImmutable = (
backup_retention_policy.get('weekly-backup-immutable')
)
backup_retention_policy_message.monthlyBackupImmutable = (
backup_retention_policy.get('monthly-backup-immutable')
)
backup_retention_policy_message.manualBackupImmutable = (
backup_retention_policy.get('manual-backup-immutable')
)
return backup_retention_policy_message
class BetaBackupVaultsAdapter(BackupVaultsAdapter):
"""Adapter for the Beta Cloud NetApp Files API for Backup Vaults."""
def __init__(self):
super(BetaBackupVaultsAdapter, self).__init__()
self.release_track = base.ReleaseTrack.BETA
self.client = netapp_util.GetClientInstance(
release_track=self.release_track
)
self.messages = netapp_util.GetMessagesModule(
release_track=self.release_track
)

View File

@@ -0,0 +1,50 @@
# -*- 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.
"""Constants for interacting with the Cloud NetApp Files API."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
API_NAME = 'netapp'
ALPHA_API_VERSION = 'v1alpha1'
BETA_API_VERSION = 'v1beta1'
BACKUPPOLICIES_COLLECTION = 'netapp.projects.locations.backupPolicies'
BACKUPVAULTS_COLLECTION = 'netapp.projects.locations.backupVaults'
BACKUPS_COLLECTION = 'netapp.projects.locations.backupVaults.backups'
VOLUMES_COLLECTION = 'netapp.projects.locations.volumes'
STORAGEPOOLS_COLLECTION = 'netapp.projects.locations.storagePools'
ACTIVEDIRECTORIES_COLLECTION = 'netapp.projects.locations.activeDirectories'
REPLICATIONS_COLLECTION = 'netapp.projects.locations.volumes.replications'
SNAPSHOTS_COLLECTION = 'netapp.projects.locations.volumes.snapshots'
KMSCONFIGS_COLLECTION = 'netapp.projects.locations.kmsConfigs'
OPERATIONS_COLLECTION = 'netapp.projects.locations.operations'
LOCATIONS_COLLECTION = 'netapp.projects.locations'
QUOTA_RULES_COLLECTION = 'netapp.projects.locations.volumes.quotaRules'
HOST_GROUPS_COLLECTION = 'netapp.projects.locations.hostGroups'
ACTIVE_DIRECTORY_RESOURCE = 'activeDirectories'
STORAGE_POOL_RESOURCE = 'storagePools'
VOLUME_RESOURCE = 'volumes'
REPLICATION_RESOURCE = 'replications'
SNAPSHOT_RESOURCE = 'snapshots'
KMS_CONFIG_RESOURCE = 'kmsConfigs'
BACKUP_POLICY_RESOURCE = 'backupPolicies'
BACKUP_VAULT_RESOURCE = 'backupVaults'
BACKUP_RESOURCE = 'backups'
QUOTA_RULE_RESOURCE = 'quotaRules'
HOST_GROUP_RESOURCE = 'hostGroups'

View File

@@ -0,0 +1,16 @@
# -*- coding: utf-8 -*- #
# Copyright 2025 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.
"""Cloud NetApp Files Host Groups API client library helper files."""

View File

@@ -0,0 +1,241 @@
# -*- coding: utf-8 -*- #
# Copyright 2025 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.
"""Commands for interacting with the Cloud NetApp Files Host Groups API resource."""
from apitools.base.py import list_pager
from googlecloudsdk.api_lib.netapp import constants
from googlecloudsdk.api_lib.netapp import util as netapp_api_util
from googlecloudsdk.api_lib.util import waiter
from googlecloudsdk.calliope import base
from googlecloudsdk.core import log
from googlecloudsdk.core import resources
class HostGroupsClient(object):
"""Wrapper for working with Host Groups in the Cloud NetApp Files API Client."""
def __init__(self, release_track=base.ReleaseTrack.ALPHA):
self.release_track = release_track
if self.release_track == base.ReleaseTrack.ALPHA:
self._adapter = AlphaHostGroupsAdapter()
elif self.release_track == base.ReleaseTrack.BETA:
self._adapter = BetaHostGroupsAdapter()
elif self.release_track == base.ReleaseTrack.GA:
self._adapter = HostGroupsAdapter()
else:
raise ValueError(
'[{}] is not a valid API version.'.format(
netapp_api_util.VERSION_MAP[release_track]
)
)
@property
def client(self):
return self._adapter.client
@property
def messages(self):
return self._adapter.messages
def WaitForOperation(self, operation_ref):
"""Waits on the long-running operation until the done field is True.
Args:
operation_ref: the operation reference.
Raises:
waiter.OperationError: if the operation contains an error.
Returns:
the 'response' field of the Operation.
"""
return waiter.WaitFor(
waiter.CloudOperationPollerNoResources(
self.client.projects_locations_operations
),
operation_ref,
'Waiting for [{0}] to finish'.format(operation_ref.Name()),
)
def CreateHostGroup(self, host_group_ref, async_, config):
"""Create a Cloud NetApp Host Group."""
request = self.messages.NetappProjectsLocationsHostGroupsCreateRequest(
parent=host_group_ref.Parent().RelativeName(),
hostGroupId=host_group_ref.Name(),
hostGroup=config,
)
create_op = self.client.projects_locations_hostGroups.Create(request)
if async_:
return create_op
operation_ref = resources.REGISTRY.ParseRelativeName(
create_op.name, collection=constants.OPERATIONS_COLLECTION
)
return self.WaitForOperation(operation_ref)
def ParseHostGroupConfig(
self,
name=None,
host_group_type=None,
hosts=None,
os_type=None,
description=None,
labels=None,
):
"""Parses the command line arguments for Create Host Group into a config."""
host_group = self.messages.HostGroup()
host_group.name = name
host_group.type = host_group_type
host_group.hosts = hosts
host_group.osType = os_type
host_group.description = description
host_group.labels = labels
return host_group
def ListHostGroups(self, location_ref):
"""List Cloud NetApp Host Groups.
Args:
location_ref: The parent location to list Cloud Netapp Host Groups.
Returns:
Generator that yields the Cloud Netapp Host Groups.
"""
request = self.messages.NetappProjectsLocationsHostGroupsListRequest(
parent=location_ref
)
# Check for unreachable locations.
response = self.client.projects_locations_hostGroups.List(request)
for location in response.unreachable:
log.warning('Location {} may be unreachable.'.format(location))
return list_pager.YieldFromList(
self.client.projects_locations_hostGroups,
request,
field=constants.HOST_GROUP_RESOURCE,
batch_size_attribute='pageSize',
)
def GetHostGroup(self, host_group_ref):
"""Get a Cloud NetApp Host Group."""
request = self.messages.NetappProjectsLocationsHostGroupsGetRequest(
name=host_group_ref.RelativeName()
)
return self.client.projects_locations_hostGroups.Get(request)
def DeleteHostGroup(self, host_group_ref, async_):
"""Delete a Cloud NetApp Host Group."""
request = self.messages.NetappProjectsLocationsHostGroupsDeleteRequest(
name=host_group_ref.RelativeName()
)
delete_op = self.client.projects_locations_hostGroups.Delete(request)
if async_:
return delete_op
operation_ref = resources.REGISTRY.ParseRelativeName(
delete_op.name, collection=constants.OPERATIONS_COLLECTION
)
return self.WaitForOperation(operation_ref)
def ParseUpdatedHostGroupConfig(
self,
host_group_config,
hosts=None,
description=None,
labels=None,
):
"""Parses updates into a host group config.
Args:
host_group_config: The host group config to update.
hosts: list of str, new list of hosts, if any.
description: str, a new description, if any.
labels: LabelsValue message, the new labels value, if any.
Returns:
The host group message.
"""
if hosts is not None:
host_group_config.hosts = hosts
if description is not None:
host_group_config.description = description
if labels is not None:
host_group_config.labels = labels
return host_group_config
def UpdateHostGroup(self, host_group_ref, host_group, update_mask, async_):
"""Updates a Cloud NetApp Host Group.
Args:
host_group_ref: the reference to the Host Group.
host_group: Host group config, the updated host group.
update_mask: str, a comma-separated list of updated fields.
async_: bool, if False, wait for the operation to complete.
Returns:
an Operation or HostGroup message.
"""
request = self.messages.NetappProjectsLocationsHostGroupsPatchRequest(
name=host_group_ref.RelativeName(),
updateMask=update_mask,
hostGroup=host_group,
)
update_op = self.client.projects_locations_hostGroups.Patch(request)
if async_:
return update_op
operation_ref = resources.REGISTRY.ParseRelativeName(
update_op.name, collection=constants.OPERATIONS_COLLECTION
)
return self.WaitForOperation(operation_ref)
class HostGroupsAdapter(object):
"""Adapter for the Cloud NetApp Files API Host Group resource."""
def __init__(self):
self.release_track = base.ReleaseTrack.GA
self.client = netapp_api_util.GetClientInstance(
release_track=self.release_track
)
self.messages = netapp_api_util.GetMessagesModule(
release_track=self.release_track
)
class BetaHostGroupsAdapter(HostGroupsAdapter):
"""Adapter for the Beta Cloud NetApp Files API Host Group resource."""
def __init__(self):
super(BetaHostGroupsAdapter, self).__init__()
self.release_track = base.ReleaseTrack.BETA
self.client = netapp_api_util.GetClientInstance(
release_track=self.release_track
)
self.messages = netapp_api_util.GetMessagesModule(
release_track=self.release_track
)
class AlphaHostGroupsAdapter(BetaHostGroupsAdapter):
"""Adapter for the Cloud NetApp Files API Host Group resource."""
def __init__(self):
super(AlphaHostGroupsAdapter, self).__init__()
self.release_track = base.ReleaseTrack.ALPHA
self.client = netapp_api_util.GetClientInstance(
release_track=self.release_track
)
self.messages = netapp_api_util.GetMessagesModule(
release_track=self.release_track
)

View File

@@ -0,0 +1,21 @@
# -*- coding: utf-8 -*- #
# Copyright 2023 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.
"""Cloud NetApp Files KMS Configs API client library helper files."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals

View File

@@ -0,0 +1,260 @@
# -*- coding: utf-8 -*- #
# Copyright 2023 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.
"""Commands for interacting with the Cloud NetApp Files KMS Config API resource."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from apitools.base.py import list_pager
from googlecloudsdk.api_lib.netapp import constants
from googlecloudsdk.api_lib.netapp import util as netapp_api_util
from googlecloudsdk.api_lib.util import waiter
from googlecloudsdk.calliope import base
from googlecloudsdk.core import log
from googlecloudsdk.core import resources
class KmsConfigsClient(object):
"""Wrapper for working with KMS Configs in the Cloud NetApp Files API Client."""
def __init__(self, release_track=base.ReleaseTrack.BETA):
if release_track == base.ReleaseTrack.BETA:
self._adapter = BetaKmsConfigsAdapter()
elif release_track == base.ReleaseTrack.GA:
self._adapter = KmsConfigsAdapter()
else:
raise ValueError('[{}] is not a valid API version.'.format(
netapp_api_util.VERSION_MAP[release_track]))
@property
def client(self):
return self._adapter.client
@property
def messages(self):
return self._adapter.messages
def WaitForOperation(self, operation_ref):
"""Waits on the long-running operation until the done field is True.
Args:
operation_ref: the operation reference.
Raises:
waiter.OperationError: if the operation contains an error.
Returns:
the 'response' field of the Operation.
"""
return waiter.WaitFor(
waiter.CloudOperationPollerNoResources(
self.client.projects_locations_operations
),
operation_ref,
'Waiting for [{0}] to finish'.format(operation_ref.Name()),
)
def CreateKmsConfig(self, kmsconfig_ref, async_, kms_config):
"""Create a Cloud NetApp KMS Config."""
request = self.messages.NetappProjectsLocationsKmsConfigsCreateRequest(
parent=kmsconfig_ref.Parent().RelativeName(),
kmsConfigId=kmsconfig_ref.Name(),
kmsConfig=kms_config,
)
create_op = self.client.projects_locations_kmsConfigs.Create(request)
if async_:
return create_op
operation_ref = resources.REGISTRY.ParseRelativeName(
create_op.name, collection=constants.OPERATIONS_COLLECTION
)
return self.WaitForOperation(operation_ref)
def ParseKmsConfig(
self, name=None, crypto_key_name=None, description=None, labels=None
):
"""Parses the command line arguments for Create KMS Config into a message.
Args:
name: the name of the KMS Config
crypto_key_name: the crypto key name of the KMS Config
description: the description of the KMS COnfig
labels: the parsed labels value
Returns:
The configuration that will be used as the request body for creating a
Cloud NetApp KMS Config.
"""
kms_config = self.messages.KmsConfig()
kms_config.name = name
kms_config.cryptoKeyName = crypto_key_name
kms_config.description = description
kms_config.labels = labels
return kms_config
def ListKmsConfigs(self, location_ref, limit=None):
"""Make API calls to List Cloud NetApp KMS Configs.
Args:
location_ref: The parsed location of the listed NetApp KMS Configs.
limit: The number of Cloud NetApp KMS Configs to limit the results to.
This limit is passed to the server and the server does the limiting.
Returns:
Generator that yields the Cloud NetApp KMS Config.
"""
request = self.messages.NetappProjectsLocationsKmsConfigsListRequest(
parent=location_ref)
# Check for unreachable locations.
response = self.client.projects_locations_kmsConfigs.List(request)
for location in response.unreachable:
log.warning('Location {} may be unreachable.'.format(location))
return list_pager.YieldFromList(
self.client.projects_locations_kmsConfigs,
request,
field=constants.KMS_CONFIG_RESOURCE,
limit=limit,
batch_size_attribute='pageSize')
def GetKmsConfig(self, kmsconfig_ref):
"""Get Cloud NetApp KMS Config information."""
request = self.messages.NetappProjectsLocationsKmsConfigsGetRequest(
name=kmsconfig_ref.RelativeName())
return self.client.projects_locations_kmsConfigs.Get(request)
def DeleteKmsConfig(self, kmsconfig_ref, async_):
"""Deletes an existing Cloud NetApp KMS Config."""
request = (
self.messages.NetappProjectsLocationsKmsConfigsDeleteRequest(
name=kmsconfig_ref.RelativeName()
)
)
return self._DeleteKmsConfig(async_, request)
def _DeleteKmsConfig(self, async_, request):
delete_op = self.client.projects_locations_kmsConfigs.Delete(request)
if async_:
return delete_op
operation_ref = resources.REGISTRY.ParseRelativeName(
delete_op.name, collection=constants.OPERATIONS_COLLECTION
)
return self.WaitForOperation(operation_ref)
def UpdateKmsConfig(self, kmsconfig_ref, kms_config, update_mask, async_):
"""Updates a KMS Config.
Args:
kmsconfig_ref: the reference to the kms config.
kms_config: KMS Config message, the updated kms config.
update_mask: str, a comma-separated list of updated fields.
async_: bool, if False, wait for the operation to complete.
Returns:
an Operation or KMS Config message.
"""
update_op = self._adapter.UpdateKmsConfig(kmsconfig_ref,
kms_config, update_mask)
if async_:
return update_op
operation_ref = resources.REGISTRY.ParseRelativeName(
update_op.name, collection=constants.OPERATIONS_COLLECTION)
return self.WaitForOperation(operation_ref)
def ParseUpdatedKmsConfig(self,
kms_config,
crypto_key_name,
description=None,
labels=None):
"""Parses updates into an kms config."""
return self._adapter.ParseUpdatedKmsConfig(
kms_config=kms_config,
crypto_key_name=crypto_key_name,
description=description,
labels=labels)
def EncryptKmsConfig(self, kmsconfig_ref, async_):
"""Encrypts the volumes attached to the Cloud NetApp KMS Config."""
request = (
self.messages.NetappProjectsLocationsKmsConfigsEncryptRequest(
name=kmsconfig_ref.RelativeName()
)
)
encrypt_op = self.client.projects_locations_kmsConfigs.Encrypt(request)
if async_:
return encrypt_op
operation_ref = resources.REGISTRY.ParseRelativeName(
encrypt_op.name, collection=constants.OPERATIONS_COLLECTION)
return self.WaitForOperation(operation_ref)
def VerifyKmsConfig(self, kmsconfig_ref):
"""Verifies the Cloud NetApp Volumes KMS Config is reachable."""
request = (
self.messages.NetappProjectsLocationsKmsConfigsVerifyRequest(
name=kmsconfig_ref.RelativeName()
)
)
return self.client.projects_locations_kmsConfigs.Verify(
request
)
class KmsConfigsAdapter(object):
"""Adapter for the Cloud NetApp Files API for KMS Configs."""
def __init__(self):
self.release_track = base.ReleaseTrack.GA
self.client = netapp_api_util.GetClientInstance(
release_track=self.release_track
)
self.messages = netapp_api_util.GetMessagesModule(
release_track=self.release_track
)
def ParseUpdatedKmsConfig(
self, kms_config, crypto_key_name=None, description=None, labels=None
):
"""Parses updates into a new kms config."""
if crypto_key_name is not None:
kms_config.cryptoKeyName = crypto_key_name
if description is not None:
kms_config.description = description
if labels is not None:
kms_config.labels = labels
return kms_config
def UpdateKmsConfig(self, kmsconfig_ref, kms_config, update_mask):
"""Send a Patch request for the Cloud NetApp KMS Config."""
update_request = (
self.messages.NetappProjectsLocationsKmsConfigsPatchRequest(
kmsConfig=kms_config,
name=kmsconfig_ref.RelativeName(),
updateMask=update_mask))
update_op = self.client.projects_locations_kmsConfigs.Patch(
update_request)
return update_op
class BetaKmsConfigsAdapter(KmsConfigsAdapter):
"""Adapter for the Beta Cloud NetApp Files API for KMS Configs."""
def __init__(self):
super(BetaKmsConfigsAdapter, self).__init__()
self.release_track = base.ReleaseTrack.BETA
self.client = netapp_api_util.GetClientInstance(
release_track=self.release_track
)
self.messages = netapp_api_util.GetMessagesModule(
release_track=self.release_track
)

View File

@@ -0,0 +1,168 @@
# -*- 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.
"""Useful commands for interacting with the Cloud NetApp Files API."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from apitools.base.py import list_pager
from googlecloudsdk.api_lib.netapp import util
from googlecloudsdk.api_lib.util import waiter
from googlecloudsdk.calliope import base
API_NAME = 'netapp'
ALPHA_API_VERSION = 'v1alpha1'
class NetAppClient(object):
"""Wrapper for working with the Cloud NetApp Files API Client."""
def __init__(self, release_track=base.ReleaseTrack.ALPHA):
if release_track == base.ReleaseTrack.ALPHA:
self._adapter = AlphaNetappAdapter()
elif release_track == base.ReleaseTrack.BETA:
self._adapter = BetaNetappAdapter()
elif release_track == base.ReleaseTrack.GA:
self._adapter = NetappAdapter()
else:
raise ValueError('[{}] is not a valid API version.'.format(
util.VERSION_MAP[release_track]))
@property
def client(self):
return self._adapter.client
@property
def messages(self):
return self._adapter.messages
def GetOperation(self, operation_ref):
"""Gets description of a long-running operation.
Args:
operation_ref: the operation reference.
Returns:
messages.GoogleLongrunningOperation, the operation.
"""
request = self.messages.NetappProjectsLocationsOperationsGetRequest(
name=operation_ref.RelativeName())
return self.client.projects_locations_operations.Get(request)
def WaitForOperation(self, operation_ref):
"""Waits on the long-running operation until the done field is True.
Args:
operation_ref: the operation reference.
Raises:
waiter.OperationError: if the operation contains an error.
Returns:
the 'response' field of the Operation.
"""
return waiter.WaitFor(
waiter.CloudOperationPollerNoResources(
self.client.projects_locations_operations), operation_ref,
'Waiting for [{0}] to finish'.format(operation_ref.Name()))
def CancelOperation(self, operation_ref):
"""Cancels a long-running operation.
Args:
operation_ref: the operation reference.
Returns:
Empty response message.
"""
request = self.messages.NetappProjectsLocationsOperationsCancelRequest(
name=operation_ref.RelativeName())
return self.client.projects_locations_operations.Cancel(request)
def GetLocation(self, location_ref):
request = self.messages.NetappProjectsLocationsGetRequest(name=location_ref)
return self.client.projects_locations.Get(request)
def ListLocations(self, project_ref, limit=None):
request = self.messages.NetappProjectsLocationsListRequest(
name=project_ref.RelativeName())
return list_pager.YieldFromList(
self.client.projects_locations,
request,
field='locations',
limit=limit,
batch_size_attribute='pageSize')
def ListOperations(self, location_ref, limit=None): # pylint: disable=redefined-builtin
"""Make API calls to List active Cloud NetApp operations.
Args:
location_ref: The parsed location of the listed NetApp resources.
limit: The number of Cloud NetApp resources to limit the results to. This
limit is passed to the server and the server does the limiting.
Returns:
Generator that yields the Cloud NetApp resources.
"""
request = self.messages.NetappProjectsLocationsOperationsListRequest(
name=location_ref)
return list_pager.YieldFromList(
self.client.projects_locations_operations,
request,
field='operations',
limit=limit,
batch_size_attribute='pageSize')
class NetappAdapter(object):
"""Adapter for the Cloud NetApp Files v1 API."""
def __init__(self):
self.release_track = base.ReleaseTrack.GA
self.client = util.GetClientInstance(
release_track=self.release_track
)
self.messages = util.GetMessagesModule(
release_track=self.release_track
)
class BetaNetappAdapter(NetappAdapter):
"""Adapter for the Beta Cloud NetApp Files API."""
def __init__(self):
super(BetaNetappAdapter, self).__init__()
self.release_track = base.ReleaseTrack.BETA
self.client = util.GetClientInstance(
release_track=self.release_track
)
self.messages = util.GetMessagesModule(
release_track=self.release_track
)
class AlphaNetappAdapter(BetaNetappAdapter):
"""Adapter for the Alpha Cloud NetApp Files API."""
def __init__(self):
super(AlphaNetappAdapter, self).__init__()
self.release_track = base.ReleaseTrack.ALPHA
self.client = util.GetClientInstance(
release_track=self.release_track
)
self.messages = util.GetMessagesModule(
release_track=self.release_track
)

View File

@@ -0,0 +1,21 @@
# -*- 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.
"""Cloud NetApp Files Storage Pools API client library helper files."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals

View File

@@ -0,0 +1,497 @@
# -*- 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.
"""Commands for interacting with the Cloud NetApp Files Storage Pool API resource."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from apitools.base.py import list_pager
from googlecloudsdk.api_lib.netapp import constants
from googlecloudsdk.api_lib.netapp import util as netapp_api_util
from googlecloudsdk.api_lib.util import waiter
from googlecloudsdk.calliope import base
from googlecloudsdk.core import log
from googlecloudsdk.core import resources
class StoragePoolsClient(object):
"""Wrapper for working with Storage Pool in the Cloud NetApp Files API Client.
"""
def __init__(self, release_track=base.ReleaseTrack.ALPHA):
self.release_track = release_track
if self.release_track == base.ReleaseTrack.ALPHA:
self._adapter = AlphaStoragePoolsAdapter()
elif self.release_track == base.ReleaseTrack.BETA:
self._adapter = BetaStoragePoolsAdapter()
elif self.release_track == base.ReleaseTrack.GA:
self._adapter = StoragePoolsAdapter()
else:
raise ValueError('[{}] is not a valid API version.'.format(
netapp_api_util.VERSION_MAP[release_track]))
@property
def client(self):
return self._adapter.client
@property
def messages(self):
return self._adapter.messages
def WaitForOperation(self, operation_ref):
"""Waits on the long-running operation until the done field is True.
Args:
operation_ref: the operation reference.
Raises:
waiter.OperationError: if the operation contains an error.
Returns:
the 'response' field of the Operation.
"""
return waiter.WaitFor(
waiter.CloudOperationPollerNoResources(
self.client.projects_locations_operations), operation_ref,
'Waiting for [{0}] to finish'.format(operation_ref.Name()))
def CreateStoragePool(self, storagepool_ref, async_, config):
"""Create a Cloud NetApp Storage Pool."""
request = self.messages.NetappProjectsLocationsStoragePoolsCreateRequest(
parent=storagepool_ref.Parent().RelativeName(),
storagePoolId=storagepool_ref.Name(),
storagePool=config)
create_op = self.client.projects_locations_storagePools.Create(request)
if async_:
return create_op
operation_ref = resources.REGISTRY.ParseRelativeName(
create_op.name, collection=constants.OPERATIONS_COLLECTION)
return self.WaitForOperation(operation_ref)
def ParseStoragePoolConfig(self,
name=None,
service_level=None,
network=None,
active_directory=None,
kms_config=None,
enable_ldap=None,
capacity=None,
description=None,
allow_auto_tiering=None,
zone=None,
replica_zone=None,
custom_performance_enabled=None,
total_throughput=None,
total_iops=None,
hot_tier_size=None,
enable_hot_tier_auto_resize=None,
labels=None,
unified_pool=None,
qos_type=None,
storage_pool_type=None,
):
"""Parses the command line arguments for Create Storage Pool into a config."""
return self._adapter.ParseStoragePoolConfig(
name=name,
service_level=service_level,
network=network,
kms_config=kms_config,
active_directory=active_directory,
enable_ldap=enable_ldap,
capacity=capacity,
description=description,
allow_auto_tiering=allow_auto_tiering,
zone=zone,
replica_zone=replica_zone,
custom_performance_enabled=custom_performance_enabled,
total_throughput=total_throughput,
total_iops=total_iops,
hot_tier_size=hot_tier_size,
enable_hot_tier_auto_resize=enable_hot_tier_auto_resize,
labels=labels,
unified_pool=unified_pool,
qos_type=qos_type,
storage_pool_type=storage_pool_type,
)
def ListStoragePools(self, location_ref, limit=None):
"""Make API calls to List active Cloud NetApp Storage Pools.
Args:
location_ref: The parsed location of the listed NetApp Volumes.
limit: The number of Cloud NetApp Storage Pools to limit the results to.
This limit is passed to the server and the server does the limiting.
Returns:
Generator that yields the Cloud NetApp Volumes.
"""
request = self.messages.NetappProjectsLocationsStoragePoolsListRequest(
parent=location_ref)
# Check for unreachable locations.
response = self.client.projects_locations_storagePools.List(request)
for location in response.unreachable:
log.warning('Location {} may be unreachable.'.format(location))
return list_pager.YieldFromList(
self.client.projects_locations_storagePools,
request,
field=constants.STORAGE_POOL_RESOURCE,
limit=limit,
batch_size_attribute='pageSize')
def GetStoragePool(self, storagepool_ref):
"""Get Cloud NetApp Storage Pool information."""
request = self.messages.NetappProjectsLocationsStoragePoolsGetRequest(
name=storagepool_ref.RelativeName())
return self.client.projects_locations_storagePools.Get(request)
def DeleteStoragePool(self, storagepool_ref, async_):
"""Deletes an existing Cloud NetApp Storage Pool."""
request = self.messages.NetappProjectsLocationsStoragePoolsDeleteRequest(
name=storagepool_ref.RelativeName())
return self._DeleteStoragePool(async_, request)
def _DeleteStoragePool(self, async_, request):
delete_op = self.client.projects_locations_storagePools.Delete(request)
if async_:
return delete_op
operation_ref = resources.REGISTRY.ParseRelativeName(
delete_op.name, collection=constants.OPERATIONS_COLLECTION)
return self.WaitForOperation(operation_ref)
def ParseUpdatedStoragePoolConfig(self,
storagepool_config,
capacity=None,
active_directory=None,
description=None,
allow_auto_tiering=None,
zone=None,
replica_zone=None,
total_throughput=None,
total_iops=None,
hot_tier_size=None,
enable_hot_tier_auto_resize=None,
qos_type=None,
labels=None,
):
"""Parses updates into a storage pool config.
Args:
storagepool_config: The storage pool message to update.
capacity: capacity of a storage pool
active_directory: the Active Directory attached to a storage pool
description: str, a new description, if any.
allow_auto_tiering: bool indicate whether pool supports auto-tiering
zone: str, zone for storage pool
replica_zone: str, replica zone for storage pool
total_throughput: int, total throughput of the storage pool
total_iops: int, total IOPS of the storage pool
hot_tier_size: int, hot tier size of the storage pool
enable_hot_tier_auto_resize: bool, whether hot tier auto resize is enabled
for the storage pool
qos_type: qos (quality of service) type of the storage pool
labels: LabelsValue message, the new labels value, if any.
Returns:
The storage pool message.
"""
storage_pool = self._adapter.ParseUpdatedStoragePoolConfig(
storagepool_config,
capacity=capacity,
active_directory=active_directory,
description=description,
allow_auto_tiering=allow_auto_tiering,
zone=zone,
replica_zone=replica_zone,
total_throughput=total_throughput,
total_iops=total_iops,
hot_tier_size=hot_tier_size,
enable_hot_tier_auto_resize=enable_hot_tier_auto_resize,
qos_type=qos_type,
labels=labels,
)
return storage_pool
def UpdateStoragePool(
self, storagepool_ref, storagepool_config, update_mask, async_
):
"""Updates a Storage Pool.
Args:
storagepool_ref: the reference to the storage pool.
storagepool_config: Storage Pool message, the updated storage pool.
update_mask: str, a comma-separated list of updated fields.
async_: bool, if False, wait for the operation to complete.
Returns:
an Operation or Storage Pool message.
"""
update_op = self._adapter.UpdateStoragePool(storagepool_ref,
storagepool_config, update_mask)
if async_:
return update_op
operation_ref = resources.REGISTRY.ParseRelativeName(
update_op.name, collection=constants.OPERATIONS_COLLECTION)
return self.WaitForOperation(operation_ref)
def SwitchStoragePool(self, storagepool_ref, async_):
"""Switch the zone of a Regional Cloud NetApp Storage Pooln.
Args:
storagepool_ref: the reference to the storage pool.
async_: bool, if False, wait for the operation to complete.
Returns:
an Operation if async_ is set to true, or a switch message if the
SwtichStoragePool is successful.
"""
switch_op = self._adapter.SwitchStoragePool(storagepool_ref)
if async_:
return switch_op
operation_ref = resources.REGISTRY.ParseRelativeName(
switch_op.name, collection=constants.OPERATIONS_COLLECTION
)
return self.WaitForOperation(operation_ref)
def ValidateDirectoryService(self, storagepool_ref, directory_service_type,
async_):
"""Validates the directory service attached to the storage pool.
Args:
storagepool_ref: the reference to the storage pool.
directory_service_type: the type of directory service to validate.
async_: bool, if False, wait for the operation to complete.
Returns:
an Operation if async_ is set to true, or a validate message if the
validation is successful.
"""
validate_op = self._adapter.ValidateDirectoryService(
storagepool_ref, directory_service_type
)
if async_:
return validate_op
operation_ref = resources.REGISTRY.ParseRelativeName(
validate_op.name, collection=constants.OPERATIONS_COLLECTION
)
return self.WaitForOperation(operation_ref)
class StoragePoolsAdapter(object):
"""Adapter for the Cloud NetApp Files API for Storage Pools."""
def __init__(self):
self.release_track = base.ReleaseTrack.GA
self.client = netapp_api_util.GetClientInstance(
release_track=self.release_track
)
self.messages = netapp_api_util.GetMessagesModule(
release_track=self.release_track
)
def ParseStoragePoolConfig(
self,
name,
service_level,
network,
kms_config,
active_directory,
enable_ldap,
capacity,
description,
allow_auto_tiering,
zone,
replica_zone,
custom_performance_enabled,
total_throughput,
total_iops,
hot_tier_size,
enable_hot_tier_auto_resize,
qos_type,
labels,
unified_pool,
storage_pool_type,
):
"""Parses the command line arguments for Create Storage Pool into a config.
Args:
name: the name of the Storage Pool
service_level: the service level of the Storage Pool
network: the network of the Storage Pool
kms_config: the KMS Config of the Storage Pool
active_directory: the Active Directory of the Storage Pool
enable_ldap: Bool on whether to enable LDAP on Storage Pool
capacity: the storage capacity of the Storage Pool
description: the description of the Storage Pool
allow_auto_tiering: Bool on whether Storage Pool supports auto tiering
zone: zone of the Storage Pool
replica_zone: Replica zone for the Storage Pool
custom_performance_enabled: Bool on whether custom performance is enabled
total_throughput: Total throughput of the Storage Pool
total_iops: Total IOPS of the Storage Pool
hot_tier_size: Hot tier size of the Storage Pool
enable_hot_tier_auto_resize: Bool on whether hot tier auto resize is
enabled
qos_type: qos (quality of service) type of the storage pool
labels: the parsed labels value
unified_pool: Bool on whether the Storage Pool is a unified pool
storage_pool_type: Type of the Storage Pool
Returns:
The configuration that will be used as the request body for creating a
Cloud NetApp Storage Pool.
"""
storage_pool = self.messages.StoragePool()
storage_pool.name = name
storage_pool.serviceLevel = service_level
storage_pool.network = network.get('name')
if 'psa-range' in network:
storage_pool.psaRange = network.get('psa-range')
storage_pool.kmsConfig = kms_config
storage_pool.activeDirectory = active_directory
storage_pool.ldapEnabled = enable_ldap
storage_pool.capacityGib = capacity
storage_pool.description = description
if allow_auto_tiering is not None:
storage_pool.allowAutoTiering = allow_auto_tiering
if zone is not None:
storage_pool.zone = zone
if replica_zone is not None:
storage_pool.replicaZone = replica_zone
if custom_performance_enabled is not None:
storage_pool.customPerformanceEnabled = custom_performance_enabled
if total_throughput is not None:
storage_pool.totalThroughputMibps = total_throughput
if total_iops is not None:
storage_pool.totalIops = total_iops
if hot_tier_size is not None:
storage_pool.hotTierSizeGib = hot_tier_size
if enable_hot_tier_auto_resize is not None:
storage_pool.enableHotTierAutoResize = enable_hot_tier_auto_resize
if qos_type is not None:
storage_pool.qosType = qos_type
storage_pool.labels = labels
if unified_pool is not None:
storage_pool.unifiedPool = unified_pool
if storage_pool_type is not None:
storage_pool.type = storage_pool_type
return storage_pool
def ParseUpdatedStoragePoolConfig(
self,
storagepool_config,
description=None,
active_directory=None,
labels=None,
capacity=None,
allow_auto_tiering=None,
zone=None,
replica_zone=None,
total_throughput=None,
total_iops=None,
hot_tier_size=None,
enable_hot_tier_auto_resize=None,
qos_type=None,
):
"""Parse update information into an updated Storage Pool message."""
if capacity is not None:
storagepool_config.capacityGib = capacity
if active_directory is not None:
storagepool_config.activeDirectory = active_directory
if description is not None:
storagepool_config.description = description
if allow_auto_tiering is not None:
storagepool_config.allowAutoTiering = allow_auto_tiering
if zone is not None:
storagepool_config.zone = zone
if replica_zone is not None:
storagepool_config.replicaZone = replica_zone
if total_throughput is not None:
storagepool_config.totalThroughputMibps = total_throughput
if total_iops is not None:
storagepool_config.totalIops = total_iops
if hot_tier_size is not None:
storagepool_config.hotTierSizeGib = hot_tier_size
if enable_hot_tier_auto_resize is not None:
storagepool_config.enableHotTierAutoResize = enable_hot_tier_auto_resize
if qos_type is not None:
storagepool_config.qosType = qos_type
if labels is not None:
storagepool_config.labels = labels
return storagepool_config
def UpdateStoragePool(self, storagepool_ref, storagepool_config, update_mask):
"""Send a Patch request for the Cloud NetApp Storage Pool."""
update_request = (
self.messages.NetappProjectsLocationsStoragePoolsPatchRequest(
storagePool=storagepool_config,
name=storagepool_ref.RelativeName(),
updateMask=update_mask,
)
)
update_op = self.client.projects_locations_storagePools.Patch(
update_request
)
return update_op
def SwitchStoragePool(self, storagepool_ref):
"""Send a switch zone request for the Cloud NetApp storage pool."""
switch_request = (
self.messages.NetappProjectsLocationsStoragePoolsSwitchRequest(
name=storagepool_ref.RelativeName(),
)
)
return self.client.projects_locations_storagePools.Switch(switch_request)
def ValidateDirectoryService(self, storagepool_ref, directory_service_type):
"""Send a validate directory service request for the Cloud NetApp storage pool."""
request = self.messages.ValidateDirectoryServiceRequest(
directoryServiceType=directory_service_type,
)
validate_request = self.messages.NetappProjectsLocationsStoragePoolsValidateDirectoryServiceRequest(
name=storagepool_ref.RelativeName(),
validateDirectoryServiceRequest=request,
)
return self.client.projects_locations_storagePools.ValidateDirectoryService(
validate_request
)
class BetaStoragePoolsAdapter(StoragePoolsAdapter):
"""Adapter for the Beta Cloud NetApp Files API for Storage Pools."""
def __init__(self):
super(BetaStoragePoolsAdapter, self).__init__()
self.release_track = base.ReleaseTrack.BETA
self.client = netapp_api_util.GetClientInstance(
release_track=self.release_track
)
self.messages = netapp_api_util.GetMessagesModule(
release_track=self.release_track
)
class AlphaStoragePoolsAdapter(BetaStoragePoolsAdapter):
"""Adapter for the Alpha Cloud NetApp Files API for Storage Pools."""
def __init__(self):
super(AlphaStoragePoolsAdapter, self).__init__()
self.release_track = base.ReleaseTrack.ALPHA
self.client = netapp_api_util.GetClientInstance(
release_track=self.release_track
)
self.messages = netapp_api_util.GetMessagesModule(
release_track=self.release_track
)

View File

@@ -0,0 +1,59 @@
# -*- 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.
"""Useful commands for interacting with the Cloud NetApp Files API."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.util import apis
from googlecloudsdk.calliope import base
from googlecloudsdk.core import exceptions
# TODO(b/239613419), when ready, introduce GA release tracks
VERSION_MAP = {
base.ReleaseTrack.ALPHA: "v1alpha1",
base.ReleaseTrack.BETA: "v1beta1",
base.ReleaseTrack.GA: "v1",
}
# The messages module can also be accessed from client.MESSAGES_MODULE
def GetMessagesModule(release_track):
"""Import and return the appropriate NetApp messages module."""
api_version = VERSION_MAP.get(release_track)
return apis.GetMessagesModule(api_name="netapp", api_version=api_version)
def GetClientInstance(release_track):
api_version = VERSION_MAP.get(release_track)
return apis.GetClientInstance(api_name="netapp", api_version=api_version)
class Error(exceptions.Error):
"""Base class for exceptions in this module."""
class InvalidArgumentError(Error):
"""Raised when command line argument constraints are violated."""
class InvalidCapacityError(Error):
"""Raised when an invalid capacity value is provided."""
class InvalidNameError(Error):
"""Raised when an invalid share name, network VPC name, Storage Pool, Active Directory, Encryption Key name value is provided."""

View File

@@ -0,0 +1,21 @@
# -*- 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.
"""Cloud NetApp Files Volumes API client library helper files."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals

View File

@@ -0,0 +1,922 @@
# -*- 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.
"""Commands for interacting with the Cloud NetApp Files Volume API resource."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from apitools.base.py import list_pager
from googlecloudsdk.api_lib.netapp import constants
from googlecloudsdk.api_lib.netapp import util
from googlecloudsdk.api_lib.util import waiter
from googlecloudsdk.calliope import base
from googlecloudsdk.core import log
from googlecloudsdk.core import resources
from googlecloudsdk.generated_clients.apis.netapp.v1beta1 import netapp_v1beta1_messages
EstablishVolumePeeringRequest = (
netapp_v1beta1_messages.EstablishVolumePeeringRequest
)
Volume = netapp_v1beta1_messages.Volume
class VolumesClient(object):
"""Wrapper for working with volumes in the Cloud NetApp Files API Client."""
def __init__(self, release_track=base.ReleaseTrack.ALPHA):
self.release_track = release_track
if self.release_track == base.ReleaseTrack.ALPHA:
self._adapter = AlphaVolumesAdapter()
elif self.release_track == base.ReleaseTrack.BETA:
self._adapter = BetaVolumesAdapter()
elif self.release_track == base.ReleaseTrack.GA:
self._adapter = VolumesAdapter()
else:
raise ValueError(
'[{}] is not a valid API version.'.format(
util.VERSION_MAP[release_track]
)
)
@property
def client(self):
return self._adapter.client
@property
def messages(self):
return self._adapter.messages
def WaitForOperation(self, operation_ref):
"""Waits on the long-running operation until the done field is True.
Args:
operation_ref: the operation reference.
Raises:
waiter.OperationError: if the operation contains an error.
Returns:
the 'response' field of the Operation.
"""
return waiter.WaitFor(
waiter.CloudOperationPollerNoResources(
self.client.projects_locations_operations
),
operation_ref,
'Waiting for [{0}] to finish'.format(operation_ref.Name()),
)
def ListVolumes(self, location_ref, limit=None):
"""Make API calls to List active Cloud NetApp Volumes.
Args:
location_ref: The parsed location of the listed NetApp Volumes.
limit: The number of Cloud NetApp Volumes to limit the results to. This
limit is passed to the server and the server does the limiting.
Returns:
Generator that yields the Cloud NetApp Volumes.
"""
request = self.messages.NetappProjectsLocationsVolumesListRequest(
parent=location_ref
)
# Check for unreachable locations.
response = self.client.projects_locations_volumes.List(request)
for location in response.unreachable:
log.warning('Location {} may be unreachable.'.format(location))
return list_pager.YieldFromList(
self.client.projects_locations_volumes,
request,
field=constants.VOLUME_RESOURCE,
limit=limit,
batch_size_attribute='pageSize',
)
def CreateVolume(self, volume_ref, async_, config):
"""Create a Cloud NetApp Volume."""
request = self.messages.NetappProjectsLocationsVolumesCreateRequest(
parent=volume_ref.Parent().RelativeName(),
volumeId=volume_ref.Name(),
volume=config,
)
create_op = self.client.projects_locations_volumes.Create(request)
if async_:
return create_op
operation_ref = resources.REGISTRY.ParseRelativeName(
create_op.name, collection=constants.OPERATIONS_COLLECTION
)
return self.WaitForOperation(operation_ref)
def ParseVolumeConfig(
self,
name=None,
capacity=None,
description=None,
storage_pool=None,
protocols=None,
share_name=None,
export_policy=None,
unix_permissions=None,
smb_settings=None,
snapshot_policy=None,
snap_reserve=None,
snapshot_directory=None,
security_style=None,
enable_kerberos=None,
snapshot=None,
backup=None,
restricted_actions=None,
backup_config=None,
large_capacity=None,
multiple_endpoints=None,
tiering_policy=None,
hybrid_replication_parameters=None,
throughput_mibps=None,
cache_parameters=None,
cache_pre_populate=None,
labels=None,
block_devices=None,
):
"""Parses the command line arguments for Create Volume into a config."""
return self._adapter.ParseVolumeConfig(
name=name,
capacity=capacity,
description=description,
storage_pool=storage_pool,
protocols=protocols,
share_name=share_name,
export_policy=export_policy,
unix_permissions=unix_permissions,
smb_settings=smb_settings,
snapshot_policy=snapshot_policy,
snap_reserve=snap_reserve,
snapshot_directory=snapshot_directory,
security_style=security_style,
enable_kerberos=enable_kerberos,
snapshot=snapshot,
backup=backup,
restricted_actions=restricted_actions,
backup_config=backup_config,
large_capacity=large_capacity,
multiple_endpoints=multiple_endpoints,
tiering_policy=tiering_policy,
hybrid_replication_parameters=hybrid_replication_parameters,
throughput_mibps=throughput_mibps,
cache_parameters=cache_parameters,
cache_pre_populate=cache_pre_populate,
labels=labels,
block_devices=block_devices,
)
def GetVolume(self, volume_ref):
"""Get Cloud NetApp Volume information."""
request = self.messages.NetappProjectsLocationsVolumesGetRequest(
name=volume_ref.RelativeName()
)
return self.client.projects_locations_volumes.Get(request)
def DeleteVolume(self, volume_ref, async_, force):
"""Deletes an existing Cloud NetApp Volume."""
request = self.messages.NetappProjectsLocationsVolumesDeleteRequest(
name=volume_ref.RelativeName(), force=force
)
return self._DeleteVolume(async_, request)
def _DeleteVolume(self, async_, request):
delete_op = self.client.projects_locations_volumes.Delete(request)
if async_:
return delete_op
operation_ref = resources.REGISTRY.ParseRelativeName(
delete_op.name, collection=constants.OPERATIONS_COLLECTION
)
return self.WaitForOperation(operation_ref)
def RevertVolume(self, volume_ref, snapshot_id, async_):
"""Reverts an existing Cloud NetApp Volume."""
request = self.messages.NetappProjectsLocationsVolumesRevertRequest(
name=volume_ref.RelativeName(),
revertVolumeRequest=self.messages.RevertVolumeRequest(
snapshotId=snapshot_id
),
)
revert_op = self.client.projects_locations_volumes.Revert(request)
if async_:
return revert_op
operation_ref = resources.REGISTRY.ParseRelativeName(
revert_op.name, collection=constants.OPERATIONS_COLLECTION
)
return self.WaitForOperation(operation_ref)
def RestoreVolume(
self, volume_ref, backup, file_list, restore_destination_path, async_
):
"""Restores specific files from a backup to a volume."""
request = self.messages.NetappProjectsLocationsVolumesRestoreRequest(
name=volume_ref.RelativeName(),
restoreBackupFilesRequest=self.messages.RestoreBackupFilesRequest(
backup=backup,
fileList=file_list,
restoreDestinationPath=restore_destination_path,
),
)
restore_op = self.client.projects_locations_volumes.Restore(request)
if async_:
return restore_op
operation_ref = resources.REGISTRY.ParseRelativeName(
restore_op.name, collection=constants.OPERATIONS_COLLECTION
)
return self.WaitForOperation(operation_ref)
def ParseUpdatedVolumeConfig(
self,
volume_config,
description=None,
labels=None,
storage_pool=None,
protocols=None,
share_name=None,
export_policy=None,
capacity=None,
unix_permissions=None,
smb_settings=None,
snapshot_policy=None,
snap_reserve=None,
snapshot_directory=None,
security_style=None,
enable_kerberos=None,
snapshot=None,
backup=None,
restricted_actions=None,
backup_config=None,
large_capacity=None,
multiple_endpoints=None,
tiering_policy=None,
cache_parameters=None,
cache_pre_populate=None,
throughput_mibps=None,
block_devices=None,
):
"""Parses updates into a volume config."""
return self._adapter.ParseUpdatedVolumeConfig(
volume_config,
description=description,
labels=labels,
storage_pool=storage_pool,
protocols=protocols,
share_name=share_name,
export_policy=export_policy,
capacity=capacity,
unix_permissions=unix_permissions,
smb_settings=smb_settings,
snapshot_policy=snapshot_policy,
snap_reserve=snap_reserve,
snapshot_directory=snapshot_directory,
security_style=security_style,
enable_kerberos=enable_kerberos,
snapshot=snapshot,
backup=backup,
restricted_actions=restricted_actions,
backup_config=backup_config,
large_capacity=large_capacity,
multiple_endpoints=multiple_endpoints,
tiering_policy=tiering_policy,
cache_parameters=cache_parameters,
cache_pre_populate=cache_pre_populate,
throughput_mibps=throughput_mibps,
block_devices=block_devices,
)
def UpdateVolume(self, volume_ref, volume_config, update_mask, async_):
"""Updates a Cloud NetApp Volume.
Args:
volume_ref: the reference to the Volume.
volume_config: Volume config, the updated volume.
update_mask: str, a comma-separated list of updated fields.
async_: bool, if False, wait for the operation to complete.
Returns:
an Operation or Volume message.
"""
update_op = self._adapter.UpdateVolume(
volume_ref, volume_config, update_mask
)
if async_:
return update_op
operation_ref = resources.REGISTRY.ParseRelativeName(
update_op.name, collection=constants.OPERATIONS_COLLECTION
)
return self.WaitForOperation(operation_ref)
def ParseEstablishVolumePeeringRequestConfig(
self,
peer_cluster_name: str,
peer_svm_name: str,
peer_volume_name: str,
peer_ip_addresses=None,
) -> EstablishVolumePeeringRequest:
"""Parses the command line arguments for EstablishPeering into a config.
Args:
peer_cluster_name: The name of the peer cluster.
peer_svm_name: The name of the peer SVM.
peer_volume_name: The name of the peer volume.
peer_ip_addresses: The list of peer IP addresses.
Returns:
An EstablishVolumePeeringRequest message.
"""
return self.messages.EstablishVolumePeeringRequest(
peerClusterName=peer_cluster_name,
peerSvmName=peer_svm_name,
peerVolumeName=peer_volume_name,
peerIpAddresses=peer_ip_addresses if peer_ip_addresses else [],
)
def EstablishPeering(
self,
volume_ref: Volume,
establish_volume_peering_request_config: EstablishVolumePeeringRequest,
async_: bool,
):
"""Establish peering between GCNV volume and an onprem ONTAP volume.
Args:
volume_ref: The reference to the volume.
establish_volume_peering_request_config: The config for the peering
request.
async_: If true, the call will return immediately, otherwise wait for
operation to complete.
Returns:
An EstablishVolumePeering operation.
"""
request = self.messages.NetappProjectsLocationsVolumesEstablishPeeringRequest(
name=volume_ref.RelativeName(),
establishVolumePeeringRequest=establish_volume_peering_request_config,
)
establish_peering_op = (
self.client.projects_locations_volumes.EstablishPeering(request)
)
if async_:
return establish_peering_op
operation_ref = resources.REGISTRY.ParseRelativeName(
establish_peering_op.name, collection=constants.OPERATIONS_COLLECTION
)
return self.WaitForOperation(operation_ref)
class VolumesAdapter(object):
"""Adapter for the Cloud NetApp Files API Volume resource."""
def __init__(self):
self.release_track = base.ReleaseTrack.GA
self.client = util.GetClientInstance(release_track=self.release_track)
self.messages = util.GetMessagesModule(release_track=self.release_track)
def ParseExportPolicy(self, volume, export_policy):
"""Parses Export Policy for Volume into a config.
Args:
volume: The Cloud NetApp Volume message object
export_policy: the Export Policy message object.
Returns:
Volume message populated with Export Policy values.
"""
if not export_policy:
return
export_policy_config = self.messages.ExportPolicy()
for policy in export_policy:
simple_export_policy_rule = self.messages.SimpleExportPolicyRule()
for key, val in policy.items():
# Support for structural pattern matching with `match` was introduced in
# Python 3.10, but gcloud still supports older Python versions (e.g.
# 3.9). Using an `if` statement instead for the time being.
if key == 'allowed-clients':
simple_export_policy_rule.allowedClients = val
elif key == 'access-type':
simple_export_policy_rule.accessType = (
self.messages.SimpleExportPolicyRule.AccessTypeValueValuesEnum.lookup_by_name(
val
)
)
elif key == 'has-root-access':
simple_export_policy_rule.hasRootAccess = val
elif key == 'kerberos-5-read-only':
simple_export_policy_rule.kerberos5ReadOnly = val
elif key == 'kerberos-5-read-write':
simple_export_policy_rule.kerberos5ReadWrite = val
elif key == 'kerberos-5i-read-only':
simple_export_policy_rule.kerberos5iReadOnly = val
elif key == 'kerberos-5i-read-write':
simple_export_policy_rule.kerberos5iReadWrite = val
elif key == 'kerberos-5p-read-only':
simple_export_policy_rule.kerberos5pReadOnly = val
elif key == 'kerberos-5p-read-write':
simple_export_policy_rule.kerberos5pReadWrite = val
elif key == 'nfsv3':
simple_export_policy_rule.nfsv3 = val
elif key == 'nfsv4':
simple_export_policy_rule.nfsv4 = val
elif key == 'squash-mode':
simple_export_policy_rule.squashMode = val
elif key == 'anon-uid':
simple_export_policy_rule.anonUid = val
export_policy_config.rules.append(simple_export_policy_rule)
volume.exportPolicy = export_policy_config
def ParseBlockDevices(self, volume, block_devices):
"""Parses Block Devices for Volume into a config."""
volume.blockDevices = [] # clear volume block devices
if block_devices is None:
return
for block_device_args in block_devices:
block_device_message = self.messages.BlockDevice()
if 'name' in block_device_args:
block_device_message.name = block_device_args['name']
for host_group in block_device_args.get('host-groups', []):
block_device_message.hostGroups.append(host_group)
if 'os-type' in block_device_args:
block_device_message.osType = block_device_args['os-type']
if 'size-gib' in block_device_args:
block_device_message.sizeGib = block_device_args['size-gib']
volume.blockDevices.append(block_device_message)
def ParseProtocols(self, volume, protocols):
"""Parses Protocols from a list of Protocol Enums into the given volume.
Args:
volume: The Cloud NetApp Volume message object
protocols: A list of protocol enums
Returns:
Volume message populated with protocol values.
"""
protocols_config = []
for protocol in protocols:
protocols_config.append(protocol)
volume.protocols = protocols_config
def ParseSnapshotPolicy(self, volume, snapshot_policy):
"""Parses Snapshot Policy from a list of snapshot schedules into a given Volume.
Args:
volume: The Cloud NetApp Volume message object
snapshot_policy: A list of snapshot policies (schedules) to parse
Returns:
Volume messages populated with snapshotPolicy field
"""
if not snapshot_policy:
return
volume.snapshotPolicy = self.messages.SnapshotPolicy()
volume.snapshotPolicy.enabled = True
for name, snapshot_schedule in snapshot_policy.items():
if name == 'hourly_snapshot':
schedule = self.messages.HourlySchedule()
schedule.snapshotsToKeep = snapshot_schedule.get('snapshots-to-keep')
schedule.minute = snapshot_schedule.get('minute', 0)
volume.snapshotPolicy.hourlySchedule = schedule
elif name == 'daily_snapshot':
schedule = self.messages.DailySchedule()
schedule.snapshotsToKeep = snapshot_schedule.get('snapshots-to-keep')
schedule.minute = snapshot_schedule.get('minute', 0)
schedule.hour = snapshot_schedule.get('hour', 0)
volume.snapshotPolicy.dailySchedule = schedule
elif name == 'weekly_snapshot':
schedule = self.messages.WeeklySchedule()
schedule.snapshotsToKeep = snapshot_schedule.get('snapshots-to-keep')
schedule.minute = snapshot_schedule.get('minute', 0)
schedule.hour = snapshot_schedule.get('hour', 0)
schedule.day = snapshot_schedule.get('day', 'Sunday')
volume.snapshotPolicy.weeklySchedule = schedule
elif name == 'monthly-snapshot':
schedule = self.messages.MonthlySchedule()
schedule.snapshotsToKeep = snapshot_schedule.get('snapshots-to-keep')
schedule.minute = snapshot_schedule.get('minute', 0)
schedule.hour = snapshot_schedule.get('hour', 0)
schedule.day = snapshot_schedule.get('day', 1)
volume.snapshotPolicy.monthlySchedule = schedule
def UpdateVolume(self, volume_ref, volume_config, update_mask):
"""Send a Patch request for the Cloud NetApp Volume."""
update_request = self.messages.NetappProjectsLocationsVolumesPatchRequest(
volume=volume_config,
name=volume_ref.RelativeName(),
updateMask=update_mask,
)
update_op = self.client.projects_locations_volumes.Patch(update_request)
return update_op
def ParseVolumeConfig(
self,
name=None,
capacity=None,
description=None,
storage_pool=None,
protocols=None,
share_name=None,
export_policy=None,
unix_permissions=None,
smb_settings=None,
snapshot_policy=None,
snap_reserve=None,
snapshot_directory=None,
security_style=None,
enable_kerberos=None,
snapshot=None,
backup=None,
restricted_actions=None,
backup_config=None,
large_capacity=None,
multiple_endpoints=None,
tiering_policy=None,
hybrid_replication_parameters=None,
throughput_mibps=None,
cache_parameters=None,
cache_pre_populate=None,
labels=None,
block_devices=None,
):
"""Parses the command line arguments for Create Volume into a config.
Args:
name: the name of the Volume
capacity: the storage capacity of the Volume.
description: the description of the Volume.
storage_pool: the Storage Pool the Volume is attached to.
protocols: the type of fileshare protocol of the Volume.
share_name: the share name or mount point of the Volume.
export_policy: the export policy of the Volume if NFS.
unix_permissions: the Unix permissions for the Volume.
smb_settings: the SMB settings for the Volume.
snapshot_policy: the Snapshot Policy for the Volume
snap_reserve: the snap reserve (double) for the Volume
snapshot_directory: Bool on whether to use snapshot directory for Volume
security_style: the security style of the Volume
enable_kerberos: Bool on whether to use kerberos for Volume
snapshot: the snapshot name to create Volume from
backup: the backup to create the Volume from.
restricted_actions: the actions to be restricted on a Volume
backup_config: the Backup Config attached to the Volume
large_capacity: Bool on whether to use large capacity for Volume
multiple_endpoints: Bool on whether to use multiple endpoints for Volume
tiering_policy: the tiering policy for the volume.
hybrid_replication_parameters: the hybrid replication parameters for the
volume.
throughput_mibps: throughput of the Volume (in MiB/s).
cache_parameters: the cache parameters for the volume.
cache_pre_populate: the cache pre-populate parameters for the volume.
labels: the parsed labels value.
block_devices: the block devices for the volume.
Returns:
the configuration that will be used as the request body for creating a
Cloud NetApp Files Volume.
"""
volume = self.messages.Volume()
volume.name = name
volume.capacityGib = capacity
volume.description = description
volume.labels = labels
volume.storagePool = storage_pool
volume.shareName = share_name
self.ParseExportPolicy(volume, export_policy)
self.ParseProtocols(volume, protocols)
volume.unixPermissions = unix_permissions
volume.smbSettings = smb_settings
self.ParseSnapshotPolicy(volume, snapshot_policy)
volume.snapReserve = snap_reserve
volume.snapshotDirectory = snapshot_directory
volume.securityStyle = security_style
volume.kerberosEnabled = enable_kerberos
restore_parameters = self.messages.RestoreParameters()
if snapshot is not None:
restore_parameters.sourceSnapshot = snapshot
if backup is not None:
restore_parameters.sourceBackup = backup
if backup is None and snapshot is None:
restore_parameters = None
volume.restoreParameters = restore_parameters
volume.restrictedActions = restricted_actions
volume.throughputMibps = throughput_mibps
if backup_config is not None:
self.ParseBackupConfig(volume, backup_config)
if large_capacity is not None:
volume.largeCapacity = large_capacity
if multiple_endpoints is not None:
volume.multipleEndpoints = multiple_endpoints
if tiering_policy is not None:
self.ParseTieringPolicy(volume, tiering_policy)
if hybrid_replication_parameters is not None:
self.ParseHybridReplicationParameters(
volume, hybrid_replication_parameters, self.release_track
)
if block_devices is not None:
self.ParseBlockDevices(volume, block_devices)
if cache_parameters is not None:
self.ParseCacheParameters(volume, cache_parameters)
if cache_pre_populate is not None:
self.ParseCachePrePopulate(volume, cache_pre_populate)
return volume
def ParseUpdatedVolumeConfig(
self,
volume_config,
description=None,
labels=None,
storage_pool=None,
protocols=None,
share_name=None,
export_policy=None,
capacity=None,
unix_permissions=None,
smb_settings=None,
snapshot_policy=None,
snap_reserve=None,
snapshot_directory=None,
security_style=None,
enable_kerberos=None,
active_directory=None,
snapshot=None,
backup=None,
restricted_actions=None,
backup_config=None,
large_capacity=None,
multiple_endpoints=None,
tiering_policy=None,
cache_parameters=None,
cache_pre_populate=None,
throughput_mibps=None,
block_devices=None,
):
"""Parse update information into an updated Volume message."""
if description is not None:
volume_config.description = description
if labels is not None:
volume_config.labels = labels
if capacity is not None:
volume_config.capacityGib = capacity
if storage_pool is not None:
volume_config.storagePool = storage_pool
if protocols is not None:
self.ParseProtocols(volume_config, protocols)
if share_name is not None:
volume_config.shareName = share_name
if export_policy is not None:
self.ParseExportPolicy(volume_config, export_policy)
if unix_permissions is not None:
volume_config.unixPermissions = unix_permissions
if smb_settings is not None:
volume_config.smbSettings = smb_settings
if snapshot_policy is not None:
self.ParseSnapshotPolicy(volume_config, snapshot_policy)
if snap_reserve is not None:
volume_config.snapReserve = snap_reserve
if snapshot_directory is not None:
volume_config.snapshotDirectory = snapshot_directory
if security_style is not None:
volume_config.securityStyle = security_style
if enable_kerberos is not None:
volume_config.kerberosEnabled = enable_kerberos
if active_directory is not None:
volume_config.activeDirectory = active_directory
if snapshot is not None or backup is not None:
self.ParseRestoreParameters(volume_config, snapshot, backup)
if restricted_actions is not None:
volume_config.restrictedActions = restricted_actions
if backup_config is not None:
self.ParseBackupConfig(volume_config, backup_config)
if large_capacity is not None:
volume_config.largeCapacity = large_capacity
if multiple_endpoints is not None:
volume_config.multipleEndpoints = multiple_endpoints
if tiering_policy is not None:
self.ParseTieringPolicy(volume_config, tiering_policy)
if cache_parameters is not None:
self.ParseCacheParameters(volume_config, cache_parameters)
if cache_pre_populate is not None:
self.ParseCachePrePopulate(volume_config, cache_pre_populate)
if throughput_mibps is not None:
volume_config.throughputMibps = throughput_mibps
if block_devices is not None:
self.ParseBlockDevices(volume_config, block_devices)
return volume_config
def ParseBackupConfig(self, volume, backup_config):
"""Parses Backup Config for Volume into a config.
Args:
volume: The Cloud NetApp Volume message object.
backup_config: the Backup Config message object.
Returns:
Volume message populated with Backup Config values.
"""
backup_config_message = self.messages.BackupConfig()
# Iterate through backup_config.
for backup_policy in backup_config.get('backup-policies', []):
backup_config_message.backupPolicies.append(backup_policy)
backup_config_message.backupVault = backup_config.get('backup-vault', '')
backup_config_message.scheduledBackupEnabled = backup_config.get(
'enable-scheduled-backups', None
)
volume.backupConfig = backup_config_message
def ParseRestoreParameters(self, volume, snapshot, backup):
"""Parses Restore Parameters for Volume into a config."""
restore_parameters = self.messages.RestoreParameters()
if snapshot:
restore_parameters.sourceSnapshot = snapshot
if backup:
restore_parameters.sourceBackup = backup
volume.restoreParameters = restore_parameters
def ParseTieringPolicy(self, volume, tiering_policy):
"""Parses Tiering Policy for Volume into a config.
Args:
volume: The Cloud NetApp Volume message object.
tiering_policy: the tiering policy message object.
Returns:
Volume message populated with Tiering Policy values.
"""
tiering_policy_message = self.messages.TieringPolicy()
tiering_policy_message.tierAction = tiering_policy.get('tier-action')
tiering_policy_message.coolingThresholdDays = tiering_policy.get(
'cooling-threshold-days'
)
if (
self.release_track == base.ReleaseTrack.BETA
or self.release_track == base.ReleaseTrack.ALPHA
):
tiering_policy_message.hotTierBypassModeEnabled = tiering_policy.get(
'enable-hot-tier-bypass-mode'
)
volume.tieringPolicy = tiering_policy_message
def ParseHybridReplicationParameters(
self,
volume,
hybrid_replication_parameters,
release_track=base.ReleaseTrack.GA,
):
"""Parses Hybrid Replication Parameters for Volume into a config.
Args:
volume: The Cloud NetApp Volume message object.
hybrid_replication_parameters: The hybrid replication params message
object.
release_track: The release track of the command.
Returns:
Volume message populated with Hybrid Replication Parameters
"""
del release_track
hybrid_replication_parameters_message = (
self.messages.HybridReplicationParameters()
)
hybrid_replication_parameters_message.replication = (
hybrid_replication_parameters.get('replication')
)
hybrid_replication_parameters_message.peerVolumeName = (
hybrid_replication_parameters.get('peer-volume-name')
)
hybrid_replication_parameters_message.peerClusterName = (
hybrid_replication_parameters.get('peer-cluster-name')
)
hybrid_replication_parameters_message.peerSvmName = (
hybrid_replication_parameters.get('peer-svm-name')
)
for ip_address in hybrid_replication_parameters.get(
'peer-ip-addresses', []
):
hybrid_replication_parameters_message.peerIpAddresses.append(ip_address)
hybrid_replication_parameters_message.clusterLocation = (
hybrid_replication_parameters.get('cluster-location')
)
hybrid_replication_parameters_message.description = (
hybrid_replication_parameters.get('description')
)
hybrid_replication_parameters_message.labels = self.messages.HybridReplicationParameters.LabelsValue(
additionalProperties=[
self.messages.HybridReplicationParameters.LabelsValue.AdditionalProperty(
key=key_value_pair.split(':')[0],
value=key_value_pair.split(':')[1],
)
for key_value_pair in hybrid_replication_parameters.get(
'labels', []
)
]
)
hybrid_replication_parameters_message.replicationSchedule = (
hybrid_replication_parameters.get('replication-schedule')
)
hybrid_replication_parameters_message.hybridReplicationType = (
hybrid_replication_parameters.get('hybrid-replication-type')
)
hybrid_replication_parameters_message.largeVolumeConstituentCount = (
hybrid_replication_parameters.get('large-volume-constituent-count')
)
volume.hybridReplicationParameters = hybrid_replication_parameters_message
def ParseCacheParameters(self, volume, cache_parameters):
"""Parses Cache Parameters for Volume into a config.
Args:
volume: The Cloud NetApp Volume message object.
cache_parameters: The cache params message object.
Returns:
Volume message populated with Cache Parameters
"""
cache_parameters_message = self.messages.CacheParameters()
cache_parameters_message.peerVolumeName = cache_parameters.get(
'peer-volume-name'
)
cache_parameters_message.peerClusterName = cache_parameters.get(
'peer-cluster-name'
)
cache_parameters_message.peerSvmName = cache_parameters.get('peer-svm-name')
for ip_address in cache_parameters.get('peer-ip-addresses', []):
cache_parameters_message.peerIpAddresses.append(ip_address)
cache_parameters_message.enableGlobalFileLock = cache_parameters.get(
'enable-global-file-lock'
)
cache_config_message = self.messages.CacheConfig()
for config in cache_parameters.get('cache-config', []):
if 'cifs-change-notify-enabled' in config:
cache_config_message.cifsChangeNotifyEnabled = (
config['cifs-change-notify-enabled'].lower() == 'true'
)
if 'write-back-enabled' in config:
cache_config_message.writebackEnabled = (
config['write-back-enabled'].lower() == 'true'
)
cache_parameters_message.cacheConfig = cache_config_message
volume.cacheParameters = cache_parameters_message
def ParseCachePrePopulate(self, volume, cache_pre_populate):
"""Parses Cache Pre-populate for Volume into a config.
Args:
volume: The Cloud NetApp Volume message object.
cache_pre_populate: The cache pre-populate params message object.
Returns:
Volume message populated with Cache Pre-populate Parameters
"""
cache_pre_populate_message = self.messages.CachePrePopulate()
for path in cache_pre_populate.get('path-list', []):
cache_pre_populate_message.pathList.append(path)
for path in cache_pre_populate.get('exclude-path-list', []):
cache_pre_populate_message.excludePathList.append(path)
cache_pre_populate_message.recursion = cache_pre_populate.get(
'recursion'
)
if volume.cacheParameters is None:
volume.cacheParameters = self.messages.CacheParameters()
if volume.cacheParameters.cacheConfig is None:
volume.cacheParameters.cacheConfig = self.messages.CacheConfig()
volume.cacheParameters.cacheConfig.cachePrePopulate = (
cache_pre_populate_message
)
class BetaVolumesAdapter(VolumesAdapter):
"""Adapter for the Beta Cloud NetApp Files API Volume resource."""
def __init__(self):
super(BetaVolumesAdapter, self).__init__()
self.release_track = base.ReleaseTrack.BETA
self.client = util.GetClientInstance(release_track=self.release_track)
self.messages = util.GetMessagesModule(release_track=self.release_track)
class AlphaVolumesAdapter(BetaVolumesAdapter):
"""Adapter for the Alpha Cloud NetApp Files API Volume resource."""
def __init__(self):
super(AlphaVolumesAdapter, self).__init__()
self.release_track = base.ReleaseTrack.ALPHA
self.client = util.GetClientInstance(release_track=self.release_track)
self.messages = util.GetMessagesModule(release_track=self.release_track)

View File

@@ -0,0 +1,16 @@
# -*- coding: utf-8 -*- #
# Copyright 2025 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.
"""Cloud NetApp Files Volumes QuotaRules API client library helper files."""

View File

@@ -0,0 +1,232 @@
# -*- coding: utf-8 -*- #
# Copyright 2025 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.
"""Commands for interacting with the Cloud NetApp Files Quota Rules API resource."""
from apitools.base.py import list_pager
from googlecloudsdk.api_lib.netapp import constants
from googlecloudsdk.api_lib.netapp import util as netapp_api_util
from googlecloudsdk.api_lib.util import waiter
from googlecloudsdk.calliope import base
from googlecloudsdk.core import log
from googlecloudsdk.core import resources
class QuotaRulesClient(object):
"""Wrapper for working with Quota Rules in the Cloud NetApp Files API Client.
"""
def __init__(self, release_track=base.ReleaseTrack.BETA):
self.release_track = release_track
if self.release_track == base.ReleaseTrack.BETA:
self._adapter = BetaQuotaRulesAdapter()
elif self.release_track == base.ReleaseTrack.GA:
self._adapter = QuotaRulesAdapter()
else:
raise ValueError('[{}] is not a valid API version.'.format(
netapp_api_util.VERSION_MAP[release_track]))
@property
def client(self):
return self._adapter.client
@property
def messages(self):
return self._adapter.messages
def WaitForOperation(self, operation_ref):
"""Waits on the long-running operation until the done field is True.
Args:
operation_ref: the operation reference.
Raises:
waiter.OperationError: if the operation contains an error.
Returns:
the 'response' field of the Operation.
"""
return waiter.WaitFor(
waiter.CloudOperationPollerNoResources(
self.client.projects_locations_operations), operation_ref,
'Waiting for [{0}] to finish'.format(operation_ref.Name()))
def CreateQuotaRule(self, quota_rule_ref, volume_ref, async_, config):
"""Create a Cloud NetApp Volume Quota Rule."""
request = (
self.messages.NetappProjectsLocationsVolumesQuotaRulesCreateRequest(
parent=volume_ref,
quotaRuleId=quota_rule_ref.Name(),
quotaRule=config,
)
)
create_op = self.client.projects_locations_volumes_quotaRules.Create(
request
)
if async_:
return create_op
operation_ref = resources.REGISTRY.ParseRelativeName(
create_op.name, collection=constants.OPERATIONS_COLLECTION
)
return self.WaitForOperation(operation_ref)
def ParseQuotaRuleConfig(
self,
name=None,
quota_rule_type=None,
target=None,
disk_limit_mib=None,
description=None,
labels=None,
):
"""Parses the command line arguments for Create Quota Rule into a config."""
quota_rule = self.messages.QuotaRule()
quota_rule.name = name
quota_rule.type = quota_rule_type
quota_rule.target = target
quota_rule.diskLimitMib = disk_limit_mib
quota_rule.description = description
quota_rule.labels = labels
return quota_rule
def ListQuotaRules(self, volume_ref, limit=None):
"""List Cloud NetApp Volume Quota Rules.
Args:
volume_ref: The parent Volume to list Cloud Netapp Volume QuotaRules.
limit: The number of Cloud Netapp Volume QuotaRules to limit the results
to. This limit is passed to the server and the server does the limiting.
Returns:
Generator that yields the Cloud Netapp Volume QuotaRules.
"""
request = self.messages.NetappProjectsLocationsVolumesQuotaRulesListRequest(
parent=volume_ref
)
# Check for unreachable locations.
response = self.client.projects_locations_volumes_quotaRules.List(request)
for location in response.unreachable:
log.warning('Location {} may be unreachable.'.format(location))
return list_pager.YieldFromList(
self.client.projects_locations_volumes_quotaRules,
request,
field=constants.QUOTA_RULE_RESOURCE,
limit=limit,
batch_size_attribute='pageSize',
)
def GetQuotaRule(self, quota_rule_ref):
"""Get a Cloud NetApp Volume Quota Rule."""
request = self.messages.NetappProjectsLocationsVolumesQuotaRulesGetRequest(
name=quota_rule_ref.RelativeName()
)
return self.client.projects_locations_volumes_quotaRules.Get(request)
def DeleteQuotaRule(self, quota_rule_ref, async_):
"""Delete a Cloud NetApp Volume Quota Rule."""
request = (
self.messages.NetappProjectsLocationsVolumesQuotaRulesDeleteRequest(
name=quota_rule_ref.RelativeName()
)
)
delete_op = self.client.projects_locations_volumes_quotaRules.Delete(
request
)
if async_:
return delete_op
operation_ref = resources.REGISTRY.ParseRelativeName(
delete_op.name, collection=constants.OPERATIONS_COLLECTION
)
return self.WaitForOperation(operation_ref)
def ParseUpdatedQuotaRuleConfig(
self,
quota_rule_config,
disk_limit_mib=None,
description=None,
labels=None,
):
"""Parses updates into a quota rule config.
Args:
quota_rule_config: The quota rule config to update.
disk_limit_mib: int, a new disk limit, if any.
description: str, a new description, if any.
labels: LabelsValue message, the new labels value, if any.
Returns:
The quota rule message.
"""
if disk_limit_mib is not None:
quota_rule_config.diskLimitMib = disk_limit_mib
if description is not None:
quota_rule_config.description = description
if labels is not None:
quota_rule_config.labels = labels
return quota_rule_config
def UpdateQuotaRule(self, quota_rule_ref, quota_rule, update_mask, async_):
"""Updates a Cloud NetApp Volume Quota Rule.
Args:
quota_rule_ref: the reference to the Quota Rule.
quota_rule: Quota rule config, the updated quota rule.
update_mask: str, a comma-separated list of updated fields.
async_: bool, if False, wait for the operation to complete.
Returns:
an Operation or Volume message.
"""
request = (
self.messages.NetappProjectsLocationsVolumesQuotaRulesPatchRequest(
name=quota_rule_ref.RelativeName(),
updateMask=update_mask,
quotaRule=quota_rule,
)
)
update_op = self.client.projects_locations_volumes_quotaRules.Patch(request)
if async_:
return update_op
operation_ref = resources.REGISTRY.ParseRelativeName(
update_op.name, collection=constants.OPERATIONS_COLLECTION)
return self.WaitForOperation(operation_ref)
class QuotaRulesAdapter(object):
"""Adapter for the Cloud NetApp Files API Quota Rule resource."""
def __init__(self):
self.release_track = base.ReleaseTrack.GA
self.client = netapp_api_util.GetClientInstance(
release_track=self.release_track
)
self.messages = netapp_api_util.GetMessagesModule(
release_track=self.release_track
)
class BetaQuotaRulesAdapter(QuotaRulesAdapter):
"""Adapter for the Beta Cloud NetApp Files API Quota Rule resource."""
def __init__(self):
super(BetaQuotaRulesAdapter, self).__init__()
self.release_track = base.ReleaseTrack.BETA
self.client = netapp_api_util.GetClientInstance(
release_track=self.release_track
)
self.messages = netapp_api_util.GetMessagesModule(
release_track=self.release_track
)

View File

@@ -0,0 +1,21 @@
# -*- coding: utf-8 -*- #
# Copyright 2023 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.
"""Cloud NetApp Files Volumes Replications API client library helper files."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals

View File

@@ -0,0 +1,535 @@
# -*- coding: utf-8 -*- #
# Copyright 2023 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.
"""Commands for interacting with the Cloud NetApp Files Volume Replication API resource."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from apitools.base.py import list_pager
from googlecloudsdk.api_lib.netapp import constants
from googlecloudsdk.api_lib.netapp import util as netapp_api_util
from googlecloudsdk.api_lib.util import waiter
from googlecloudsdk.calliope import base
from googlecloudsdk.core import log
from googlecloudsdk.core import resources
class ReplicationsClient(object):
"""Wrapper for working with Replications in the Cloud NetApp Files API Client."""
def __init__(self, release_track=base.ReleaseTrack.BETA):
if release_track == base.ReleaseTrack.BETA:
self._adapter = BetaReplicationsAdapter()
elif release_track == base.ReleaseTrack.ALPHA:
self._adapter = AlphaReplicationsAdapter()
elif release_track == base.ReleaseTrack.GA:
self._adapter = ReplicationsAdapter()
else:
raise ValueError(
'[{}] is not a valid API version.'.format(
netapp_api_util.VERSION_MAP[release_track]
)
)
@property
def client(self):
return self._adapter.client
@property
def messages(self):
return self._adapter.messages
def WaitForOperation(self, operation_ref):
"""Wait on the long-running operation until the done field is True.
Args:
operation_ref: the operation reference.
Raises:
waiter.OperationError: if the operation contains an error.
Returns:
the 'response' field of the Operation.
"""
return waiter.WaitFor(
waiter.CloudOperationPollerNoResources(
self.client.projects_locations_operations
),
operation_ref,
'Waiting for [{0}] to finish'.format(operation_ref.Name()),
)
def CreateReplication(self, replication_ref, volume_ref, async_, config):
"""Creates a Cloud NetApp Volume Replication."""
request = (
self.messages.NetappProjectsLocationsVolumesReplicationsCreateRequest(
parent=volume_ref,
replicationId=replication_ref.Name(),
replication=config,
)
)
create_op = self.client.projects_locations_volumes_replications.Create(
request
)
if async_:
return create_op
operation_ref = resources.REGISTRY.ParseRelativeName(
create_op.name, collection=constants.OPERATIONS_COLLECTION
)
return self.WaitForOperation(operation_ref)
def ParseReplicationConfig(
self,
name=None,
description=None,
labels=None,
replication_schedule=None,
destination_volume_parameters=None,
cluster_location=None,
):
"""Parse the command line arguments for Create Replication into a config.
Args:
name: the name of the Replication.
description: the description of the Replication.
labels: the parsed labels value.
replication_schedule: the schedule for Replication.
destination_volume_parameters: the input parameters used for creating
destination volume.
cluster_location: location of the user cluster, optional
Returns:
the configuration that will be used as the request body for creating a
Cloud NetApp Files Replication.
"""
replication = self.messages.Replication()
replication.name = name
replication.description = description
replication.labels = labels
replication.replicationSchedule = replication_schedule
self._adapter.ParseDestinationVolumeParameters(
replication, destination_volume_parameters
)
replication.clusterLocation = cluster_location
return replication
def ListReplications(self, volume_ref, limit=None):
"""List all active Cloud NetApp Volume Replications.
Args:
volume_ref: The parent Volume to list NetApp Volume Replications.
limit: The number of Cloud NetApp Volume Replications to limit the results
to. This limit is passed to the server and the server does the limiting.
Returns:
Generator that yields the Cloud NetApp Volume Replications.
"""
request = (
self.messages.NetappProjectsLocationsVolumesReplicationsListRequest(
parent=volume_ref
)
)
# Check for unreachable locations.
response = self.client.projects_locations_volumes_replications.List(request)
for location in response.unreachable:
log.warning('Location {} may be unreachable.'.format(location))
return list_pager.YieldFromList(
self.client.projects_locations_volumes_replications,
request,
field=constants.REPLICATION_RESOURCE,
limit=limit,
batch_size_attribute='pageSize',
)
def DeleteReplication(self, replication_ref, async_):
"""Delete an existing Cloud NetApp Volume Replication."""
request = (
self.messages.NetappProjectsLocationsVolumesReplicationsDeleteRequest(
name=replication_ref.RelativeName()
)
)
return self._DeleteReplication(async_, request)
def _DeleteReplication(self, async_, request):
delete_op = self.client.projects_locations_volumes_replications.Delete(
request
)
if async_:
return delete_op
operation_ref = resources.REGISTRY.ParseRelativeName(
delete_op.name, collection=constants.OPERATIONS_COLLECTION
)
return self.WaitForOperation(operation_ref)
def GetReplication(self, replication_ref):
"""Get information of a Cloud NetApp Volume Replication."""
request = (
self.messages.NetappProjectsLocationsVolumesReplicationsGetRequest(
name=replication_ref.RelativeName()
)
)
return self.client.projects_locations_volumes_replications.Get(request)
def ParseUpdatedReplicationConfig(
self, replication_config, description=None, labels=None,
replication_schedule=None, cluster_location=None
):
"""Parse updates into a replication config.
Args:
replication_config: The replication config to update.
description: The new description, if any.
labels: LabelsValue message, the new labels value, if any.
replication_schedule: The new schedule for Replication, if any.
cluster_location: location of the user cluster, if any.
Returns:
The replication message.
"""
return self._adapter.ParseUpdatedReplicationConfig(
replication_config, description=description, labels=labels,
replication_schedule=replication_schedule,
cluster_location=cluster_location,
)
def UpdateReplication(
self, replication_ref, replication_config, update_mask, async_
):
"""Update a Cloud NetApp Volume Replication.
Args:
replication_ref: the reference to the Replication.
replication_config: Replication config, the updated replication.
update_mask: str, a comma-separated list of updated fields.
async_: bool, if False, wait for the operation to complete.
Returns:
an Operation or Volume message.
"""
update_op = self._adapter.UpdateReplication(
replication_ref, replication_config, update_mask
)
if async_:
return update_op
operation_ref = resources.REGISTRY.ParseRelativeName(
update_op.name, collection=constants.OPERATIONS_COLLECTION
)
return self.WaitForOperation(operation_ref)
def ResumeReplication(
self, replication_ref, async_
):
"""Resume a Cloud NetApp Volume Replication.
Args:
replication_ref: the reference to the Replication.
async_: bool, if False, wait for the operation to complete.
Returns:
an Operation or Volume message.
"""
resume_op = self._adapter.ResumeReplication(replication_ref)
if async_:
return resume_op
operation_ref = resources.REGISTRY.ParseRelativeName(
resume_op.name, collection=constants.OPERATIONS_COLLECTION
)
return self.WaitForOperation(operation_ref)
def ReverseReplication(
self, replication_ref, async_
):
"""Reverse the direction of a Cloud NetApp Volume Replication.
Args:
replication_ref: the reference to the Replication.
async_: bool, if False, wait for the operation to complete.
Returns:
an Operation if async_ is set to true, or a Replication message if the
ReverseReplicationDirectionRequest is successful.
"""
reverse_op = self._adapter.ReverseReplication(replication_ref)
if async_:
return reverse_op
operation_ref = resources.REGISTRY.ParseRelativeName(
reverse_op.name, collection=constants.OPERATIONS_COLLECTION
)
return self.WaitForOperation(operation_ref)
def StopReplication(self, replication_ref, async_, force):
"""Stop a Cloud NetApp Volume Replication.
Args:
replication_ref: the reference to the Replication.
async_: bool, if False, wait for the operation to complete.
force: bool, if True, call stop Replication with force parameter set to
True.
Returns:
an Operation or Volume message.
"""
stop_op = self._adapter.StopReplication(replication_ref, force)
if async_:
return stop_op
operation_ref = resources.REGISTRY.ParseRelativeName(
stop_op.name, collection=constants.OPERATIONS_COLLECTION
)
return self.WaitForOperation(operation_ref)
def ParseEstablishPeeringRequestConfig(
self,
peer_cluster_name,
peer_svm_name,
peer_volume_name,
peer_ip_addresses=None,
):
"""Parse the command line arguments for Establish Peering into a config.
Args:
peer_cluster_name: the name of the peer cluster.
peer_svm_name: the name of the peer svm.
peer_volume_name: the name of the peer volume.
peer_ip_addresses: the ip addresses of the peer cluster.
Returns:
the configuration that will be used as the request body for establishing
peering for Hybrid Replication.
"""
return self._adapter.ParseEstablishPeeringRequestConfig(
peer_cluster_name, peer_svm_name, peer_volume_name, peer_ip_addresses
)
def EstablishPeering(
self, replication_ref, establish_peering_request_config, async_
):
"""Establish a peering for a Cloud NetApp Volume Replication.
Args:
replication_ref: the reference to the Replication.
establish_peering_request_config: the request configuration to establish
peering.
async_: bool, if False, wait for the operation to complete.
Returns:
an Operation or Volume message.
"""
establish_op = self._adapter.EstablishPeering(
replication_ref, establish_peering_request_config
)
if async_:
return establish_op
operation_ref = resources.REGISTRY.ParseRelativeName(
establish_op.name, collection=constants.OPERATIONS_COLLECTION
)
return self.WaitForOperation(operation_ref)
def SyncReplication(self, replication_ref, async_):
"""Sync a Cloud NetApp Volume Replication.
Args:
replication_ref: the reference to the Replication.
async_: bool, if False, wait for the operation to complete.
Returns:
an Operation or Volume message.
"""
sync_op = self._adapter.SyncReplication(replication_ref)
if async_:
return sync_op
operation_ref = resources.REGISTRY.ParseRelativeName(
sync_op.name, collection=constants.OPERATIONS_COLLECTION
)
return self.WaitForOperation(operation_ref)
class ReplicationsAdapter(object):
"""Adapter for the Cloud NetApp Files API Replication resource."""
def __init__(self):
self.release_track = base.ReleaseTrack.GA
self.client = netapp_api_util.GetClientInstance(
release_track=self.release_track
)
self.messages = netapp_api_util.GetMessagesModule(
release_track=self.release_track
)
def ParseDestinationVolumeParameters(
self, replication, destination_volume_parameters
):
"""Parses Destination Volume Parameters for Replication into a config.
Args:
replication: The Cloud Netapp Volumes Replication object.
destination_volume_parameters: The Destination Volume Parameters message
object.
Returns:
Replication message populated with Destination Volume Parameters values.
"""
if not destination_volume_parameters:
return
parameters = self.messages.DestinationVolumeParameters()
for key, val in destination_volume_parameters.items():
if key == 'storage_pool':
parameters.storagePool = val
elif key == 'volume_id':
parameters.volumeId = val
elif key == 'share_name':
parameters.shareName = val
elif key == 'description':
parameters.description = val
elif key == 'tiering_policy':
parameters.tieringPolicy = self.messages.TieringPolicy(
tierAction=val['tier-action'],
coolingThresholdDays=val['cooling-threshold-days'],
)
else:
log.warning('The attribute {} is not recognized.'.format(key))
replication.destinationVolumeParameters = parameters
def UpdateReplication(self, replication_ref, replication_config, update_mask):
"""Send a Patch request for the Cloud NetApp Volume Replication."""
update_request = (
self.messages.NetappProjectsLocationsVolumesReplicationsPatchRequest(
replication=replication_config,
name=replication_ref.RelativeName(),
updateMask=update_mask,
)
)
update_op = self.client.projects_locations_volumes_replications.Patch(
update_request
)
return update_op
def ParseUpdatedReplicationConfig(
self, replication_config, description=None, labels=None,
replication_schedule=None, cluster_location=None
):
"""Parse update information into an updated Replication message."""
if description is not None:
replication_config.description = description
if labels is not None:
replication_config.labels = labels
if replication_schedule is not None:
replication_config.replicationSchedule = replication_schedule
if cluster_location is not None:
replication_config.clusterLocation = cluster_location
return replication_config
def ResumeReplication(self, replication_ref):
"""Send a resume request for the Cloud NetApp Volume Replication."""
resume_request = (
self.messages.NetappProjectsLocationsVolumesReplicationsResumeRequest(
name=replication_ref.RelativeName(),
)
)
return self.client.projects_locations_volumes_replications.Resume(
resume_request
)
def ReverseReplication(self, replication_ref):
"""Send a reverse request for the Cloud NetApp Volume Replication."""
reverse_request = (
self.messages.NetappProjectsLocationsVolumesReplicationsReverseDirectionRequest(
name=replication_ref.RelativeName(),
)
)
return self.client.projects_locations_volumes_replications.ReverseDirection(
reverse_request
)
def StopReplication(self, replication_ref, force):
"""Send a stop request for the Cloud NetApp Volume Replication."""
stop_request = (
self.messages.NetappProjectsLocationsVolumesReplicationsStopRequest(
name=replication_ref.RelativeName(),
stopReplicationRequest=self.messages.StopReplicationRequest(
force=force
),
)
)
return self.client.projects_locations_volumes_replications.Stop(
stop_request
)
def ParseEstablishPeeringRequestConfig(
self,
peer_cluster_name,
peer_svm_name,
peer_volume_name,
peer_ip_addresses,
):
"""Parse establish peering request for the Cloud NetApp Volume Replication."""
establish_peering_request = self.messages.EstablishPeeringRequest(
peerClusterName=peer_cluster_name,
peerSvmName=peer_svm_name,
peerVolumeName=peer_volume_name,
peerIpAddresses=peer_ip_addresses if peer_ip_addresses else [],
)
return establish_peering_request
def EstablishPeering(self, replication_ref, establish_peering_request_config):
"""Send a establish peering request for the Cloud NetApp Volume Replication."""
establish_peering_request = (
self.messages.NetappProjectsLocationsVolumesReplicationsEstablishPeeringRequest(
name=replication_ref.RelativeName(),
establishPeeringRequest=establish_peering_request_config,
)
)
return self.client.projects_locations_volumes_replications.EstablishPeering(
establish_peering_request
)
def SyncReplication(self, replication_ref):
"""Send a sync request for the Cloud NetApp Volume Replication."""
sync_request = (
self.messages.NetappProjectsLocationsVolumesReplicationsSyncRequest(
name=replication_ref.RelativeName(),
)
)
return self.client.projects_locations_volumes_replications.Sync(
sync_request
)
class BetaReplicationsAdapter(ReplicationsAdapter):
"""Adapter for the Beta Cloud NetApp Files API Replication resource."""
def __init__(self):
super(BetaReplicationsAdapter, self).__init__()
self.release_track = base.ReleaseTrack.BETA
self.client = netapp_api_util.GetClientInstance(
release_track=self.release_track
)
self.messages = netapp_api_util.GetMessagesModule(
release_track=self.release_track
)
class AlphaReplicationsAdapter(BetaReplicationsAdapter):
"""Adapter for the Alpha Cloud NetApp Files API Replication resource."""
def __init__(self):
super(AlphaReplicationsAdapter, self).__init__()
self.release_track = base.ReleaseTrack.ALPHA
self.client = netapp_api_util.GetClientInstance(
release_track=self.release_track
)
self.messages = netapp_api_util.GetMessagesModule(
release_track=self.release_track
)

View File

@@ -0,0 +1,21 @@
# -*- 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.
"""Cloud NetApp Files Volumes Snapshots API client library helper files."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals

View File

@@ -0,0 +1,253 @@
# -*- 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.
"""Commands for interacting with the Cloud NetApp Files Volume Snapshot API resource."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from apitools.base.py import list_pager
from googlecloudsdk.api_lib.netapp import constants
from googlecloudsdk.api_lib.netapp import util as netapp_api_util
from googlecloudsdk.api_lib.util import waiter
from googlecloudsdk.calliope import base
from googlecloudsdk.core import log
from googlecloudsdk.core import resources
class SnapshotsClient(object):
"""Wrapper for working with Snapshots in the Cloud NetApp Files API Client."""
def __init__(self, release_track=base.ReleaseTrack.ALPHA):
if release_track == base.ReleaseTrack.ALPHA:
self._adapter = AlphaSnapshotsAdapter()
elif release_track == base.ReleaseTrack.BETA:
self._adapter = BetaSnapshotsAdapter()
elif release_track == base.ReleaseTrack.GA:
self._adapter = SnapshotsAdapter()
else:
raise ValueError('[{}] is not a valid API version.'.format(
netapp_api_util.VERSION_MAP[release_track]))
@property
def client(self):
return self._adapter.client
@property
def messages(self):
return self._adapter.messages
def WaitForOperation(self, operation_ref):
"""Waits on the long-running operation until the done field is True.
Args:
operation_ref: the operation reference.
Raises:
waiter.OperationError: if the operation contains an error.
Returns:
the 'response' field of the Operation.
"""
return waiter.WaitFor(
waiter.CloudOperationPollerNoResources(
self.client.projects_locations_operations
),
operation_ref,
'Waiting for [{0}] to finish'.format(operation_ref.Name()),
)
def CreateSnapshot(self, snapshot_ref, volume_ref, async_, config):
"""Create a Cloud NetApp Volume Snapshot."""
request = (
self.messages.NetappProjectsLocationsVolumesSnapshotsCreateRequest(
parent=volume_ref, snapshotId=snapshot_ref.Name(), snapshot=config
)
)
create_op = self.client.projects_locations_volumes_snapshots.Create(request)
if async_:
return create_op
operation_ref = resources.REGISTRY.ParseRelativeName(
create_op.name, collection=constants.OPERATIONS_COLLECTION
)
return self.WaitForOperation(operation_ref)
def ParseSnapshotConfig(self, name=None, description=None, labels=None):
"""Parses the command line arguments for Create Snapshot into a config.
Args:
name: the name of the Snapshot.
description: the description of the Snapshot.
labels: the parsed labels value.
Returns:
the configuration that will be used as the request body for creating a
Cloud NetApp Files Snapshot.
"""
snapshot = self.messages.Snapshot()
snapshot.name = name
snapshot.description = description
snapshot.labels = labels
return snapshot
def ListSnapshots(self, volume_ref, limit=None):
"""Make API calls to List active Cloud NetApp Volume Snapshots.
Args:
volume_ref: The parent Volume to list NetApp Volume Snapshots.
limit: The number of Cloud NetApp Volume Snapshots to limit the results
to. This limit is passed to the server and the server does the limiting.
Returns:
Generator that yields the Cloud NetApp Volume Snapshots.
"""
request = self.messages.NetappProjectsLocationsVolumesSnapshotsListRequest(
parent=volume_ref)
# Check for unreachable locations.
response = self.client.projects_locations_volumes_snapshots.List(request)
for location in response.unreachable:
log.warning('Location {} may be unreachable.'.format(location))
return list_pager.YieldFromList(
self.client.projects_locations_volumes_snapshots,
request,
field=constants.SNAPSHOT_RESOURCE,
limit=limit,
batch_size_attribute='pageSize',
)
def DeleteSnapshot(self, snapshot_ref, async_):
"""Deletes an existing Cloud NetApp Volume Snapshot."""
request = (
self.messages.NetappProjectsLocationsVolumesSnapshotsDeleteRequest(
name=snapshot_ref.RelativeName()
)
)
return self._DeleteSnapshot(async_, request)
def _DeleteSnapshot(self, async_, request):
delete_op = self.client.projects_locations_volumes_snapshots.Delete(request)
if async_:
return delete_op
operation_ref = resources.REGISTRY.ParseRelativeName(
delete_op.name, collection=constants.OPERATIONS_COLLECTION)
return self.WaitForOperation(operation_ref)
def GetSnapshot(self, snapshot_ref):
"""Get Cloud NetApp Snapshot information."""
request = self.messages.NetappProjectsLocationsVolumesSnapshotsGetRequest(
name=snapshot_ref.RelativeName())
return self.client.projects_locations_volumes_snapshots.Get(request)
def ParseUpdatedSnapshotConfig(self,
snapshot_config,
description=None,
labels=None):
"""Parses updates into a snapshot config.
Args:
snapshot_config: The snapshot config to update.
description: str, a new description, if any.
labels: LabelsValue message, the new labels value, if any.
Returns:
The snapshot message.
"""
return self._adapter.ParseUpdatedSnapshotConfig(
snapshot_config,
description=description,
labels=labels)
def UpdateSnapshot(self, snapshot_ref, snapshot_config, update_mask, async_):
"""Updates a Cloud NetApp Snapshot.
Args:
snapshot_ref: the reference to the Snapshot.
snapshot_config: Snapshot config, the updated snapshot.
update_mask: str, a comma-separated list of updated fields.
async_: bool, if False, wait for the operation to complete.
Returns:
an Operation or Volume message.
"""
update_op = self._adapter.UpdateSnapshot(snapshot_ref, snapshot_config,
update_mask)
if async_:
return update_op
operation_ref = resources.REGISTRY.ParseRelativeName(
update_op.name, collection=constants.OPERATIONS_COLLECTION)
return self.WaitForOperation(operation_ref)
class SnapshotsAdapter(object):
"""Adapter for the Cloud NetApp Files API Snapshot resource."""
def __init__(self):
self.release_track = base.ReleaseTrack.GA
self.client = netapp_api_util.GetClientInstance(
release_track=self.release_track
)
self.messages = netapp_api_util.GetMessagesModule(
release_track=self.release_track
)
def UpdateSnapshot(self, snapshot_ref, snapshot_config, update_mask):
"""Send a Patch request for the Cloud NetApp Snapshot."""
update_request = (
self.messages.NetappProjectsLocationsVolumesSnapshotsPatchRequest(
snapshot=snapshot_config,
name=snapshot_ref.RelativeName(),
updateMask=update_mask))
update_op = self.client.projects_locations_volumes_snapshots.Patch(
update_request)
return update_op
def ParseUpdatedSnapshotConfig(self,
snapshot_config,
description=None,
labels=None):
"""Parse update information into an updated Snapshot message."""
if description is not None:
snapshot_config.description = description
if labels is not None:
snapshot_config.labels = labels
return snapshot_config
class BetaSnapshotsAdapter(SnapshotsAdapter):
"""Adapter for the Beta Cloud NetApp Files API Snapshot resource."""
def __init__(self):
super(BetaSnapshotsAdapter, self).__init__()
self.release_track = base.ReleaseTrack.BETA
self.client = netapp_api_util.GetClientInstance(
release_track=self.release_track
)
self.messages = netapp_api_util.GetMessagesModule(
release_track=self.release_track
)
class AlphaSnapshotsAdapter(BetaSnapshotsAdapter):
"""Adapter for the Alpha Cloud NetApp Files API Snapshot resource."""
def __init__(self):
super(AlphaSnapshotsAdapter, self).__init__()
self.release_track = base.ReleaseTrack.ALPHA
self.client = netapp_api_util.GetClientInstance(
release_track=self.release_track
)
self.messages = netapp_api_util.GetMessagesModule(
release_track=self.release_track
)