commit 6bf433c9a980b4fb3b2c7796b5d628c371b33694 Author: Laurence Horrocks-Barlow Date: Tue May 19 00:35:27 2026 +0100 Initial commit diff --git a/Config/gpfs-config.json b/Config/gpfs-config.json new file mode 100644 index 0000000..f4037b4 --- /dev/null +++ b/Config/gpfs-config.json @@ -0,0 +1,14 @@ +{ + "Profiles": { + "default": { + "Server": "gpfs-server.example.com", + "Port": 443, + "ApiVersion": "v2", + "UseSsl": true, + "SkipCertificateCheck": false, + "TimeoutSeconds": 30, + "Username": "admin" + } + }, + "ActiveProfile": "default" +} diff --git a/PSGpfsApi.psd1 b/PSGpfsApi.psd1 new file mode 100644 index 0000000..8fec9e3 Binary files /dev/null and b/PSGpfsApi.psd1 differ diff --git a/PSGpfsApi.psm1 b/PSGpfsApi.psm1 new file mode 100644 index 0000000..e38b6db --- /dev/null +++ b/PSGpfsApi.psm1 @@ -0,0 +1,82 @@ +$script:GpfsSession = $null + +$privateDir = Join-Path $PSScriptRoot 'Private' +$publicDir = Join-Path $PSScriptRoot 'Public' + +foreach ($file in Get-ChildItem -Path $privateDir -Filter '*.ps1') { + . $file.FullName +} + +foreach ($file in Get-ChildItem -Path $publicDir -Filter '*.ps1') { + . $file.FullName +} + +Export-ModuleMember -Function @( + 'Connect-GpfsServer' + 'Disconnect-GpfsServer' + + 'Get-GpfsCluster' + 'Get-GpfsClusterAuditLog' + 'Set-GpfsClusterAuditLog' + + 'Get-GpfsClusterConfig' + 'Set-GpfsClusterConfig' + + 'Get-GpfsConfiguration' + 'Set-GpfsConfiguration' + 'Import-GpfsConfiguration' + 'Export-GpfsConfiguration' + 'New-GpfsConfigurationProfile' + 'Select-GpfsConfigurationProfile' + + 'Get-GpfsNode' + 'Set-GpfsNode' + 'Remove-GpfsNode' + + 'Get-GpfsFilesystem' + 'New-GpfsFilesystem' + 'Set-GpfsFilesystem' + 'Remove-GpfsFilesystem' + + 'Get-GpfsFileset' + 'New-GpfsFileset' + 'Set-GpfsFileset' + 'Remove-GpfsFileset' + 'Register-GpfsFileset' + 'Unregister-GpfsFileset' + + 'Get-GpfsQuota' + 'New-GpfsQuota' + 'Set-GpfsQuota' + 'Remove-GpfsQuota' + + 'Get-GpfsSnapshot' + 'New-GpfsSnapshot' + 'Remove-GpfsSnapshot' + + 'Get-GpfsPolicy' + 'Set-GpfsPolicy' + + 'Get-GpfsPool' + 'New-GpfsPool' + 'Set-GpfsPool' + 'Remove-GpfsPool' + + 'Get-GpfsDisk' + 'Add-GpfsDisk' + 'Remove-GpfsDisk' + + 'Get-GpfsNfsExport' + 'New-GpfsNfsExport' + 'Set-GpfsNfsExport' + 'Remove-GpfsNfsExport' + + 'Get-GpfsSmbShare' + 'New-GpfsSmbShare' + 'Set-GpfsSmbShare' + 'Remove-GpfsSmbShare' + + 'Get-GpfsJob' + 'Remove-GpfsJob' + 'Wait-GpfsJob' +) diff --git a/Private/Invoke-GpfsApiRequest.ps1 b/Private/Invoke-GpfsApiRequest.ps1 new file mode 100644 index 0000000..402a99a --- /dev/null +++ b/Private/Invoke-GpfsApiRequest.ps1 @@ -0,0 +1,75 @@ +function Invoke-GpfsApiRequest { + [CmdletBinding()] + param( + [Parameter(Mandatory)] + [ValidateSet('GET', 'POST', 'PUT', 'DELETE', 'PATCH')] + [string]$Method, + + [Parameter(Mandatory)] + [string]$Endpoint, + + [hashtable]$Body, + + [hashtable]$QueryParameters + ) + + if (-not $script:GpfsSession) { + throw 'Not connected to a GPFS server. Run Connect-GpfsServer first.' + } + + $session = $script:GpfsSession + $uri = '{0}/scalemgmt/{1}/{2}' -f $session.BaseUrl, $session.ApiVersion, $Endpoint.TrimStart('/') + + if ($QueryParameters -and $QueryParameters.Count -gt 0) { + $queryParts = $QueryParameters.GetEnumerator() | ForEach-Object { + '{0}={1}' -f $_.Key, [uri]::EscapeDataString($_.Value.ToString()) + } + $uri = '{0}?{1}' -f $uri, ($queryParts -join '&') + } + + $params = @{ + Method = $Method + Uri = $uri + Headers = $session.Headers + ContentType = 'application/json' + TimeoutSec = $session.TimeoutSeconds + ErrorAction = 'Stop' + } + + if ($session.SkipCertificateCheck) { + $params['SkipCertificateCheck'] = $true + } + + if ($Body -and $Body.Count -gt 0) { + $params['Body'] = $Body | ConvertTo-Json -Depth 20 + } + + try { + $response = Invoke-RestMethod @params + return $response + } + catch { + $statusCode = $null + $detail = $_.ErrorDetails.Message + + if ($_.Exception.Response) { + $statusCode = [int]$_.Exception.Response.StatusCode + } + + $msg = if ($statusCode) { "GPFS API error (HTTP $statusCode)" } else { 'GPFS API error' } + if ($detail) { + try { + $parsed = $detail | ConvertFrom-Json + $msg = '{0}: {1}' -f $msg, $parsed.status.message + } + catch { + $msg = '{0}: {1}' -f $msg, $detail + } + } + else { + $msg = '{0}: {1}' -f $msg, $_.Exception.Message + } + + throw $msg + } +} diff --git a/Public/Connect-GpfsServer.ps1 b/Public/Connect-GpfsServer.ps1 new file mode 100644 index 0000000..8a0bb44 --- /dev/null +++ b/Public/Connect-GpfsServer.ps1 @@ -0,0 +1,80 @@ +function Connect-GpfsServer { + [CmdletBinding(DefaultParameterSetName = 'Credential')] + param( + [Parameter(Mandatory, Position = 0)] + [string]$Server, + + [Parameter()] + [int]$Port = 443, + + [Parameter()] + [ValidateSet('v2')] + [string]$ApiVersion = 'v2', + + [Parameter(Mandatory, ParameterSetName = 'Credential')] + [PSCredential]$Credential, + + [Parameter(Mandatory, ParameterSetName = 'UserPass')] + [string]$Username, + + [Parameter(Mandatory, ParameterSetName = 'UserPass')] + [SecureString]$Password, + + [Parameter()] + [switch]$UseSsl, + + [Parameter()] + [switch]$SkipCertificateCheck, + + [Parameter()] + [int]$TimeoutSeconds = 30, + + [Parameter()] + [switch]$PassThru + ) + + if ($PSCmdlet.ParameterSetName -eq 'UserPass') { + $Credential = [PSCredential]::new($Username, $Password) + } + + $protocol = if ($UseSsl) { 'https' } else { 'https' } + $baseUrl = '{0}://{1}:{2}' -f $protocol, $Server, $Port + + $plainPass = $Credential.GetNetworkCredential().Password + $credBytes = [System.Text.Encoding]::UTF8.GetBytes('{0}:{1}' -f $Credential.UserName, $plainPass) + $encodedCred = [Convert]::ToBase64String($credBytes) + + $script:GpfsSession = @{ + Server = $Server + Port = $Port + BaseUrl = $baseUrl + ApiVersion = $ApiVersion + SkipCertificateCheck = $SkipCertificateCheck.IsPresent + TimeoutSeconds = $TimeoutSeconds + Headers = @{ + Authorization = "Basic $encodedCred" + Accept = 'application/json' + } + } + + try { + $cluster = Invoke-GpfsApiRequest -Method GET -Endpoint 'cluster' + Write-Verbose "Connected to GPFS cluster: $($cluster.cluster.clusterName)" + } + catch { + $script:GpfsSession = $null + throw "Failed to connect to GPFS server '$Server': $_" + } + + if ($PassThru) { + [PSCustomObject]@{ + Server = $Server + Port = $Port + ApiVersion = $ApiVersion + Connected = $true + } + } + else { + Write-Host "Connected to GPFS server: $Server ($ApiVersion)" -ForegroundColor Green + } +} diff --git a/Public/Disconnect-GpfsServer.ps1 b/Public/Disconnect-GpfsServer.ps1 new file mode 100644 index 0000000..d223057 --- /dev/null +++ b/Public/Disconnect-GpfsServer.ps1 @@ -0,0 +1,13 @@ +function Disconnect-GpfsServer { + [CmdletBinding()] + param() + + if (-not $script:GpfsSession) { + Write-Warning 'No active GPFS session.' + return + } + + $server = $script:GpfsSession.Server + $script:GpfsSession = $null + Write-Host "Disconnected from GPFS server: $server" -ForegroundColor Yellow +} diff --git a/Public/GpfsCluster.ps1 b/Public/GpfsCluster.ps1 new file mode 100644 index 0000000..cebd128 --- /dev/null +++ b/Public/GpfsCluster.ps1 @@ -0,0 +1,25 @@ +function Get-GpfsCluster { + [CmdletBinding()] + param() + + Invoke-GpfsApiRequest -Method GET -Endpoint 'cluster' +} + +function Get-GpfsClusterAuditLog { + [CmdletBinding()] + param() + + Invoke-GpfsApiRequest -Method GET -Endpoint 'cluster/auditlog' +} + +function Set-GpfsClusterAuditLog { + [CmdletBinding(SupportsShouldProcess)] + param( + [Parameter(Mandatory)] + [hashtable]$Settings + ) + + if ($PSCmdlet.ShouldProcess('cluster audit log', 'Update')) { + Invoke-GpfsApiRequest -Method PUT -Endpoint 'cluster/auditlog' -Body $Settings + } +} diff --git a/Public/GpfsConfig.ps1 b/Public/GpfsConfig.ps1 new file mode 100644 index 0000000..7efdbd2 --- /dev/null +++ b/Public/GpfsConfig.ps1 @@ -0,0 +1,18 @@ +function Get-GpfsClusterConfig { + [CmdletBinding()] + param() + + Invoke-GpfsApiRequest -Method GET -Endpoint 'config' +} + +function Set-GpfsClusterConfig { + [CmdletBinding(SupportsShouldProcess)] + param( + [Parameter(Mandatory)] + [hashtable]$Settings + ) + + if ($PSCmdlet.ShouldProcess('cluster configuration', 'Update')) { + Invoke-GpfsApiRequest -Method PUT -Endpoint 'config' -Body $Settings + } +} diff --git a/Public/GpfsConfiguration.ps1 b/Public/GpfsConfiguration.ps1 new file mode 100644 index 0000000..711328c --- /dev/null +++ b/Public/GpfsConfiguration.ps1 @@ -0,0 +1,228 @@ +function Get-GpfsConfiguration { + [CmdletBinding()] + param( + [Parameter()] + [string]$Path = (Join-Path $env:USERPROFILE '.PSGpfsApi\config.json'), + + [Parameter()] + [string]$Profile + ) + + if (-not (Test-Path $Path)) { + throw "Configuration file not found: $Path" + } + + $config = Get-Content $Path -Raw | ConvertFrom-Json + + if ($Profile) { + $profileObj = $config.Profiles.$Profile + if (-not $profileObj) { + throw "Profile '$Profile' not found in configuration." + } + return $profileObj + } + + return $config +} + +function Set-GpfsConfiguration { + [CmdletBinding(SupportsShouldProcess)] + param( + [Parameter(Mandatory)] + [string]$ProfileName, + + [Parameter(Mandatory)] + [string]$Server, + + [Parameter()] + [int]$Port = 443, + + [Parameter()] + [ValidateSet('v2')] + [string]$ApiVersion = 'v2', + + [Parameter()] + [bool]$UseSsl = $true, + + [Parameter()] + [bool]$SkipCertificateCheck = $false, + + [Parameter()] + [int]$TimeoutSeconds = 30, + + [Parameter()] + [string]$Username, + + [Parameter()] + [string]$Path = (Join-Path $env:USERPROFILE '.PSGpfsApi\config.json'), + + [Parameter()] + [switch]$SetActive + ) + + $dir = Split-Path $Path -Parent + if (-not (Test-Path $dir)) { + New-Item -ItemType Directory -Path $dir -Force | Out-Null + } + + if (Test-Path $Path) { + $config = Get-Content $Path -Raw | ConvertFrom-Json + } + else { + $config = [PSCustomObject]@{ + Profiles = [PSCustomObject]@{} + ActiveProfile = 'default' + } + } + + $profileData = [PSCustomObject]@{ + Server = $Server + Port = $Port + ApiVersion = $ApiVersion + UseSsl = $UseSsl + SkipCertificateCheck = $SkipCertificateCheck + TimeoutSeconds = $TimeoutSeconds + Username = $Username + } + + $config.Profiles | Add-Member -NotePropertyName $ProfileName -NotePropertyValue $profileData -Force + + if ($SetActive) { + $config.ActiveProfile = $ProfileName + } + + if ($PSCmdlet.ShouldProcess($Path, 'Write configuration')) { + $config | ConvertTo-Json -Depth 10 | Set-Content $Path -Encoding UTF8 + Write-Verbose "Configuration saved: $Path (profile: $ProfileName)" + } +} + +function Import-GpfsConfiguration { + [CmdletBinding()] + param( + [Parameter()] + [string]$Path = (Join-Path $env:USERPROFILE '.PSGpfsApi\config.json'), + + [Parameter()] + [string]$Profile, + + [Parameter(Mandatory)] + [PSCredential]$Credential, + + [Parameter()] + [switch]$SkipCertificateCheck + ) + + if (-not (Test-Path $Path)) { + throw "Configuration file not found: $Path" + } + + $config = Get-Content $Path -Raw | ConvertFrom-Json + $profileName = if ($Profile) { $Profile } else { $config.ActiveProfile } + $profileObj = $config.Profiles.$profileName + + if (-not $profileObj) { + throw "Profile '$profileName' not found in configuration." + } + + $connectParams = @{ + Server = $profileObj.Server + Port = $profileObj.Port + ApiVersion = $profileObj.ApiVersion + TimeoutSeconds = $profileObj.TimeoutSeconds + Credential = $Credential + } + + if ($profileObj.UseSsl) { + $connectParams['UseSsl'] = $true + } + + if ($profileObj.SkipCertificateCheck -or $SkipCertificateCheck) { + $connectParams['SkipCertificateCheck'] = $true + } + + Connect-GpfsServer @connectParams +} + +function Export-GpfsConfiguration { + [CmdletBinding(SupportsShouldProcess)] + param( + [Parameter(Mandatory)] + [string]$Path + ) + + $defaultPath = Join-Path $env:USERPROFILE '.PSGpfsApi\config.json' + + if (-not (Test-Path $defaultPath)) { + throw "No configuration found at default path: $defaultPath" + } + + if ($PSCmdlet.ShouldProcess($Path, 'Export configuration')) { + Copy-Item -Path $defaultPath -Destination $Path -Force + Write-Verbose "Configuration exported to: $Path" + } +} + +function New-GpfsConfigurationProfile { + [CmdletBinding()] + param( + [Parameter(Mandatory)] + [string]$Name, + + [Parameter(Mandatory)] + [string]$Server, + + [Parameter()] + [int]$Port = 443, + + [Parameter()] + [string]$Username, + + [Parameter()] + [bool]$SkipCertificateCheck = $false, + + [Parameter()] + [switch]$SetActive + ) + + $setParams = @{ + ProfileName = $Name + Server = $Server + Port = $Port + SkipCertificateCheck = $SkipCertificateCheck + SetActive = $SetActive + } + + if ($Username) { + $setParams['Username'] = $Username + } + + Set-GpfsConfiguration @setParams +} + +function Select-GpfsConfigurationProfile { + [CmdletBinding(SupportsShouldProcess)] + param( + [Parameter(Mandatory, Position = 0)] + [string]$Profile, + + [Parameter()] + [string]$Path = (Join-Path $env:USERPROFILE '.PSGpfsApi\config.json') + ) + + if (-not (Test-Path $Path)) { + throw "Configuration file not found: $Path" + } + + $config = Get-Content $Path -Raw | ConvertFrom-Json + + if (-not $config.Profiles.$Profile) { + throw "Profile '$Profile' not found in configuration." + } + + if ($PSCmdlet.ShouldProcess($Profile, 'Set active profile')) { + $config.ActiveProfile = $Profile + $config | ConvertTo-Json -Depth 10 | Set-Content $Path -Encoding UTF8 + Write-Verbose "Active profile set to: $Profile" + } +} diff --git a/Public/GpfsDisk.ps1 b/Public/GpfsDisk.ps1 new file mode 100644 index 0000000..b032b6a --- /dev/null +++ b/Public/GpfsDisk.ps1 @@ -0,0 +1,47 @@ +function Get-GpfsDisk { + [CmdletBinding(DefaultParameterSetName = 'All')] + param( + [Parameter(Mandatory, Position = 0)] + [string]$FilesystemName, + + [Parameter(Mandatory, ParameterSetName = 'ByName', Position = 1)] + [string]$DiskName + ) + + if ($PSCmdlet.ParameterSetName -eq 'ByName') { + Invoke-GpfsApiRequest -Method GET -Endpoint "filesystems/$FilesystemName/disks/$DiskName" + } + else { + Invoke-GpfsApiRequest -Method GET -Endpoint "filesystems/$FilesystemName/disks" + } +} + +function Add-GpfsDisk { + [CmdletBinding(SupportsShouldProcess)] + param( + [Parameter(Mandatory, Position = 0)] + [string]$FilesystemName, + + [Parameter(Mandatory)] + [hashtable]$Settings + ) + + if ($PSCmdlet.ShouldProcess($FilesystemName, 'Add disk')) { + Invoke-GpfsApiRequest -Method POST -Endpoint "filesystems/$FilesystemName/disks" -Body $Settings + } +} + +function Remove-GpfsDisk { + [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High')] + param( + [Parameter(Mandatory, Position = 0)] + [string]$FilesystemName, + + [Parameter(Mandatory, Position = 1)] + [string]$DiskName + ) + + if ($PSCmdlet.ShouldProcess($DiskName, 'Remove disk')) { + Invoke-GpfsApiRequest -Method DELETE -Endpoint "filesystems/$FilesystemName/disks/$DiskName" + } +} diff --git a/Public/GpfsFileset.ps1 b/Public/GpfsFileset.ps1 new file mode 100644 index 0000000..98a251c --- /dev/null +++ b/Public/GpfsFileset.ps1 @@ -0,0 +1,98 @@ +function Get-GpfsFileset { + [CmdletBinding(DefaultParameterSetName = 'All')] + param( + [Parameter(Mandatory, Position = 0)] + [string]$FilesystemName, + + [Parameter(Mandatory, ParameterSetName = 'ByName', Position = 1)] + [string]$FilesetName + ) + + if ($PSCmdlet.ParameterSetName -eq 'ByName') { + Invoke-GpfsApiRequest -Method GET -Endpoint "filesystems/$FilesystemName/filesets/$FilesetName" + } + else { + Invoke-GpfsApiRequest -Method GET -Endpoint "filesystems/$FilesystemName/filesets" + } +} + +function New-GpfsFileset { + [CmdletBinding(SupportsShouldProcess)] + param( + [Parameter(Mandatory, Position = 0)] + [string]$FilesystemName, + + [Parameter(Mandatory)] + [hashtable]$Settings + ) + + if ($PSCmdlet.ShouldProcess($FilesystemName, 'Create fileset')) { + Invoke-GpfsApiRequest -Method POST -Endpoint "filesystems/$FilesystemName/filesets" -Body $Settings + } +} + +function Set-GpfsFileset { + [CmdletBinding(SupportsShouldProcess)] + param( + [Parameter(Mandatory, Position = 0)] + [string]$FilesystemName, + + [Parameter(Mandatory, Position = 1)] + [string]$FilesetName, + + [Parameter(Mandatory)] + [hashtable]$Settings + ) + + if ($PSCmdlet.ShouldProcess($FilesetName, 'Update fileset')) { + Invoke-GpfsApiRequest -Method PUT -Endpoint "filesystems/$FilesystemName/filesets/$FilesetName" -Body $Settings + } +} + +function Remove-GpfsFileset { + [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High')] + param( + [Parameter(Mandatory, Position = 0)] + [string]$FilesystemName, + + [Parameter(Mandatory, Position = 1)] + [string]$FilesetName + ) + + if ($PSCmdlet.ShouldProcess($FilesetName, 'Remove fileset')) { + Invoke-GpfsApiRequest -Method DELETE -Endpoint "filesystems/$FilesystemName/filesets/$FilesetName" + } +} + +function Register-GpfsFileset { + [CmdletBinding(SupportsShouldProcess)] + param( + [Parameter(Mandatory, Position = 0)] + [string]$FilesystemName, + + [Parameter(Mandatory, Position = 1)] + [string]$FilesetName, + + [Parameter(Mandatory)] + [hashtable]$LinkSettings + ) + + if ($PSCmdlet.ShouldProcess($FilesetName, 'Link fileset')) { + Invoke-GpfsApiRequest -Method PUT -Endpoint "filesystems/$FilesystemName/filesets/$FilesetName/link" -Body $LinkSettings + } +} + +function Unregister-GpfsFileset { + [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High')] + param( + [Parameter(Mandatory, Position = 0)] + [string]$FilesystemName, + + [Parameter(Mandatory, Position = 1)] + [string]$FilesetName + ) + + if ($PSCmdlet.ShouldProcess($FilesetName, 'Unlink fileset')) { + Invoke-GpfsApiRequest -Method DELETE -Endpoint "filesystems/$FilesystemName/filesets/$FilesetName/link" + } +} diff --git a/Public/GpfsFilesystem.ps1 b/Public/GpfsFilesystem.ps1 new file mode 100644 index 0000000..8c3c43d --- /dev/null +++ b/Public/GpfsFilesystem.ps1 @@ -0,0 +1,53 @@ +function Get-GpfsFilesystem { + [CmdletBinding(DefaultParameterSetName = 'All')] + param( + [Parameter(Mandatory, ParameterSetName = 'ByName', Position = 0)] + [string]$FilesystemName + ) + + if ($PSCmdlet.ParameterSetName -eq 'ByName') { + Invoke-GpfsApiRequest -Method GET -Endpoint "filesystems/$FilesystemName" + } + else { + Invoke-GpfsApiRequest -Method GET -Endpoint 'filesystems' + } +} + +function New-GpfsFilesystem { + [CmdletBinding(SupportsShouldProcess)] + param( + [Parameter(Mandatory)] + [hashtable]$Settings + ) + + if ($PSCmdlet.ShouldProcess('filesystem', 'Create')) { + Invoke-GpfsApiRequest -Method POST -Endpoint 'filesystems' -Body $Settings + } +} + +function Set-GpfsFilesystem { + [CmdletBinding(SupportsShouldProcess)] + param( + [Parameter(Mandatory, Position = 0)] + [string]$FilesystemName, + + [Parameter(Mandatory)] + [hashtable]$Settings + ) + + if ($PSCmdlet.ShouldProcess($FilesystemName, 'Update filesystem')) { + Invoke-GpfsApiRequest -Method PUT -Endpoint "filesystems/$FilesystemName" -Body $Settings + } +} + +function Remove-GpfsFilesystem { + [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High')] + param( + [Parameter(Mandatory, Position = 0)] + [string]$FilesystemName + ) + + if ($PSCmdlet.ShouldProcess($FilesystemName, 'Remove filesystem')) { + Invoke-GpfsApiRequest -Method DELETE -Endpoint "filesystems/$FilesystemName" + } +} diff --git a/Public/GpfsJob.ps1 b/Public/GpfsJob.ps1 new file mode 100644 index 0000000..401131a --- /dev/null +++ b/Public/GpfsJob.ps1 @@ -0,0 +1,67 @@ +function Get-GpfsJob { + [CmdletBinding(DefaultParameterSetName = 'All')] + param( + [Parameter(Mandatory, ParameterSetName = 'ById', Position = 0)] + [string]$JobId, + + [Parameter(ParameterSetName = 'All')] + [ValidateSet('RUNNING', 'COMPLETED', 'FAILED', 'CANCELLED')] + [string]$Status + ) + + if ($PSCmdlet.ParameterSetName -eq 'ById') { + Invoke-GpfsApiRequest -Method GET -Endpoint "jobs/$JobId" + } + else { + $params = @{ Method = 'GET'; Endpoint = 'jobs' } + if ($Status) { + $params['QueryParameters'] = @{ status = $Status } + } + Invoke-GpfsApiRequest @params + } +} + +function Remove-GpfsJob { + [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'Medium')] + param( + [Parameter(Mandatory, Position = 0)] + [string]$JobId + ) + + if ($PSCmdlet.ShouldProcess($JobId, 'Remove job')) { + Invoke-GpfsApiRequest -Method DELETE -Endpoint "jobs/$JobId" + } +} + +function Wait-GpfsJob { + [CmdletBinding()] + param( + [Parameter(Mandatory, Position = 0)] + [string]$JobId, + + [Parameter()] + [int]$PollingIntervalSeconds = 5, + + [Parameter()] + [int]$TimeoutSeconds = 300 + ) + + $start = Get-Date + + do { + Start-Sleep -Seconds $PollingIntervalSeconds + + $job = Invoke-GpfsApiRequest -Method GET -Endpoint "jobs/$JobId" + $currentStatus = $job.jobs[0].status + + Write-Verbose "Job $JobId status: $currentStatus" + + if ($currentStatus -in @('COMPLETED', 'FAILED', 'CANCELLED')) { + return $job + } + + if (((Get-Date) - $start).TotalSeconds -ge $TimeoutSeconds) { + throw "Timed out waiting for job $JobId after $TimeoutSeconds seconds." + } + } while ($true) +} diff --git a/Public/GpfsNfsExport.ps1 b/Public/GpfsNfsExport.ps1 new file mode 100644 index 0000000..f542ad6 --- /dev/null +++ b/Public/GpfsNfsExport.ps1 @@ -0,0 +1,53 @@ +function Get-GpfsNfsExport { + [CmdletBinding(DefaultParameterSetName = 'All')] + param( + [Parameter(Mandatory, ParameterSetName = 'ById', Position = 0)] + [string]$ExportId + ) + + if ($PSCmdlet.ParameterSetName -eq 'ById') { + Invoke-GpfsApiRequest -Method GET -Endpoint "nfs/exports/$ExportId" + } + else { + Invoke-GpfsApiRequest -Method GET -Endpoint 'nfs/exports' + } +} + +function New-GpfsNfsExport { + [CmdletBinding(SupportsShouldProcess)] + param( + [Parameter(Mandatory)] + [hashtable]$Settings + ) + + if ($PSCmdlet.ShouldProcess('NFS export', 'Create')) { + Invoke-GpfsApiRequest -Method POST -Endpoint 'nfs/exports' -Body $Settings + } +} + +function Set-GpfsNfsExport { + [CmdletBinding(SupportsShouldProcess)] + param( + [Parameter(Mandatory, Position = 0)] + [string]$ExportId, + + [Parameter(Mandatory)] + [hashtable]$Settings + ) + + if ($PSCmdlet.ShouldProcess($ExportId, 'Update NFS export')) { + Invoke-GpfsApiRequest -Method PUT -Endpoint "nfs/exports/$ExportId" -Body $Settings + } +} + +function Remove-GpfsNfsExport { + [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High')] + param( + [Parameter(Mandatory, Position = 0)] + [string]$ExportId + ) + + if ($PSCmdlet.ShouldProcess($ExportId, 'Remove NFS export')) { + Invoke-GpfsApiRequest -Method DELETE -Endpoint "nfs/exports/$ExportId" + } +} diff --git a/Public/GpfsNode.ps1 b/Public/GpfsNode.ps1 new file mode 100644 index 0000000..d62ee2d --- /dev/null +++ b/Public/GpfsNode.ps1 @@ -0,0 +1,41 @@ +function Get-GpfsNode { + [CmdletBinding(DefaultParameterSetName = 'All')] + param( + [Parameter(Mandatory, ParameterSetName = 'ByName', Position = 0)] + [string]$NodeName + ) + + if ($PSCmdlet.ParameterSetName -eq 'ByName') { + Invoke-GpfsApiRequest -Method GET -Endpoint "nodes/$NodeName" + } + else { + Invoke-GpfsApiRequest -Method GET -Endpoint 'nodes' + } +} + +function Set-GpfsNode { + [CmdletBinding(SupportsShouldProcess)] + param( + [Parameter(Mandatory, Position = 0)] + [string]$NodeName, + + [Parameter(Mandatory)] + [hashtable]$Settings + ) + + if ($PSCmdlet.ShouldProcess($NodeName, 'Update node')) { + Invoke-GpfsApiRequest -Method PUT -Endpoint "nodes/$NodeName" -Body $Settings + } +} + +function Remove-GpfsNode { + [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High')] + param( + [Parameter(Mandatory, Position = 0)] + [string]$NodeName + ) + + if ($PSCmdlet.ShouldProcess($NodeName, 'Remove node')) { + Invoke-GpfsApiRequest -Method DELETE -Endpoint "nodes/$NodeName" + } +} diff --git a/Public/GpfsPolicy.ps1 b/Public/GpfsPolicy.ps1 new file mode 100644 index 0000000..fb1faab --- /dev/null +++ b/Public/GpfsPolicy.ps1 @@ -0,0 +1,24 @@ +function Get-GpfsPolicy { + [CmdletBinding()] + param( + [Parameter(Mandatory, Position = 0)] + [string]$FilesystemName + ) + + Invoke-GpfsApiRequest -Method GET -Endpoint "filesystems/$FilesystemName/policies" +} + +function Set-GpfsPolicy { + [CmdletBinding(SupportsShouldProcess)] + param( + [Parameter(Mandatory, Position = 0)] + [string]$FilesystemName, + + [Parameter(Mandatory)] + [hashtable]$Settings + ) + + if ($PSCmdlet.ShouldProcess($FilesystemName, 'Apply policy')) { + Invoke-GpfsApiRequest -Method PUT -Endpoint "filesystems/$FilesystemName/policies" -Body $Settings + } +} diff --git a/Public/GpfsPool.ps1 b/Public/GpfsPool.ps1 new file mode 100644 index 0000000..a7662bb --- /dev/null +++ b/Public/GpfsPool.ps1 @@ -0,0 +1,65 @@ +function Get-GpfsPool { + [CmdletBinding(DefaultParameterSetName = 'All')] + param( + [Parameter(Mandatory, Position = 0)] + [string]$FilesystemName, + + [Parameter(Mandatory, ParameterSetName = 'ByName', Position = 1)] + [string]$PoolName + ) + + if ($PSCmdlet.ParameterSetName -eq 'ByName') { + Invoke-GpfsApiRequest -Method GET -Endpoint "filesystems/$FilesystemName/pools/$PoolName" + } + else { + Invoke-GpfsApiRequest -Method GET -Endpoint "filesystems/$FilesystemName/pools" + } +} + +function New-GpfsPool { + [CmdletBinding(SupportsShouldProcess)] + param( + [Parameter(Mandatory, Position = 0)] + [string]$FilesystemName, + + [Parameter(Mandatory)] + [hashtable]$Settings + ) + + if ($PSCmdlet.ShouldProcess($FilesystemName, 'Create pool')) { + Invoke-GpfsApiRequest -Method POST -Endpoint "filesystems/$FilesystemName/pools" -Body $Settings + } +} + +function Set-GpfsPool { + [CmdletBinding(SupportsShouldProcess)] + param( + [Parameter(Mandatory, Position = 0)] + [string]$FilesystemName, + + [Parameter(Mandatory, Position = 1)] + [string]$PoolName, + + [Parameter(Mandatory)] + [hashtable]$Settings + ) + + if ($PSCmdlet.ShouldProcess($PoolName, 'Update pool')) { + Invoke-GpfsApiRequest -Method PUT -Endpoint "filesystems/$FilesystemName/pools/$PoolName" -Body $Settings + } +} + +function Remove-GpfsPool { + [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High')] + param( + [Parameter(Mandatory, Position = 0)] + [string]$FilesystemName, + + [Parameter(Mandatory, Position = 1)] + [string]$PoolName + ) + + if ($PSCmdlet.ShouldProcess($PoolName, 'Remove pool')) { + Invoke-GpfsApiRequest -Method DELETE -Endpoint "filesystems/$FilesystemName/pools/$PoolName" + } +} diff --git a/Public/GpfsQuota.ps1 b/Public/GpfsQuota.ps1 new file mode 100644 index 0000000..2024b5f --- /dev/null +++ b/Public/GpfsQuota.ps1 @@ -0,0 +1,72 @@ +function Get-GpfsQuota { + [CmdletBinding()] + param( + [Parameter(Mandatory, Position = 0)] + [string]$FilesystemName, + + [Parameter()] + [ValidateSet('USR', 'GRP', 'FILESET')] + [string]$QuotaType, + + [Parameter()] + [string]$ObjectName, + + [Parameter()] + [string]$FilesetName + ) + + $query = @{} + if ($QuotaType) { $query['quotaType'] = $QuotaType } + if ($ObjectName) { $query['objectName'] = $ObjectName } + if ($FilesetName){ $query['filesetName']= $FilesetName } + + $params = @{ Method = 'GET'; Endpoint = "filesystems/$FilesystemName/quotas" } + if ($query.Count -gt 0) { $params['QueryParameters'] = $query } + + Invoke-GpfsApiRequest @params +} + +function New-GpfsQuota { + [CmdletBinding(SupportsShouldProcess)] + param( + [Parameter(Mandatory, Position = 0)] + [string]$FilesystemName, + + [Parameter(Mandatory)] + [hashtable]$Settings + ) + + if ($PSCmdlet.ShouldProcess($FilesystemName, 'Create quota')) { + Invoke-GpfsApiRequest -Method POST -Endpoint "filesystems/$FilesystemName/quotas" -Body $Settings + } +} + +function Set-GpfsQuota { + [CmdletBinding(SupportsShouldProcess)] + param( + [Parameter(Mandatory, Position = 0)] + [string]$FilesystemName, + + [Parameter(Mandatory)] + [hashtable]$Settings + ) + + if ($PSCmdlet.ShouldProcess($FilesystemName, 'Update quota')) { + Invoke-GpfsApiRequest -Method PUT -Endpoint "filesystems/$FilesystemName/quotas" -Body $Settings + } +} + +function Remove-GpfsQuota { + [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High')] + param( + [Parameter(Mandatory, Position = 0)] + [string]$FilesystemName, + + [Parameter(Mandatory)] + [hashtable]$Filter + ) + + if ($PSCmdlet.ShouldProcess($FilesystemName, 'Remove quota')) { + Invoke-GpfsApiRequest -Method DELETE -Endpoint "filesystems/$FilesystemName/quotas" -Body $Filter + } +} diff --git a/Public/GpfsSmbShare.ps1 b/Public/GpfsSmbShare.ps1 new file mode 100644 index 0000000..1733966 --- /dev/null +++ b/Public/GpfsSmbShare.ps1 @@ -0,0 +1,53 @@ +function Get-GpfsSmbShare { + [CmdletBinding(DefaultParameterSetName = 'All')] + param( + [Parameter(Mandatory, ParameterSetName = 'ByName', Position = 0)] + [string]$ShareName + ) + + if ($PSCmdlet.ParameterSetName -eq 'ByName') { + Invoke-GpfsApiRequest -Method GET -Endpoint "smb/shares/$ShareName" + } + else { + Invoke-GpfsApiRequest -Method GET -Endpoint 'smb/shares' + } +} + +function New-GpfsSmbShare { + [CmdletBinding(SupportsShouldProcess)] + param( + [Parameter(Mandatory)] + [hashtable]$Settings + ) + + if ($PSCmdlet.ShouldProcess('SMB share', 'Create')) { + Invoke-GpfsApiRequest -Method POST -Endpoint 'smb/shares' -Body $Settings + } +} + +function Set-GpfsSmbShare { + [CmdletBinding(SupportsShouldProcess)] + param( + [Parameter(Mandatory, Position = 0)] + [string]$ShareName, + + [Parameter(Mandatory)] + [hashtable]$Settings + ) + + if ($PSCmdlet.ShouldProcess($ShareName, 'Update SMB share')) { + Invoke-GpfsApiRequest -Method PUT -Endpoint "smb/shares/$ShareName" -Body $Settings + } +} + +function Remove-GpfsSmbShare { + [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High')] + param( + [Parameter(Mandatory, Position = 0)] + [string]$ShareName + ) + + if ($PSCmdlet.ShouldProcess($ShareName, 'Remove SMB share')) { + Invoke-GpfsApiRequest -Method DELETE -Endpoint "smb/shares/$ShareName" + } +} diff --git a/Public/GpfsSnapshot.ps1 b/Public/GpfsSnapshot.ps1 new file mode 100644 index 0000000..be671e4 --- /dev/null +++ b/Public/GpfsSnapshot.ps1 @@ -0,0 +1,54 @@ +function Get-GpfsSnapshot { + [CmdletBinding(DefaultParameterSetName = 'All')] + param( + [Parameter(Mandatory, Position = 0)] + [string]$FilesystemName, + + [Parameter(Mandatory, ParameterSetName = 'ByName', Position = 1)] + [string]$SnapshotName, + + [Parameter(ParameterSetName = 'All')] + [string]$FilesetName + ) + + if ($PSCmdlet.ParameterSetName -eq 'ByName') { + Invoke-GpfsApiRequest -Method GET -Endpoint "filesystems/$FilesystemName/snapshots/$SnapshotName" + } + else { + $params = @{ Method = 'GET'; Endpoint = "filesystems/$FilesystemName/snapshots" } + if ($FilesetName) { + $params['QueryParameters'] = @{ filesetName = $FilesetName } + } + Invoke-GpfsApiRequest @params + } +} + +function New-GpfsSnapshot { + [CmdletBinding(SupportsShouldProcess)] + param( + [Parameter(Mandatory, Position = 0)] + [string]$FilesystemName, + + [Parameter(Mandatory)] + [hashtable]$Settings + ) + + if ($PSCmdlet.ShouldProcess($FilesystemName, 'Create snapshot')) { + Invoke-GpfsApiRequest -Method POST -Endpoint "filesystems/$FilesystemName/snapshots" -Body $Settings + } +} + +function Remove-GpfsSnapshot { + [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High')] + param( + [Parameter(Mandatory, Position = 0)] + [string]$FilesystemName, + + [Parameter(Mandatory, Position = 1)] + [string]$SnapshotName + ) + + if ($PSCmdlet.ShouldProcess($SnapshotName, 'Remove snapshot')) { + Invoke-GpfsApiRequest -Method DELETE -Endpoint "filesystems/$FilesystemName/snapshots/$SnapshotName" + } +}