Public/serviceoffering.ps1

function Get-CSServiceOffering {
    <#
    .SYNOPSIS
        Lists service offerings in CloudStack.
    
    .DESCRIPTION
        Retrieves a list of service offerings with optional filtering by ID, name,
        state, storage type, or other parameters.
    
    .PARAMETER Id
        Filter by service offering ID
    
    .PARAMETER Name
        Filter by service offering name (exact match)
    
    .PARAMETER Keyword
        Filter by keyword (partial match on name)
    
    .PARAMETER State
        Filter by state of the service offering. Defaults to 'Active'.
        If set to 'all' shows both Active & Inactive offerings.
    
    .PARAMETER IsSystem
        Filter for system VM offerings
    
    .PARAMETER StorageType
        The storage type of the service offering. Values are local and shared.
    
    .PARAMETER ZoneId
        Filter by zone ID
    
    .PARAMETER DomainId
        Filter by domain ID

    .PARAMETER Domain
        Filter by domain
    
    .PARAMETER CpuNumber
        Filter by CPU number that listed offerings must support
    
    .PARAMETER CpuSpeed
        Filter by CPU speed that listed offerings must support
    
    .PARAMETER Memory
        Filter by RAM memory that listed offering must support
    
    .PARAMETER SystemVmType
        The system VM type. Possible types are "consoleproxy",
        "secondarystoragevm" or "domainrouter"
    
    .PARAMETER ListAll
        If set to true - list resources that the caller is authorized to see.
        Default value is false.
    
    .EXAMPLE
        Get-CSServiceOffering
        Lists all active service offerings in your account
    
    .EXAMPLE
        Get-CSServiceOffering -Name "Medium Instance"
        Gets a specific service offering by name
    
    .EXAMPLE
        Get-CSServiceOffering -State all
        Lists all service offerings including inactive ones
    
    .EXAMPLE
        Get-CSServiceOffering -IsSystem $true -SystemVmType domainrouter
        Lists all domain router system VM offerings
    
    .EXAMPLE
        Get-CSServiceOffering -CpuNumber 4 -Memory 8192
        Lists offerings with 4 CPUs and 8GB RAM
    #>

    [CmdletBinding(DefaultParameterSetName='Default')]
    param(
        [Parameter(ParameterSetName='ById')]
        [string]$Id,
        
        [Parameter(ParameterSetName='ByName')]
        [string]$Name,
        
        [Parameter(ParameterSetName='Default')]
        [string]$Keyword,
        
        [Parameter(ParameterSetName='Default')]
        [string]$State,
        
        [Parameter(ParameterSetName='Default')]
        [bool]$IsSystem,
        
        [Parameter(ParameterSetName='Default')]
        [ValidateSet('local', 'shared')]
        [string]$StorageType,
        
        [Parameter(ParameterSetName='Default')]
        [string]$ZoneId,
        
        [Parameter(ParameterSetName='Default')]
        [string]$DomainId,
        
        [Parameter(ParameterSetName='Default')]
        [string]$Domain,

        [Parameter(ParameterSetName='Default')]
        [int]$CpuNumber,
        
        [Parameter(ParameterSetName='Default')]
        [int]$CpuSpeed,
        
        [Parameter(ParameterSetName='Default')]
        [int]$Memory,
        
        [Parameter(ParameterSetName='Default')]
        [ValidateSet('consoleproxy', 'secondarystoragevm', 'domainrouter')]
        [string]$SystemVmType,
        
        [Parameter(ParameterSetName='Default')]
        [switch]$ListAll
    )
    
    # Build parameters
    $apiParams = @{}
    
    if ($PSBoundParameters.ContainsKey('Id')) {
        $apiParams['id'] = $Id
    }
    
    if ($PSBoundParameters.ContainsKey('Name')) {
        $apiParams['name'] = $Name
    }
    
    if ($PSBoundParameters.ContainsKey('Keyword')) {
        $apiParams['keyword'] = $Keyword
    }
    
    if ($PSBoundParameters.ContainsKey('State')) {
        $apiParams['state'] = $State
    }
    
    if ($PSBoundParameters.ContainsKey('IsSystem')) {
        $apiParams['issystem'] = $IsSystem.ToString().ToLower()
    }
    
    if ($PSBoundParameters.ContainsKey('StorageType')) {
        $apiParams['storagetype'] = $StorageType
    }
    
    if ($PSBoundParameters.ContainsKey('ZoneId')) {
        $apiParams['zoneid'] = $ZoneId
    }
    
    if ($PSBoundParameters.ContainsKey('DomainId')) {
        $apiParams['domainid'] = $DomainId
    }

    if ($PSBoundParameters.ContainsKey('Domain')) {
        $apiParams['domain'] = $Domain
    }

    if ($PSBoundParameters.ContainsKey('CpuNumber')) {
        $apiParams['cpunumber'] = $CpuNumber
    }
    
    if ($PSBoundParameters.ContainsKey('CpuSpeed')) {
        $apiParams['cpuspeed'] = $CpuSpeed
    }
    
    if ($PSBoundParameters.ContainsKey('Memory')) {
        $apiParams['memory'] = $Memory
    }
    
    if ($PSBoundParameters.ContainsKey('SystemVmType')) {
        $apiParams['systemvmtype'] = $SystemVmType
    }
    
    if ($ListAll) {
        $apiParams['listall'] = 'true'
    }
    
    # Make the API call
    $response = Invoke-CSApiRequest -Command 'listServiceOfferings' -Parameters $apiParams
    Write-Verbose "API Parameters: $($apiParams | Out-String)"
    
    # Return the service offering list
    if ($response.listserviceofferingsresponse.serviceoffering) {
        return $response.listserviceofferingsresponse.serviceoffering
    }
    else {
        Write-Verbose "No service offerings found matching the criteria."
        return $null
    }
}

