Storage Virtual Machines (SVM) are the entity in clustered Data ONTAP which the storage consumer actually interacts with. As the name implies, they are a virtual entity, however they are not a virtual machine like you would expect. There are no CPU, RAM, or other cache assignments that must be made. Instead, we assign storage resources to the SVM, such as aggregates and data LIF(s), which the SVM then uses to provision FlexVols and make them available via the desired protocol.
In this post we will look at how to configure an SVM using PowerShell.
- Create an SVM
- Aggregate Access
- SVM DNS Service
- Configuring Data LIF(s)
- Configuring Protocols
Create an SVM
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
# create a new SVM $splat = @{ # a name for the SVM "Name" = $svmName; # the name of the root volume, easy to keep track of # by using the SVM name in the name of the root vol "RootVolume" = "$($svmName)_root"; # the aggregate to create the root volume on "RootVolumeAggregate" = $rootAggrName; # the NSS setting, use "file" if unsure "NameServerSwitch" = "file"; # will vary based on how you're accessing the volumes # unix = NFS, iSCSI, and/or FC/FCoE # ntfs = CIFS/SMB # mixed = all of the above "RootVolumeSecurityStyle" = "unix"; # language, C.UTF-8 is a good default if unsure "Language" = "C.UTF-8"; } New-NcVserver @splat |
Destroying SVMs can be a complex task, as all of the resources it uses must be removed first. Vidad Cosonock has created a script here that will automate removing an SVM, I highly recommend using that to simplify removing the SVM.
Aggregate Access
Limiting the aggregates that the SVM has access to can be beneficial when in a multitenant environment so that you can dedicate disks to specific tasks/customers. However, it can also be useful regardless of your use of mutlitenancy by preventing volumes from being created on root aggregates.
1 2 |
# show assigned aggregates (Get-NcVserver $svmName).AggrList |
Managing aggregate access is done by modifying the SVM properties. We can wrap that into functions to make it even easier:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
function Add-SvmAggrAccess { [CmdletBinding(SupportsShouldProcess=$true)] param( [parameter( Mandatory=$true, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true )] [System.String]$Vserver , [parameter( Mandatory=$true, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true )] [Alias('Name')] [System.String[]]$Aggregate ) process { # get the current aggr list $aggrList = (Get-NcVserver -Name $svmName).AggrList # add the new aggr to the list $aggrlist += $Aggregate if ($PSCmdlet.ShouldProcess($Vserver, "Adding aggregate $($Aggregate) to approved list")) { # update the assigned aggregate list Set-NcVserver -Name $Vserver -Aggregates $aggrList } } } function Remove-SvmAggrAccess { [CmdletBinding(SupportsShouldProcess=$true)] param( [parameter( Mandatory=$true, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true )] [System.String]$Vserver , [parameter( Mandatory=$true, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true )] [Alias('Name')] [System.String[]]$Aggregate ) process { # remove the aggr from the list of current aggrs $aggrlist = (Get-NcVserver -Name $svmName).AggrList | ?{ $_ -notin $Aggregate } if ($PSCmdlet.ShouldProcess( $Vserver, "Removing aggregate $($Aggregate) from approved list" )) { # update the assigned aggregate list Set-NcVserver -Name $Vserver -Aggregates $aggrList } } } |
Using these functions it’s now quite easy to modify the aggregates that an SVM has permission to use:
1 2 3 4 5 |
# add an aggregate to the SVM Get-NcVserver $svmName | Add-SvmAggrAccess $aggrName # remove an aggregate from the SVM's access Get-NcAggr $aggrName | Remove-SvmAggrAccess $svmName |
Finally, let’s add only non-root aggregates to the SVM:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
# get the root aggrs $rootAggrs = Get-NcVol | ?{ $_.VolumeStateAttributes.IsNodeRoot -eq $true } | %{ $_.Aggregate } # remove them from the access list Remove-SvmAggrAccess -Name $svmName -Aggregate $rootAggrs # get the non-root aggregates $nonRootAggrs = Get-NcAggr | ?{ $_.Name -notin $rootAggrs }).Name # add them to the access list Add-SvmAggrAccess -Name $svmName -Aggregate $nonRootAggrs |
SVM DNS Service
1 2 3 4 5 6 |
# configure new DNS Get-NcVserver $svmName | New-NcNetDns -Domains foo.bar,your.company -NameServers 8.8.8.8,8.8.4.4 # modify DNS configuration Get-NcVserver $svmName | Set-NcNetDns -Domains foo.bar -NameServers $ns1,$ns2 |
Configuring Data LIF(s)
Before we can enable data access protocols we need to have a way of accessing the data. NetApp uses logical network interfaces, known as LIFs, assigned to the SVM. Let’s look at creating LIFs for the different protocols:
- NFS / CIFS / SMB
12345678910111213141516171819202122# Splatting is a convenient way to keep parameters readable$splat = @{# I prefer a simple naming convention to quickly identify LIFs'Name' = "$($nodeName)_$($svmName)_FILE_$($instanceNum)";# where to create the LIF'Vserver' = $svmName;'Node' = $nodeName;'Port' = $portName;# the type of LIF'Role' = "data";# alternatively only one or the other can be provided'DataProtocols' = "nfs","cifs";# finally, the IP information'Address' = $ipAddress;'Netmask' = $subnetMask;}New-NcNetInterface @splat - iSCSI
123456789101112131415161718192021222324252627# for block based protocols we want to have one LIF per node so# that ALUA can work its magic. if you're using cDOT 8.3 and Subnets# then creating the LIFs is quite easyGet-NcNode | Foreach-Object {# create a LIF on each node$splat = @{# keep a nice and easy naming convention'Name' = "$($_.Node)_$($svmName)_ISCSI";# where to create the LIF'Vserver' = $svmName;'Node' = $_.Node;'Port' = $portName;# the type of LIF'Role' = "data";'DataProtocols' = "iscsi";# Using a subnet, ONTAP will allocate the IP address.# The gateway and subnet mask are provided when the# subnet is created, and the Broadcast Domain will# ensure that we can failover the LIF'Subnet' = $subnetName;}New-NcNetInterface @splat} - FC / FCoE
123456789101112131415161718192021222324# Like with iSCSI, we want to create an FCP / FCoE LIF# on each node in the clusterGet-NcNode | Foreach-Object {# create a LIF on each node$splat = @{# keep a nice and easy naming convention'Name' = "$($_.Node)_$($svmName)_FC";# where to create the LIF'Vserver' = $svmName;'Node' = $_.Node;'Port' = $portName;# the type of LIF'Role' = "data";# the protocol'DataProtocols' = "fcp";# for fcp WWPNs will be automatically generated}New-NcNetInterface @splat}
Configuring Procotols
A newly created SVM will not have any protocols assigned to it. Adding and configuring the protocols is a few simple commands.
- NFS
1234567891011121314151617# configuring the protocol is a bit different because there are# so many options we create an object and set the options there$nfsServiceConfig = Get-NcNfsService -Template# enable the nfs service$nfsServiceConfig.IsNfsAccessEnabled = $true# enable nfsv3$nfsServiceConfig.IsNfsv3Enabled = $true# disable nfsv2, v4.0, v4.1$nfsServiceConfig.IsNfsv2Enabled= $false$nfsServiceConfig.IsNfsv40Enabled = $false$nfsServiceConfig.IsNfsv41Enabled = $false# apply the configGet-NcVserver $svmName | Add-NcNfsService -Attributes $nfsServiceconfig - SMB / CIFS
123456# create the CIFS/SMB server and join it to the domainAdd-NcCifsServer -VserverContext $svmName `-Domain $domainName -AdminCredential (Get-Credential)# start CIFS/SMB serverGet-NcVserver $svmName | Start-NcCifsServer - iSCSI
12345# add the service to the SVMGet-NcVserver $svmName | Add-NcIscsiService# start the serviceGet-NcVerver $svmName | Enable-NcIscsi - FC / FCoE
12345# add the service to the SVMAdd-NcFcpService -VserverContext $svmName# start the serviceGet-NcVserver $svmName | Enable-NcFcp
Thank you for posting this. I think we need to get better at providing real world examples in the toolkit. I was scratching my head with my first NFS build on cDOT.
Hi Scott,
Thank you for reading! If there are other examples you’d like to see, please let me know…I’m always looking for use cases.
Andrew
Hi, I just started out using powershell with netapp. and was wondering how i would go about extending a volume with powershell.
Can I traverse all vservers in a CDoT cluster and run a command on each of them? How?
Hello Anindra,
Yes, you can. One way is to simply loop over them like this:
Hope that helps.
Andrew