General Discussion

PowerShell Toolkit - Automating Qtree and Share Creation Issues

MattBaldwin
221 Views

I am working on some automation using powershell and the powershell toolkit.  After creating a qtree and then its share, I am trying to set the 'ShareProperties' parameter, "browsable", which correlates to the checkbox in the UI for "allow client access to snapshot copies directory".   It fails saying, "ShareProperties parameter specified, which is not supported for REST call". 

 

I have tried it with Set-NcCifsShare and Add-NcCifsShare.  I am running the powershell module for NetApp.ONTAP Version: 9.16.1.2501 in PowerShell 7.5.1.

 

An example of the script.  If I take out the shareproperties piece, it works perfectly.

Set-NcCifsShare -Name $shareName -SymlinkProperties enable  -AccessBasedEnumeration $true -ShareProperties "browsable" -VserverContext $storageVM

Is there any way to set that option via PowerShell? 

1 ACCEPTED SOLUTION

mbeattie
132 Views

Hey Matt,

 

Just FYI if a PowerShell CmdLet doesn't support setting a value you can either use the Private REST CLI to invoke an SSH command HTTPS or if the PSTK CmdLet doesn't support setting a property value but the REST API does and you don't want to use ZAPI you can write your own functions around the native ONTAP REST API's. Here's an example that enables you to set a CIFS share property value using REST and PowerShell

 