function New-CSServiceOffering {
    <#
    .SYNOPSIS
        Creates a service offering in CloudStack.
    
    .DESCRIPTION
        Creates a new compute service offering with specified CPU, memory,
        and other configuration options.
    
    .PARAMETER Name
        The name of the service offering (required)
    
    .PARAMETER DisplayText
        The display text of the service offering, defaults to Name if not specified
    
    .PARAMETER CpuNumber
        The CPU number of the service offering
    
    .PARAMETER CpuSpeed
        The CPU speed of the service offering in MHz
    
    .PARAMETER Memory
        The total memory of the service offering in MB
    
    .PARAMETER Customized
        Whether service offering size is custom or not
    
    .PARAMETER StorageType
        The storage type of the service offering. Values are local and shared.
    
    .PARAMETER OfferHA
        Whether the service offering supports HA
    
    .PARAMETER IsSystem
        Whether this is a system VM offering
    
    .PARAMETER SystemVmType
        The system VM type. Possible types are "domainrouter",
        "consoleproxy" and "secondarystoragevm"
    
    .PARAMETER HostTags
        The host tag for this service offering
    
    .PARAMETER StorageTags
        The tags for this service offering (comma-separated)
    
    .PARAMETER NetworkRate
        Data transfer rate in megabits per second allowed
    
    .PARAMETER DynamicScalingEnabled
        Whether virtual machine needs to be dynamically scalable of cpu or memory
    
    .PARAMETER RootDiskSize
        The Root disk size in GB
    
    .PARAMETER LimitCpuUse
        Restrict the CPU usage to committed service offering
    
    .PARAMETER IsVolatile
        True if the virtual machine needs to be volatile (root disk destroyed on reboot)
    
    .PARAMETER ProvisioningType
        Provisioning type used to create volumes. Valid values are thin, sparse, fat.
    
    .PARAMETER DiskOfferingId
        The ID of the disk offering to which service offering should be mapped
    
    .PARAMETER ZoneId
        The ID of the containing zone(s), null for public offerings
    
    .PARAMETER DomainId
        The ID of the containing domain(s), null for public offerings

    .PARAMETER Domain
        The name of the containing domain(s), null for public offerings
    
    .EXAMPLE
        New-CSServiceOffering -Name "Small" -CpuNumber 1 -CpuSpeed 1000 -Memory 1024
        Creates a basic service offering with 1 CPU, 1GHz, and 1GB RAM
    
    .EXAMPLE
        New-CSServiceOffering -Name "Medium-HA" -CpuNumber 2 -Memory 4096 -OfferHA $true -StorageType shared
        Creates a service offering with HA support
    
    .EXAMPLE
        New-CSServiceOffering -Name "Custom" -Customized $true -DisplayText "Custom Offering"
        Creates a customized service offering where users can specify CPU/memory
    #>

    [CmdletBinding(SupportsShouldProcess)]
    param(
        [Parameter(Mandatory=$true)]
        [string]$Name,
        
        [string]$DisplayText,
        
        [int]$CpuNumber,
        
        [int]$CpuSpeed,
        
        [int]$Memory,
        
        [bool]$Customized,
        
        [ValidateSet('local', 'shared')]
        [string]$StorageType,
        
        [bool]$OfferHA,
        
        [bool]$IsSystem,
        
        [ValidateSet('domainrouter', 'consoleproxy', 'secondarystoragevm')]
        [string]$SystemVmType,
        
        [string]$HostTags,
        
        [string]$StorageTags,
        
        [int]$NetworkRate,
        
        [bool]$DynamicScalingEnabled,
        
        [int]$RootDiskSize,
        
        [bool]$LimitCpuUse,
        
        [bool]$IsVolatile,
        
        [ValidateSet('thin', 'sparse', 'fat')]
        [string]$ProvisioningType,
        
        [string]$DiskOfferingId,
        
        [string]$ZoneId,
        
        [string]$DomainId,

        [string]$Domain
    )
    
    # Build parameters
    $apiParams = @{
        'name' = $Name
    }
    
    if ($PSBoundParameters.ContainsKey('DisplayText')) {
        $apiParams['displaytext'] = $DisplayText
    }
    
    if ($PSBoundParameters.ContainsKey('CpuNumber')) {
        $apiParams['cpunumber'] = $CpuNumber
    }
    
    if ($PSBoundParameters.ContainsKey('CpuSpeed')) {
        $apiParams['cpuspeed'] = $CpuSpeed
    }
    
    if ($PSBoundParameters.ContainsKey('Memory')) {
        $apiParams['memory'] = $Memory
    }
    
    if ($PSBoundParameters.ContainsKey('Customized')) {
        $apiParams['customized'] = $Customized.ToString().ToLower()
    }
    
    if ($PSBoundParameters.ContainsKey('StorageType')) {
        $apiParams['storagetype'] = $StorageType
    }
    
    if ($PSBoundParameters.ContainsKey('OfferHA')) {
        $apiParams['offerha'] = $OfferHA.ToString().ToLower()
    }
    
    if ($PSBoundParameters.ContainsKey('IsSystem')) {
        $apiParams['issystem'] = $IsSystem.ToString().ToLower()
    }
    
    if ($PSBoundParameters.ContainsKey('SystemVmType')) {
        $apiParams['systemvmtype'] = $SystemVmType
    }
    
    if ($PSBoundParameters.ContainsKey('HostTags')) {
        $apiParams['hosttags'] = $HostTags
    }
    
    if ($PSBoundParameters.ContainsKey('StorageTags')) {
        $apiParams['tags'] = $StorageTags
    }
    
    if ($PSBoundParameters.ContainsKey('NetworkRate')) {
        $apiParams['networkrate'] = $NetworkRate
    }
    
    if ($PSBoundParameters.ContainsKey('DynamicScalingEnabled')) {
        $apiParams['dynamicscalingenabled'] = $DynamicScalingEnabled.ToString().ToLower()
    }
    
    if ($PSBoundParameters.ContainsKey('RootDiskSize')) {
        $apiParams['rootdisksize'] = $RootDiskSize
    }
    
    if ($PSBoundParameters.ContainsKey('LimitCpuUse')) {
        $apiParams['limitcpuuse'] = $LimitCpuUse.ToString().ToLower()
    }
    
    if ($PSBoundParameters.ContainsKey('IsVolatile')) {
        $apiParams['isvolatile'] = $IsVolatile.ToString().ToLower()
    }
    
    if ($PSBoundParameters.ContainsKey('ProvisioningType')) {
        $apiParams['provisioningtype'] = $ProvisioningType
    }
    
    if ($PSBoundParameters.ContainsKey('DiskOfferingId')) {
        $apiParams['diskofferingid'] = $DiskOfferingId
    }
    
    if ($PSBoundParameters.ContainsKey('ZoneId')) {
        $apiParams['zoneid'] = $ZoneId
    }
    
    if ($PSBoundParameters.ContainsKey('DomainId')) {
        $apiParams['domainid'] = $DomainId
    }

    if ($PSBoundParameters.ContainsKey('Domain')) {
        $apiParams['domain'] = $Domain
    }
    
    # Make the API call
    if ($PSCmdlet.ShouldProcess($Name, "Create service offering")) {
        $response = Invoke-CSApiRequest -Command 'createServiceOffering' -Parameters $apiParams
        Write-Verbose "API Parameters: $($apiParams | Out-String)"
        
        # Return the created service offering
        if ($response.createserviceofferingresponse.serviceoffering) {
            return $response.createserviceofferingresponse.serviceoffering
        }
        else {
            Write-Error "Failed to create service offering."
            return $null
        }
    }
}