Param(
   [Parameter(Mandatory = $True, HelpMessage = "The IP Address of the Cluster or SVM")]
   [String]$Cluster,
   [Parameter(Mandatory = $True, HelpMessage = "The Vserver Name")]
   [String]$VserverName,
   [Parameter(Mandatory = $False, HelpMessage = "The Vserver UUID")]
   [String]$VserverID,
   [Parameter(Mandatory = $True, HelpMessage = "The CIFS Share Name")]
   [String]$ShareName,
   [Parameter(Mandatory = $True, HelpMessage = "The CIFS Share Property")]
   [ValidateSet("oplocks","browsable","showsnapshot","changenotify","homedirectory","attributecache")]
   [String]$ShareProperty,
   [Parameter(Mandatory = $True, HelpMessage = "The CIFS Share Property Enabled State")]
   [Bool]$Enabled,
   [Parameter(Mandatory = $True, HelpMessage = "The Credential to authenticate to the Cluster or SVM")]
   [ValidateNotNullOrEmpty()]
   [System.Management.Automation.PSCredential]$Credential
)
#'------------------------------------------------------------------------------
Function Get-OntapVserver{
   [CmdletBinding()]
   Param(
      [Parameter(Mandatory = $True, HelpMessage = "The Cluster Name or IP Address")]
      [String]$Cluster,
      [Parameter(Mandatory = $True, HelpMessage = "The Vserver Name")]
      [String]$VserverName,
      [Parameter(Mandatory = $True, HelpMessage = "The Credential to authenticate to the Cluster")]
      [ValidateNotNullOrEmpty()]
      [System.Management.Automation.PSCredential]$Credential
   )
   #'---------------------------------------------------------------------------
   #'Set the authentication header to connect to AIQUM.
   #'---------------------------------------------------------------------------
   $headers = Get-UMAuthorization -Credential $Credential
   #'---------------------------------------------------------------------------
   #'Enumerate the vservers.
   #'---------------------------------------------------------------------------
   [String]$uri = "https://$Cluster/api/svm/svms?name=$VserverName"
   Try{
      $response = Invoke-RestMethod -Uri $uri -Method GET -Headers $headers -ErrorAction Stop
      Write-Host "Enumerated Vserver ""$VserverName"" on Cluster ""$Cluster"" using URI ""$uri"""
   }Catch{
      Write-Warning -Message $("Failed enumerating Vserver ""$VserverName"" on Cluster ""$Cluster"" using URI ""$uri"". Error " + $_.Exception.Message + ". Status Code " + $_.Exception.Response.StatusCode.value__)
   }
   Return $response;
}#'End Function Get-OntapVserver.
#'------------------------------------------------------------------------------
Function Set-OntapCifsShareProperty{
   [CmdletBinding()]
   Param(
      [Parameter(Mandatory = $True, HelpMessage = "The IP Address of the Cluster or SVM")]
      [String]$Cluster,
      [Parameter(Mandatory = $True, HelpMessage = "The Vserver Name")]
      [String]$VserverName,
      [Parameter(Mandatory = $False, HelpMessage = "The Vserver UUID")]
      [String]$VserverID,
      [Parameter(Mandatory = $True, HelpMessage = "The CIFS Share Name")]
      [String]$ShareName,
      [Parameter(Mandatory = $True, HelpMessage = "The CIFS Share Property")]
      [ValidateSet("oplocks","browsable","showsnapshot","changenotify","homedirectory","attributecache")]
      [String]$ShareProperty,
      [Parameter(Mandatory = $True, HelpMessage = "The CIFS Share Property Enabled State")]
      [Bool]$Enabled,
      [Parameter(Mandatory = $True, HelpMessage = "The Credential to authenticate to the Cluster or SVM")]
      [ValidateNotNullOrEmpty()]
      [System.Management.Automation.PSCredential]$Credential
   )
   #'---------------------------------------------------------------------------
   #'Enumerate the Vserver UUID if not provided.
   #'---------------------------------------------------------------------------
   If(-Not($VserverID)){
      $vserver = Get-OntapVserver -Cluster $Cluster -VserverName $VserverName -Credential $Credential
      If(($Null -eq $Vserver) -Or ($vserver.num_records -ne 1)){
         Write-Warning -Message "Failed enumerating UUID for Vserver ""$VserverName"" on Cluster ""$Cluster"""
         Return $Null;
      }Else{
         [String]$VserverID = $vserver.records.uuid
      }
   }
   #'---------------------------------------------------------------------------
   #'Set the CIFS Share Property.
   #'---------------------------------------------------------------------------
   [String]$url = "https://$Cluster/api/protocols/cifs/shares/$VserverID/$ShareName"
   $json = @{"$ShareProperty" = $Enabled.ToString()}
   $body = $json | ConvertTo-Json
   Try{
      $response = Invoke-RestMethod -Method Patch -Body $body -Uri $url -Credential $Credential -ErrorAction Stop
      Write-Host "Set CIFS Share ""$ShareName"" Property ""$ShareProperty"" on Vserver ""$VserverName"" on Cluster ""$Cluster"" using URL`: ""$url"""
   }Catch{
      Write-Warning -Message $("Failed setting CIFS Share Property ""$ShareProperty"" on Vserver ""$VserverName"" on Cluster ""$Cluster"" using URL`: ""$url"". Error " + $_.Exception.Message)
   }
   Return $response;
}#'End Function Set-OntapCifsShareProperty.
#'------------------------------------------------------------------------------
Function Get-UMAuthorization{
   [Alias("Get-UMAuth")]
   [CmdletBinding()]
   Param(
      [Parameter(Mandatory = $True, HelpMessage = "The Credential to authenticate to AIQUM")]
      [ValidateNotNullOrEmpty()]
      [System.Management.Automation.PSCredential]$Credential
   )
   #'---------------------------------------------------------------------------
   #'Set the authentication header to connect to AIQUM.
   #'---------------------------------------------------------------------------
   $auth    = [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($Credential.UserName + ':' + $Credential.GetNetworkCredential().Password))
   $headers = @{
      "Authorization" = "Basic $auth"
      "Accept"        = "application/json"
      "Content-Type"  = "application/json"
   }
   Return $headers;
}#'End Function Get-UMAuthorization.
#'------------------------------------------------------------------------------
#'Set the certificate policy and TLS version.
#'------------------------------------------------------------------------------
Add-Type @"
   using System.Net;
   using System.Security.Cryptography.X509Certificates;
   public class TrustAllCertsPolicy : ICertificatePolicy {
   public bool CheckValidationResult(
   ServicePoint srvPoint, X509Certificate certificate,
   WebRequest request, int certificateProblem) {
      return true;
   }
}
"@
#[System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls -bor [Net.SecurityProtocolType]::Tls11 -bor [Net.SecurityProtocolType]::Tls12
[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy
#'------------------------------------------------------------------------------
#'Disable SSL Check.
#'------------------------------------------------------------------------------
$sslHandler = @"
public class SSLHandler{
   public static System.Net.Security.RemoteCertificateValidationCallback GetSSLHandler(){
      return new System.Net.Security.RemoteCertificateValidationCallback((sender, certificate, chain, policyErrors) => { return true; });
   } 
}
"@
Add-Type -TypeDefinition $sslHandler
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = [SSLHandler]::GetSSLHandler()
#'------------------------------------------------------------------------------
$response = Set-OntapCifsShareProperty -Cluster $Cluster -VserverName $VserverName -ShareName $ShareName -ShareProperty $ShareProperty -Enabled $Enabled -Credential $Credential
$response

Example:

 

PS C:\Scripts\PowerShell\Projects\SetCifsShareProperty> $Credential = Get-Credential
PS C:\Scripts\PowerShell\Projects\SetCifsShareProperty> .\SetCifsShareProperty.ps1 -Cluster 192.168.100.2 -VserverName svm1 -ShareName "share1`$" -ShareProperty browsable -Enabled $true -Credential $credential
Enumerated Vserver "svm1" on Cluster "192.168.100.2" using URI "https://192.168.100.2/api/svm/svms?name=svm1"
Set CIFS Share "share1$" Property "browsable" on Vserver "svm1" on Cluster "192.168.100.2" using URL: "https://192.168.100.2/api/protocols/cifs/shares/939ee27e-e202-11ef-aef5-00a098bd4884/testshare$"


cluster1::> cifs share show -vserver svm1 -share-name share1$ -fields share-properties
vserver      share-name  share-properties
------------ ----------- -----------------------------------------------------
svm1 share1$ oplocks,browsable,changenotify,show-previous-versions

 

Hope that helps

 

/Matt

If this post resolved your issue, help others by selecting ACCEPT AS SOLUTION or adding a KUDO.

View solution in original post

5 REPLIES 5

mbeattie
135 Views

Hey Matt,

 

The browsable parameter was introduced in the REST API in ONTAP 9.13

 

/protocols/cifs/shares/{svm.uuid}/{name}

 

It's possible that the PSTK CmdLet has not yet been updated to support setting this property (although it is possible if you use the native REST API). You could either write a PowerShell Function that invokes the REST API externally to the PSTK or alternately you can use the -ZapiCall parameter on the "Connect-NcController" CmdLet which will force the connection to the cluster to use ZAPI instead of the REST API and then you should be able to set the "ShareProperties" parameter to "browsable".

 

/Matt

 

 

If this post resolved your issue, help others by selecting ACCEPT AS SOLUTION or adding a KUDO.

mbeattie
133 Views

Hey Matt,

 

Just FYI if a PowerShell CmdLet doesn't support setting a value you can either use the Private REST CLI to invoke an SSH command HTTPS or if the PSTK CmdLet doesn't support setting a property value but the REST API does and you don't want to use ZAPI you can write your own functions around the native ONTAP REST API's. Here's an example that enables you to set a CIFS share property value using REST and PowerShell

 

Param(
   [Parameter(Mandatory = $True, HelpMessage = "The IP Address of the Cluster or SVM")]
   [String]$Cluster,
   [Parameter(Mandatory = $True, HelpMessage = "The Vserver Name")]
   [String]$VserverName,
   [Parameter(Mandatory = $False, HelpMessage = "The Vserver UUID")]
   [String]$VserverID,
   [Parameter(Mandatory = $True, HelpMessage = "The CIFS Share Name")]
   [String]$ShareName,
   [Parameter(Mandatory = $True, HelpMessage = "The CIFS Share Property")]
   [ValidateSet("oplocks","browsable","showsnapshot","changenotify","homedirectory","attributecache")]
   [String]$ShareProperty,
   [Parameter(Mandatory = $True, HelpMessage = "The CIFS Share Property Enabled State")]
   [Bool]$Enabled,
   [Parameter(Mandatory = $True, HelpMessage = "The Credential to authenticate to the Cluster or SVM")]
   [ValidateNotNullOrEmpty()]
   [System.Management.Automation.PSCredential]$Credential
)
#'------------------------------------------------------------------------------
Function Get-OntapVserver{
   [CmdletBinding()]
   Param(
      [Parameter(Mandatory = $True, HelpMessage = "The Cluster Name or IP Address")]
      [String]$Cluster,
      [Parameter(Mandatory = $True, HelpMessage = "The Vserver Name")]
      [String]$VserverName,
      [Parameter(Mandatory = $True, HelpMessage = "The Credential to authenticate to the Cluster")]
      [ValidateNotNullOrEmpty()]
      [System.Management.Automation.PSCredential]$Credential
   )
   #'---------------------------------------------------------------------------
   #'Set the authentication header to connect to AIQUM.
   #'---------------------------------------------------------------------------
   $headers = Get-UMAuthorization -Credential $Credential
   #'---------------------------------------------------------------------------
   #'Enumerate the vservers.
   #'---------------------------------------------------------------------------
   [String]$uri = "https://$Cluster/api/svm/svms?name=$VserverName"
   Try{
      $response = Invoke-RestMethod -Uri $uri -Method GET -Headers $headers -ErrorAction Stop
      Write-Host "Enumerated Vserver ""$VserverName"" on Cluster ""$Cluster"" using URI ""$uri"""
   }Catch{
      Write-Warning -Message $("Failed enumerating Vserver ""$VserverName"" on Cluster ""$Cluster"" using URI ""$uri"". Error " + $_.Exception.Message + ". Status Code " + $_.Exception.Response.StatusCode.value__)
   }
   Return $response;
}#'End Function Get-OntapVserver.
#'------------------------------------------------------------------------------
Function Set-OntapCifsShareProperty{
   [CmdletBinding()]
   Param(
      [Parameter(Mandatory = $True, HelpMessage = "The IP Address of the Cluster or SVM")]
      [String]$Cluster,
      [Parameter(Mandatory = $True, HelpMessage = "The Vserver Name")]
      [String]$VserverName,
      [Parameter(Mandatory = $False, HelpMessage = "The Vserver UUID")]
      [String]$VserverID,
      [Parameter(Mandatory = $True, HelpMessage = "The CIFS Share Name")]
      [String]$ShareName,
      [Parameter(Mandatory = $True, HelpMessage = "The CIFS Share Property")]
      [ValidateSet("oplocks","browsable","showsnapshot","changenotify","homedirectory","attributecache")]
      [String]$ShareProperty,
      [Parameter(Mandatory = $True, HelpMessage = "The CIFS Share Property Enabled State")]
      [Bool]$Enabled,
      [Parameter(Mandatory = $True, HelpMessage = "The Credential to authenticate to the Cluster or SVM")]
      [ValidateNotNullOrEmpty()]
      [System.Management.Automation.PSCredential]$Credential
   )
   #'---------------------------------------------------------------------------
   #'Enumerate the Vserver UUID if not provided.
   #'---------------------------------------------------------------------------
   If(-Not($VserverID)){
      $vserver = Get-OntapVserver -Cluster $Cluster -VserverName $VserverName -Credential $Credential
      If(($Null -eq $Vserver) -Or ($vserver.num_records -ne 1)){
         Write-Warning -Message "Failed enumerating UUID for Vserver ""$VserverName"" on Cluster ""$Cluster"""
         Return $Null;
      }Else{
         [String]$VserverID = $vserver.records.uuid
      }
   }
   #'---------------------------------------------------------------------------
   #'Set the CIFS Share Property.
   #'---------------------------------------------------------------------------
   [String]$url = "https://$Cluster/api/protocols/cifs/shares/$VserverID/$ShareName"
   $json = @{"$ShareProperty" = $Enabled.ToString()}
   $body = $json | ConvertTo-Json
   Try{
      $response = Invoke-RestMethod -Method Patch -Body $body -Uri $url -Credential $Credential -ErrorAction Stop
      Write-Host "Set CIFS Share ""$ShareName"" Property ""$ShareProperty"" on Vserver ""$VserverName"" on Cluster ""$Cluster"" using URL`: ""$url"""
   }Catch{
      Write-Warning -Message $("Failed setting CIFS Share Property ""$ShareProperty"" on Vserver ""$VserverName"" on Cluster ""$Cluster"" using URL`: ""$url"". Error " + $_.Exception.Message)
   }
   Return $response;
}#'End Function Set-OntapCifsShareProperty.
#'------------------------------------------------------------------------------
Function Get-UMAuthorization{
   [Alias("Get-UMAuth")]
   [CmdletBinding()]
   Param(
      [Parameter(Mandatory = $True, HelpMessage = "The Credential to authenticate to AIQUM")]
      [ValidateNotNullOrEmpty()]
      [System.Management.Automation.PSCredential]$Credential
   )
   #'---------------------------------------------------------------------------
   #'Set the authentication header to connect to AIQUM.
   #'---------------------------------------------------------------------------
   $auth    = [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($Credential.UserName + ':' + $Credential.GetNetworkCredential().Password))
   $headers = @{
      "Authorization" = "Basic $auth"
      "Accept"        = "application/json"
      "Content-Type"  = "application/json"
   }
   Return $headers;
}#'End Function Get-UMAuthorization.
#'------------------------------------------------------------------------------
#'Set the certificate policy and TLS version.
#'------------------------------------------------------------------------------
Add-Type @"
   using System.Net;
   using System.Security.Cryptography.X509Certificates;
   public class TrustAllCertsPolicy : ICertificatePolicy {
   public bool CheckValidationResult(
   ServicePoint srvPoint, X509Certificate certificate,
   WebRequest request, int certificateProblem) {
      return true;
   }
}
"@
#[System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls -bor [Net.SecurityProtocolType]::Tls11 -bor [Net.SecurityProtocolType]::Tls12
[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy
#'------------------------------------------------------------------------------
#'Disable SSL Check.
#'------------------------------------------------------------------------------
$sslHandler = @"
public class SSLHandler{
   public static System.Net.Security.RemoteCertificateValidationCallback GetSSLHandler(){
      return new System.Net.Security.RemoteCertificateValidationCallback((sender, certificate, chain, policyErrors) => { return true; });
   } 
}
"@
Add-Type -TypeDefinition $sslHandler
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = [SSLHandler]::GetSSLHandler()
#'------------------------------------------------------------------------------
$response = Set-OntapCifsShareProperty -Cluster $Cluster -VserverName $VserverName -ShareName $ShareName -ShareProperty $ShareProperty -Enabled $Enabled -Credential $Credential
$response

Example:

 

PS C:\Scripts\PowerShell\Projects\SetCifsShareProperty> $Credential = Get-Credential
PS C:\Scripts\PowerShell\Projects\SetCifsShareProperty> .\SetCifsShareProperty.ps1 -Cluster 192.168.100.2 -VserverName svm1 -ShareName "share1`$" -ShareProperty browsable -Enabled $true -Credential $credential
Enumerated Vserver "svm1" on Cluster "192.168.100.2" using URI "https://192.168.100.2/api/svm/svms?name=svm1"
Set CIFS Share "share1$" Property "browsable" on Vserver "svm1" on Cluster "192.168.100.2" using URL: "https://192.168.100.2/api/protocols/cifs/shares/939ee27e-e202-11ef-aef5-00a098bd4884/testshare$"


cluster1::> cifs share show -vserver svm1 -share-name share1$ -fields share-properties
vserver      share-name  share-properties
------------ ----------- -----------------------------------------------------
svm1 share1$ oplocks,browsable,changenotify,show-previous-versions

 

Hope that helps

 

/Matt

If this post resolved your issue, help others by selecting ACCEPT AS SOLUTION or adding a KUDO.

Thank you both for the replies!  Do you think this is something that will eventually be added to the PSTK?

Hey Matt,

 

Yes I would assume this will be fixed in a future PSTK as it's possible to set the browsable CIFS Share property via the REST API. I'll ping the dev team to put it on their radar.

 

/Matt

 

If this post resolved your issue, help others by selecting ACCEPT AS SOLUTION or adding a KUDO.

Sounds good.  Thanks, Matt.

Public