function Set-CSServiceOffering {
    <#
    .SYNOPSIS
        Updates a service offering in CloudStack.
    
    .DESCRIPTION
        Updates properties of an existing service offering such as name,
        display text, state, or tags.
    
    .PARAMETER Id
        The ID of the service offering to be updated (required)
    
    .PARAMETER Name
        The new name of the service offering
    
    .PARAMETER DisplayText
        The new display text of the service offering
    
    .PARAMETER State
        The new state of the service offering
    
    .PARAMETER HostTags
        The host tag for this service offering
    
    .PARAMETER StorageTags
        Comma-separated list of tags for the service offering
    
    .PARAMETER SortKey
        Sort key of the service offering (integer)
    
    .PARAMETER ZoneId
        The ID of the containing zone(s) as comma separated string,
        "all" for all zones offerings
    
    .PARAMETER DomainId
        The ID of the containing domain(s) as comma separated string,
        "public" for public offerings
    
    .PARAMETER Domain
        The name of the containing domain(s) as comma separated string,
        "public" for public offerings

    .PARAMETER PurgeResources
        Whether to cleanup VM and its associated resource upon expunge
    
    .EXAMPLE
        Set-CSServiceOffering -Id "abc-123" -Name "NewName"
        Updates the name of a service offering
    
    .EXAMPLE
        Set-CSServiceOffering -Id "abc-123" -State "Inactive"
        Disables a service offering
    
    .EXAMPLE
        Set-CSServiceOffering -Id "abc-123" -DisplayText "Updated description" -StorageTags "ssd,fast"
        Updates display text and storage tags
    #>

    [CmdletBinding(SupportsShouldProcess)]
    param(
        [Parameter(Mandatory=$true, ValueFromPipelineByPropertyName=$true)]
        [string]$Id,

        [string]$Name,

        [string]$DisplayText,

        [string]$State,

        [string]$HostTags,

        [string]$StorageTags,

        [int]$SortKey,

        [string]$ZoneId,

        [string]$DomainId,

        [string]$Domain,

        [bool]$PurgeResources
    )

    process {
        # Build parameters
        $apiParams = @{
            'id' = $Id
        }

        if ($PSBoundParameters.ContainsKey('Name')) {
            $apiParams['name'] = $Name
        }

        if ($PSBoundParameters.ContainsKey('DisplayText')) {
            $apiParams['displaytext'] = $DisplayText
        }

        if ($PSBoundParameters.ContainsKey('State')) {
            $apiParams['state'] = $State
        }

        if ($PSBoundParameters.ContainsKey('HostTags')) {
            $apiParams['hosttags'] = $HostTags
        }

        if ($PSBoundParameters.ContainsKey('StorageTags')) {
            $apiParams['storagetags'] = $StorageTags
        }

        if ($PSBoundParameters.ContainsKey('SortKey')) {
            $apiParams['sortkey'] = $SortKey
        }

        if ($PSBoundParameters.ContainsKey('ZoneId')) {
            $apiParams['zoneid'] = $ZoneId
        }

        if ($PSBoundParameters.ContainsKey('DomainId')) {
            $apiParams['domainid'] = $DomainId
        }

        if ($PSBoundParameters.ContainsKey('Domain')) {
            $apiParams['domain'] = $Domain
        }

        if ($PSBoundParameters.ContainsKey('PurgeResources')) {
            $apiParams['purgeresources'] = $PurgeResources.ToString().ToLower()
        }

        # Make the API call
        if ($PSCmdlet.ShouldProcess($Id, "Update service offering")) {
            $response = Invoke-CSApiRequest -Command 'updateServiceOffering' -Parameters $apiParams
            Write-Verbose "API Parameters: $($apiParams | Out-String)"

            # Return the updated service offering
            if ($response.updateserviceofferingresponse.serviceoffering) {
                return $response.updateserviceofferingresponse.serviceoffering
            }
            else {
                Write-Error "Failed to update service offering."
                return $null
            }
        }
    }
}

function Remove-CSServiceOffering {
    <#
    .SYNOPSIS
        Deletes a service offering in CloudStack.
    
    .DESCRIPTION
        Deletes a service offering. The offering must not be in use by any VMs.
    
    .PARAMETER Id
        The ID of the service offering to delete (required)
    
    .PARAMETER Force
        Skip confirmation prompt
    
    .EXAMPLE
        Remove-CSServiceOffering -Id "abc-123"
        Deletes a service offering with confirmation
    
    .EXAMPLE
        Remove-CSServiceOffering -Id "abc-123" -Force
        Deletes a service offering without confirmation
    
    .EXAMPLE
        Get-CSServiceOffering -Name "Old-Offering" | Remove-CSServiceOffering
        Deletes a service offering via pipeline
    #>

    [CmdletBinding(SupportsShouldProcess, ConfirmImpact='High')]
    param(
        [Parameter(Mandatory=$true, ValueFromPipelineByPropertyName=$true)]
        [string]$Id,
        
        [switch]$Force
    )
    
    process {
        # Build parameters
        $apiParams = @{
            'id' = $Id
        }
        
        # Confirmation handling
        $confirmMessage = "Are you sure you want to delete service offering '$Id'?"
        $shouldProcessMessage = "Delete service offering"
        
        if ($Force) {
            $ConfirmPreference = 'None'
        }
        
        # Make the API call
        if ($PSCmdlet.ShouldProcess($Id, $shouldProcessMessage)) {
            $response = Invoke-CSApiRequest -Command 'deleteServiceOffering' -Parameters $apiParams
            Write-Verbose "API Parameters: $($apiParams | Out-String)"
            
            # Return the result
            if ($response.deleteserviceofferingresponse) {
                return $response.deleteserviceofferingresponse
            }
            else {
                Write-Error "Failed to delete service offering."
                return $null
            }
        }
    }
}