mirror of
https://github.com/Grace-Solutions/PSProxmox.git
synced 2026-07-26 08:18:19 +00:00
Add LXC container and TurnKey template support
This commit is contained in:
@@ -0,0 +1,118 @@
|
||||
# Get-ProxmoxContainer
|
||||
|
||||
## SYNOPSIS
|
||||
Gets Proxmox LXC containers.
|
||||
|
||||
## SYNTAX
|
||||
|
||||
```powershell
|
||||
Get-ProxmoxContainer [[-CTID] <Int32>] [[-Node] <String>] [[-Name] <String>] [<CommonParameters>]
|
||||
```
|
||||
|
||||
## DESCRIPTION
|
||||
Gets Proxmox LXC containers from a Proxmox server.
|
||||
|
||||
If no parameters are specified, all containers are returned.
|
||||
If a CTID is specified, only that container is returned.
|
||||
If a node is specified, only containers on that node are returned.
|
||||
If a name is specified, only containers with that name are returned (supports wildcards and regex).
|
||||
|
||||
## EXAMPLES
|
||||
|
||||
### Example 1: Get all containers
|
||||
```powershell
|
||||
Get-ProxmoxContainer
|
||||
```
|
||||
|
||||
Gets all containers from the Proxmox server.
|
||||
|
||||
### Example 2: Get a specific container
|
||||
```powershell
|
||||
Get-ProxmoxContainer -CTID 100
|
||||
```
|
||||
|
||||
Gets the container with CTID 100.
|
||||
|
||||
### Example 3: Get all containers on a specific node
|
||||
```powershell
|
||||
Get-ProxmoxContainer -Node "pve1"
|
||||
```
|
||||
|
||||
Gets all containers on node pve1.
|
||||
|
||||
### Example 4: Get containers by name using wildcards
|
||||
```powershell
|
||||
Get-ProxmoxContainer -Name "web*"
|
||||
```
|
||||
|
||||
Gets all containers with names starting with "web" (wildcard).
|
||||
|
||||
### Example 5: Get containers by name using regex
|
||||
```powershell
|
||||
Get-ProxmoxContainer -Name "^web\d+$"
|
||||
```
|
||||
|
||||
Gets all containers with names matching the regex pattern "^web\d+$".
|
||||
|
||||
## PARAMETERS
|
||||
|
||||
### -CTID
|
||||
The container ID.
|
||||
|
||||
```yaml
|
||||
Type: Int32
|
||||
Parameter Sets: (All)
|
||||
Aliases:
|
||||
|
||||
Required: False
|
||||
Position: 0
|
||||
Default value: None
|
||||
Accept pipeline input: True (ByValue, ByPropertyName)
|
||||
Accept wildcard characters: False
|
||||
```
|
||||
|
||||
### -Node
|
||||
The node name.
|
||||
|
||||
```yaml
|
||||
Type: String
|
||||
Parameter Sets: (All)
|
||||
Aliases:
|
||||
|
||||
Required: False
|
||||
Position: 1
|
||||
Default value: None
|
||||
Accept pipeline input: True (ByPropertyName)
|
||||
Accept wildcard characters: False
|
||||
```
|
||||
|
||||
### -Name
|
||||
The container name (supports wildcards and regex).
|
||||
|
||||
```yaml
|
||||
Type: String
|
||||
Parameter Sets: (All)
|
||||
Aliases:
|
||||
|
||||
Required: False
|
||||
Position: 2
|
||||
Default value: None
|
||||
Accept pipeline input: True (ByPropertyName)
|
||||
Accept wildcard characters: True
|
||||
```
|
||||
|
||||
### CommonParameters
|
||||
This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216).
|
||||
|
||||
## INPUTS
|
||||
|
||||
### System.Int32
|
||||
### System.String
|
||||
|
||||
## OUTPUTS
|
||||
|
||||
### PSProxmox.Models.ProxmoxContainer
|
||||
|
||||
## NOTES
|
||||
|
||||
## RELATED LINKS
|
||||
@@ -0,0 +1,116 @@
|
||||
# Get-ProxmoxTurnKeyTemplate
|
||||
|
||||
## SYNOPSIS
|
||||
Gets TurnKey Linux templates for Proxmox LXC containers.
|
||||
|
||||
## SYNTAX
|
||||
|
||||
```powershell
|
||||
Get-ProxmoxTurnKeyTemplate [[-Node] <String>] [[-Name] <String>] [-IncludeDownloaded] [<CommonParameters>]
|
||||
```
|
||||
|
||||
## DESCRIPTION
|
||||
Gets TurnKey Linux templates for Proxmox LXC containers from a Proxmox server.
|
||||
|
||||
If no parameters are specified, all templates are returned.
|
||||
If a node is specified, only templates available on that node are returned.
|
||||
If a name is specified, only templates with that name are returned (supports wildcards and regex).
|
||||
|
||||
## EXAMPLES
|
||||
|
||||
### Example 1: Get all TurnKey templates
|
||||
```powershell
|
||||
Get-ProxmoxTurnKeyTemplate
|
||||
```
|
||||
|
||||
Gets all TurnKey Linux templates from the Proxmox server.
|
||||
|
||||
### Example 2: Get all TurnKey templates on a specific node
|
||||
```powershell
|
||||
Get-ProxmoxTurnKeyTemplate -Node "pve1"
|
||||
```
|
||||
|
||||
Gets all TurnKey Linux templates available on node pve1.
|
||||
|
||||
### Example 3: Get TurnKey templates by name using wildcards
|
||||
```powershell
|
||||
Get-ProxmoxTurnKeyTemplate -Name "wordpress*"
|
||||
```
|
||||
|
||||
Gets all TurnKey Linux templates with names starting with "wordpress" (wildcard).
|
||||
|
||||
### Example 4: Get TurnKey templates by name using regex
|
||||
```powershell
|
||||
Get-ProxmoxTurnKeyTemplate -Name "^wordpress\d+$"
|
||||
```
|
||||
|
||||
Gets all TurnKey Linux templates with names matching the regex pattern "^wordpress\d+$".
|
||||
|
||||
### Example 5: Include downloaded templates
|
||||
```powershell
|
||||
Get-ProxmoxTurnKeyTemplate -IncludeDownloaded
|
||||
```
|
||||
|
||||
Gets all TurnKey Linux templates, including those that have already been downloaded.
|
||||
|
||||
## PARAMETERS
|
||||
|
||||
### -Node
|
||||
The node name.
|
||||
|
||||
```yaml
|
||||
Type: String
|
||||
Parameter Sets: (All)
|
||||
Aliases:
|
||||
|
||||
Required: False
|
||||
Position: 0
|
||||
Default value: None
|
||||
Accept pipeline input: True (ByPropertyName)
|
||||
Accept wildcard characters: False
|
||||
```
|
||||
|
||||
### -Name
|
||||
The template name (supports wildcards and regex).
|
||||
|
||||
```yaml
|
||||
Type: String
|
||||
Parameter Sets: (All)
|
||||
Aliases:
|
||||
|
||||
Required: False
|
||||
Position: 1
|
||||
Default value: None
|
||||
Accept pipeline input: True (ByPropertyName)
|
||||
Accept wildcard characters: True
|
||||
```
|
||||
|
||||
### -IncludeDownloaded
|
||||
Whether to include downloaded templates.
|
||||
|
||||
```yaml
|
||||
Type: SwitchParameter
|
||||
Parameter Sets: (All)
|
||||
Aliases:
|
||||
|
||||
Required: False
|
||||
Position: Named
|
||||
Default value: None
|
||||
Accept pipeline input: False
|
||||
Accept wildcard characters: False
|
||||
```
|
||||
|
||||
### CommonParameters
|
||||
This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216).
|
||||
|
||||
## INPUTS
|
||||
|
||||
### System.String
|
||||
|
||||
## OUTPUTS
|
||||
|
||||
### PSProxmox.Models.ProxmoxTurnKeyTemplate
|
||||
|
||||
## NOTES
|
||||
|
||||
## RELATED LINKS
|
||||
@@ -0,0 +1,303 @@
|
||||
# New-ProxmoxContainer
|
||||
|
||||
## SYNOPSIS
|
||||
Creates a new Proxmox LXC container.
|
||||
|
||||
## SYNTAX
|
||||
|
||||
```powershell
|
||||
New-ProxmoxContainer -Node <String> [-Builder <ProxmoxContainerBuilder>] [-CTID <Int32>] [-Name <String>]
|
||||
[-OSTemplate <String>] [-Storage <String>] [-Memory <Int32>] [-Swap <Int32>] [-Cores <Int32>]
|
||||
[-DiskSize <Int32>] [-Unprivileged] [-Password <SecureString>] [-SSHKey <String>] [-Description <String>]
|
||||
[-StartOnBoot] [-Start] [<CommonParameters>]
|
||||
```
|
||||
|
||||
## DESCRIPTION
|
||||
Creates a new Proxmox LXC container on a Proxmox server.
|
||||
|
||||
## EXAMPLES
|
||||
|
||||
### Example 1: Create a new container
|
||||
```powershell
|
||||
New-ProxmoxContainer -Node "pve1" -Name "web-container" -OSTemplate "local:vztmpl/ubuntu-20.04-standard_20.04-1_amd64.tar.gz" -Storage "local-lvm" -Memory 512 -Swap 512 -Cores 1 -DiskSize 8
|
||||
```
|
||||
|
||||
Creates a new LXC container on node pve1.
|
||||
|
||||
### Example 2: Create a new container using a builder
|
||||
```powershell
|
||||
$builder = New-ProxmoxContainerBuilder -Name "web-container"
|
||||
$builder.WithOSTemplate("local:vztmpl/ubuntu-20.04-standard_20.04-1_amd64.tar.gz")
|
||||
.WithStorage("local-lvm")
|
||||
.WithMemory(512)
|
||||
.WithSwap(512)
|
||||
.WithCores(1)
|
||||
.WithDiskSize(8)
|
||||
.WithUnprivileged($true)
|
||||
.WithStartOnBoot($true)
|
||||
.WithStart($true)
|
||||
New-ProxmoxContainer -Node "pve1" -Builder $builder
|
||||
```
|
||||
|
||||
Creates a new LXC container on node pve1 using a builder.
|
||||
|
||||
## PARAMETERS
|
||||
|
||||
### -Node
|
||||
The node name.
|
||||
|
||||
```yaml
|
||||
Type: String
|
||||
Parameter Sets: (All)
|
||||
Aliases:
|
||||
|
||||
Required: True
|
||||
Position: 0
|
||||
Default value: None
|
||||
Accept pipeline input: True (ByPropertyName)
|
||||
Accept wildcard characters: False
|
||||
```
|
||||
|
||||
### -Builder
|
||||
The container builder.
|
||||
|
||||
```yaml
|
||||
Type: ProxmoxContainerBuilder
|
||||
Parameter Sets: (All)
|
||||
Aliases:
|
||||
|
||||
Required: False
|
||||
Position: 1
|
||||
Default value: None
|
||||
Accept pipeline input: True (ByValue)
|
||||
Accept wildcard characters: False
|
||||
```
|
||||
|
||||
### -CTID
|
||||
The container ID.
|
||||
|
||||
```yaml
|
||||
Type: Int32
|
||||
Parameter Sets: (All)
|
||||
Aliases:
|
||||
|
||||
Required: False
|
||||
Position: Named
|
||||
Default value: None
|
||||
Accept pipeline input: True (ByPropertyName)
|
||||
Accept wildcard characters: False
|
||||
```
|
||||
|
||||
### -Name
|
||||
The container name.
|
||||
|
||||
```yaml
|
||||
Type: String
|
||||
Parameter Sets: (All)
|
||||
Aliases:
|
||||
|
||||
Required: False
|
||||
Position: Named
|
||||
Default value: None
|
||||
Accept pipeline input: True (ByPropertyName)
|
||||
Accept wildcard characters: False
|
||||
```
|
||||
|
||||
### -OSTemplate
|
||||
The container OS template.
|
||||
|
||||
```yaml
|
||||
Type: String
|
||||
Parameter Sets: (All)
|
||||
Aliases:
|
||||
|
||||
Required: False
|
||||
Position: Named
|
||||
Default value: None
|
||||
Accept pipeline input: True (ByPropertyName)
|
||||
Accept wildcard characters: False
|
||||
```
|
||||
|
||||
### -Storage
|
||||
The container storage.
|
||||
|
||||
```yaml
|
||||
Type: String
|
||||
Parameter Sets: (All)
|
||||
Aliases:
|
||||
|
||||
Required: False
|
||||
Position: Named
|
||||
Default value: None
|
||||
Accept pipeline input: True (ByPropertyName)
|
||||
Accept wildcard characters: False
|
||||
```
|
||||
|
||||
### -Memory
|
||||
The container memory limit in MB.
|
||||
|
||||
```yaml
|
||||
Type: Int32
|
||||
Parameter Sets: (All)
|
||||
Aliases:
|
||||
|
||||
Required: False
|
||||
Position: Named
|
||||
Default value: None
|
||||
Accept pipeline input: True (ByPropertyName)
|
||||
Accept wildcard characters: False
|
||||
```
|
||||
|
||||
### -Swap
|
||||
The container swap limit in MB.
|
||||
|
||||
```yaml
|
||||
Type: Int32
|
||||
Parameter Sets: (All)
|
||||
Aliases:
|
||||
|
||||
Required: False
|
||||
Position: Named
|
||||
Default value: None
|
||||
Accept pipeline input: True (ByPropertyName)
|
||||
Accept wildcard characters: False
|
||||
```
|
||||
|
||||
### -Cores
|
||||
The container CPU cores.
|
||||
|
||||
```yaml
|
||||
Type: Int32
|
||||
Parameter Sets: (All)
|
||||
Aliases:
|
||||
|
||||
Required: False
|
||||
Position: Named
|
||||
Default value: None
|
||||
Accept pipeline input: True (ByPropertyName)
|
||||
Accept wildcard characters: False
|
||||
```
|
||||
|
||||
### -DiskSize
|
||||
The container disk size in GB.
|
||||
|
||||
```yaml
|
||||
Type: Int32
|
||||
Parameter Sets: (All)
|
||||
Aliases:
|
||||
|
||||
Required: False
|
||||
Position: Named
|
||||
Default value: None
|
||||
Accept pipeline input: True (ByPropertyName)
|
||||
Accept wildcard characters: False
|
||||
```
|
||||
|
||||
### -Unprivileged
|
||||
Whether the container is unprivileged.
|
||||
|
||||
```yaml
|
||||
Type: SwitchParameter
|
||||
Parameter Sets: (All)
|
||||
Aliases:
|
||||
|
||||
Required: False
|
||||
Position: Named
|
||||
Default value: None
|
||||
Accept pipeline input: True (ByPropertyName)
|
||||
Accept wildcard characters: False
|
||||
```
|
||||
|
||||
### -Password
|
||||
The container password.
|
||||
|
||||
```yaml
|
||||
Type: SecureString
|
||||
Parameter Sets: (All)
|
||||
Aliases:
|
||||
|
||||
Required: False
|
||||
Position: Named
|
||||
Default value: None
|
||||
Accept pipeline input: True (ByPropertyName)
|
||||
Accept wildcard characters: False
|
||||
```
|
||||
|
||||
### -SSHKey
|
||||
The container SSH public key.
|
||||
|
||||
```yaml
|
||||
Type: String
|
||||
Parameter Sets: (All)
|
||||
Aliases:
|
||||
|
||||
Required: False
|
||||
Position: Named
|
||||
Default value: None
|
||||
Accept pipeline input: True (ByPropertyName)
|
||||
Accept wildcard characters: False
|
||||
```
|
||||
|
||||
### -Description
|
||||
The container description.
|
||||
|
||||
```yaml
|
||||
Type: String
|
||||
Parameter Sets: (All)
|
||||
Aliases:
|
||||
|
||||
Required: False
|
||||
Position: Named
|
||||
Default value: None
|
||||
Accept pipeline input: True (ByPropertyName)
|
||||
Accept wildcard characters: False
|
||||
```
|
||||
|
||||
### -StartOnBoot
|
||||
Whether to start the container on boot.
|
||||
|
||||
```yaml
|
||||
Type: SwitchParameter
|
||||
Parameter Sets: (All)
|
||||
Aliases:
|
||||
|
||||
Required: False
|
||||
Position: Named
|
||||
Default value: None
|
||||
Accept pipeline input: True (ByPropertyName)
|
||||
Accept wildcard characters: False
|
||||
```
|
||||
|
||||
### -Start
|
||||
Whether to start the container after creation.
|
||||
|
||||
```yaml
|
||||
Type: SwitchParameter
|
||||
Parameter Sets: (All)
|
||||
Aliases:
|
||||
|
||||
Required: False
|
||||
Position: Named
|
||||
Default value: None
|
||||
Accept pipeline input: True (ByPropertyName)
|
||||
Accept wildcard characters: False
|
||||
```
|
||||
|
||||
### CommonParameters
|
||||
This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216).
|
||||
|
||||
## INPUTS
|
||||
|
||||
### System.String
|
||||
### PSProxmox.Models.ProxmoxContainerBuilder
|
||||
### System.Int32
|
||||
### System.Security.SecureString
|
||||
### System.Management.Automation.SwitchParameter
|
||||
|
||||
## OUTPUTS
|
||||
|
||||
### PSProxmox.Models.ProxmoxContainer
|
||||
|
||||
## NOTES
|
||||
|
||||
## RELATED LINKS
|
||||
@@ -0,0 +1,79 @@
|
||||
# LXC Container Management Examples
|
||||
|
||||
# Connect to the Proxmox server
|
||||
$securePassword = ConvertTo-SecureString "password" -AsPlainText -Force
|
||||
Connect-ProxmoxServer -Server "proxmox.example.com" -Username "root" -Password $securePassword -Realm "pam"
|
||||
|
||||
# Get all LXC containers
|
||||
$containers = Get-ProxmoxContainer
|
||||
$containers | Format-Table -Property CTID, Name, Status, Node
|
||||
|
||||
# Get a specific LXC container
|
||||
$container = Get-ProxmoxContainer -CTID 100
|
||||
$container
|
||||
|
||||
# Get all LXC containers on a specific node
|
||||
$nodeContainers = Get-ProxmoxContainer -Node "pve1"
|
||||
$nodeContainers | Format-Table -Property CTID, Name, Status
|
||||
|
||||
# Get LXC containers by name pattern (wildcard)
|
||||
$webContainers = Get-ProxmoxContainer -Name "web*"
|
||||
$webContainers | Format-Table -Property CTID, Name, Status, Node
|
||||
|
||||
# Get LXC containers by name pattern (regex)
|
||||
$dbContainers = Get-ProxmoxContainer -Name "^db\d+$"
|
||||
$dbContainers | Format-Table -Property CTID, Name, Status, Node
|
||||
|
||||
# Create a new LXC container using parameters
|
||||
$container = New-ProxmoxContainer -Node "pve1" -Name "web-container" -OSTemplate "local:vztmpl/ubuntu-20.04-standard_20.04-1_amd64.tar.gz" -Storage "local-lvm" -Memory 512 -Swap 512 -Cores 1 -DiskSize 8 -Unprivileged -StartOnBoot -Start
|
||||
$container
|
||||
|
||||
# Create a new LXC container using a builder
|
||||
$builder = New-ProxmoxContainerBuilder -Name "db-container"
|
||||
$builder.WithOSTemplate("local:vztmpl/ubuntu-20.04-standard_20.04-1_amd64.tar.gz")
|
||||
.WithStorage("local-lvm")
|
||||
.WithMemory(1024)
|
||||
.WithSwap(1024)
|
||||
.WithCores(2)
|
||||
.WithDiskSize(16)
|
||||
.WithUnprivileged($true)
|
||||
.WithStartOnBoot($true)
|
||||
.WithStart($true)
|
||||
.WithDescription("Database container")
|
||||
|
||||
$container = New-ProxmoxContainer -Node "pve1" -Builder $builder
|
||||
$container
|
||||
|
||||
# Start an LXC container
|
||||
Start-ProxmoxContainer -Node "pve1" -CTID 100 -Wait
|
||||
Get-ProxmoxContainer -CTID 100
|
||||
|
||||
# Stop an LXC container
|
||||
Stop-ProxmoxContainer -Node "pve1" -CTID 100 -Wait
|
||||
Get-ProxmoxContainer -CTID 100
|
||||
|
||||
# Restart an LXC container
|
||||
Restart-ProxmoxContainer -Node "pve1" -CTID 100 -Wait
|
||||
Get-ProxmoxContainer -CTID 100
|
||||
|
||||
# Remove an LXC container
|
||||
Remove-ProxmoxContainer -Node "pve1" -CTID 100 -Confirm:$false
|
||||
|
||||
# Get all TurnKey Linux templates
|
||||
$templates = Get-ProxmoxTurnKeyTemplate
|
||||
$templates | Format-Table -Property Name, Title, OS, Version, HumanSize
|
||||
|
||||
# Get TurnKey Linux templates by name pattern (wildcard)
|
||||
$wordpressTemplates = Get-ProxmoxTurnKeyTemplate -Name "wordpress*"
|
||||
$wordpressTemplates | Format-Table -Property Name, Title, OS, Version, HumanSize
|
||||
|
||||
# Download a TurnKey Linux template
|
||||
$templatePath = Save-ProxmoxTurnKeyTemplate -Node "pve1" -Name "wordpress" -Storage "local"
|
||||
$templatePath
|
||||
|
||||
# Create a new LXC container from a TurnKey Linux template
|
||||
$container = New-ProxmoxContainerFromTurnKey -Node "pve1" -Name "wordpress" -Template "wordpress" -Storage "local-lvm" -Memory 512 -Cores 1 -DiskSize 8 -Start
|
||||
$container
|
||||
|
||||
# Disconnect from the Proxmox server
|
||||
Disconnect-ProxmoxServer
|
||||
@@ -0,0 +1,172 @@
|
||||
# LXC Container Management Guide
|
||||
|
||||
This guide covers how to use PSProxmox to manage LXC containers on a Proxmox VE server.
|
||||
|
||||
## Overview
|
||||
|
||||
Proxmox VE supports Linux Containers (LXC) as a lightweight alternative to full virtual machines. LXC containers provide an isolated environment for applications with minimal overhead compared to VMs.
|
||||
|
||||
PSProxmox provides cmdlets for creating, managing, and removing LXC containers, as well as working with TurnKey Linux templates.
|
||||
|
||||
## Container Management Cmdlets
|
||||
|
||||
PSProxmox includes the following cmdlets for managing LXC containers:
|
||||
|
||||
- `Get-ProxmoxContainer`: List all LXC containers or get details for a specific container
|
||||
- `New-ProxmoxContainer`: Create a new LXC container
|
||||
- `New-ProxmoxContainerBuilder`: Create a builder for configuring container parameters
|
||||
- `Remove-ProxmoxContainer`: Delete an LXC container
|
||||
- `Start-ProxmoxContainer`: Start an LXC container
|
||||
- `Stop-ProxmoxContainer`: Stop an LXC container
|
||||
- `Restart-ProxmoxContainer`: Restart an LXC container
|
||||
|
||||
## TurnKey Template Management Cmdlets
|
||||
|
||||
PSProxmox also includes cmdlets for working with TurnKey Linux templates:
|
||||
|
||||
- `Get-ProxmoxTurnKeyTemplate`: List available TurnKey templates
|
||||
- `Save-ProxmoxTurnKeyTemplate`: Download a TurnKey template to a Proxmox storage
|
||||
- `New-ProxmoxContainerFromTurnKey`: Create a new LXC container from a TurnKey template
|
||||
|
||||
## Basic Container Operations
|
||||
|
||||
### Listing Containers
|
||||
|
||||
To list all containers on a Proxmox server:
|
||||
|
||||
```powershell
|
||||
Get-ProxmoxContainer
|
||||
```
|
||||
|
||||
To get a specific container by ID:
|
||||
|
||||
```powershell
|
||||
Get-ProxmoxContainer -CTID 100
|
||||
```
|
||||
|
||||
To get containers on a specific node:
|
||||
|
||||
```powershell
|
||||
Get-ProxmoxContainer -Node "pve1"
|
||||
```
|
||||
|
||||
To get containers by name pattern (supports wildcards and regex):
|
||||
|
||||
```powershell
|
||||
# Using wildcards
|
||||
Get-ProxmoxContainer -Name "web*"
|
||||
|
||||
# Using regex
|
||||
Get-ProxmoxContainer -Name "^web\d+$"
|
||||
```
|
||||
|
||||
### Creating Containers
|
||||
|
||||
To create a new container using parameters:
|
||||
|
||||
```powershell
|
||||
New-ProxmoxContainer -Node "pve1" -Name "web-container" -OSTemplate "local:vztmpl/ubuntu-20.04-standard_20.04-1_amd64.tar.gz" -Storage "local-lvm" -Memory 512 -Swap 512 -Cores 1 -DiskSize 8 -Unprivileged -StartOnBoot -Start
|
||||
```
|
||||
|
||||
To create a new container using a builder (for more complex configurations):
|
||||
|
||||
```powershell
|
||||
$builder = New-ProxmoxContainerBuilder -Name "db-container"
|
||||
$builder.WithOSTemplate("local:vztmpl/ubuntu-20.04-standard_20.04-1_amd64.tar.gz")
|
||||
.WithStorage("local-lvm")
|
||||
.WithMemory(1024)
|
||||
.WithSwap(1024)
|
||||
.WithCores(2)
|
||||
.WithDiskSize(16)
|
||||
.WithUnprivileged($true)
|
||||
.WithStartOnBoot($true)
|
||||
.WithStart($true)
|
||||
.WithDescription("Database container")
|
||||
|
||||
New-ProxmoxContainer -Node "pve1" -Builder $builder
|
||||
```
|
||||
|
||||
### Managing Container State
|
||||
|
||||
To start a container:
|
||||
|
||||
```powershell
|
||||
Start-ProxmoxContainer -Node "pve1" -CTID 100 -Wait
|
||||
```
|
||||
|
||||
To stop a container:
|
||||
|
||||
```powershell
|
||||
Stop-ProxmoxContainer -Node "pve1" -CTID 100 -Wait
|
||||
```
|
||||
|
||||
To restart a container:
|
||||
|
||||
```powershell
|
||||
Restart-ProxmoxContainer -Node "pve1" -CTID 100 -Wait
|
||||
```
|
||||
|
||||
### Removing Containers
|
||||
|
||||
To remove a container:
|
||||
|
||||
```powershell
|
||||
Remove-ProxmoxContainer -Node "pve1" -CTID 100 -Confirm:$false
|
||||
```
|
||||
|
||||
## Working with TurnKey Linux Templates
|
||||
|
||||
TurnKey Linux provides pre-built appliances that can be used as templates for LXC containers.
|
||||
|
||||
### Listing TurnKey Templates
|
||||
|
||||
To list all available TurnKey templates:
|
||||
|
||||
```powershell
|
||||
Get-ProxmoxTurnKeyTemplate
|
||||
```
|
||||
|
||||
To list templates by name pattern:
|
||||
|
||||
```powershell
|
||||
Get-ProxmoxTurnKeyTemplate -Name "wordpress*"
|
||||
```
|
||||
|
||||
To include templates that have already been downloaded:
|
||||
|
||||
```powershell
|
||||
Get-ProxmoxTurnKeyTemplate -IncludeDownloaded
|
||||
```
|
||||
|
||||
### Downloading TurnKey Templates
|
||||
|
||||
To download a TurnKey template to a storage:
|
||||
|
||||
```powershell
|
||||
Save-ProxmoxTurnKeyTemplate -Node "pve1" -Name "wordpress" -Storage "local"
|
||||
```
|
||||
|
||||
### Creating Containers from TurnKey Templates
|
||||
|
||||
To create a container from a TurnKey template:
|
||||
|
||||
```powershell
|
||||
New-ProxmoxContainerFromTurnKey -Node "pve1" -Name "wordpress" -Template "wordpress" -Storage "local-lvm" -Memory 512 -Cores 1 -DiskSize 8 -Start
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Use Unprivileged Containers**: For better security, create unprivileged containers when possible.
|
||||
2. **Resource Allocation**: Allocate appropriate resources (memory, CPU, disk) based on the container's purpose.
|
||||
3. **Storage Selection**: Choose the appropriate storage type for your containers (local-lvm is often a good choice for performance).
|
||||
4. **Naming Convention**: Use a consistent naming convention for your containers to make management easier.
|
||||
5. **Template Management**: Download and maintain templates on a central storage for easy access from all nodes.
|
||||
|
||||
## Examples
|
||||
|
||||
See the [LXC Container Management Examples](../examples/LXC-Container-Management.ps1) for more detailed examples.
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- [Proxmox VE LXC Documentation](https://pve.proxmox.com/wiki/Linux_Container)
|
||||
- [TurnKey Linux](https://www.turnkeylinux.org/)
|
||||
+17
-3
@@ -1,5 +1,5 @@
|
||||
@{
|
||||
ModuleVersion = '2025.05.10.1500'
|
||||
ModuleVersion = '2025.05.10.1600'
|
||||
GUID = 'd24f0894-3d0c-4ef1-a41e-b273c3db86ad'
|
||||
Author = 'PSProxmox Team'
|
||||
CompanyName = 'PSProxmox'
|
||||
@@ -83,7 +83,21 @@
|
||||
'Save-ProxmoxCloudImage',
|
||||
'Invoke-ProxmoxCloudImageCustomization',
|
||||
'New-ProxmoxCloudImageTemplate',
|
||||
'Set-ProxmoxVMCloudInit'
|
||||
'Set-ProxmoxVMCloudInit',
|
||||
|
||||
# LXC Container Management
|
||||
'Get-ProxmoxContainer',
|
||||
'New-ProxmoxContainer',
|
||||
'New-ProxmoxContainerBuilder',
|
||||
'Remove-ProxmoxContainer',
|
||||
'Start-ProxmoxContainer',
|
||||
'Stop-ProxmoxContainer',
|
||||
'Restart-ProxmoxContainer',
|
||||
|
||||
# TurnKey Template Management
|
||||
'Get-ProxmoxTurnKeyTemplate',
|
||||
'Save-ProxmoxTurnKeyTemplate',
|
||||
'New-ProxmoxContainerFromTurnKey'
|
||||
)
|
||||
VariablesToExport = @()
|
||||
AliasesToExport = @()
|
||||
@@ -92,7 +106,7 @@
|
||||
Tags = @('Proxmox', 'VirtualMachine', 'Cluster', 'Management')
|
||||
LicenseUri = 'https://github.com/Grace-Solutions/PSProxmox/blob/main/LICENSE'
|
||||
ProjectUri = 'https://github.com/Grace-Solutions/PSProxmox'
|
||||
ReleaseNotes = 'Added cloud image template functionality. See https://github.com/Grace-Solutions/PSProxmox/releases/tag/v2025.05.10.1500'
|
||||
ReleaseNotes = 'Added LXC container and TurnKey template support. See https://github.com/Grace-Solutions/PSProxmox/releases/tag/v2025.05.10.1600'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,223 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Management.Automation;
|
||||
using System.Text.RegularExpressions;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using PSProxmox.Models;
|
||||
using PSProxmox.Session;
|
||||
|
||||
namespace PSProxmox.Cmdlets
|
||||
{
|
||||
/// <summary>
|
||||
/// <para type="synopsis">Gets Proxmox LXC containers</para>
|
||||
/// <para type="description">Gets Proxmox LXC containers from a Proxmox server</para>
|
||||
/// <para type="description">If no parameters are specified, all containers are returned</para>
|
||||
/// <para type="description">If a CTID is specified, only that container is returned</para>
|
||||
/// <para type="description">If a node is specified, only containers on that node are returned</para>
|
||||
/// <para type="description">If a name is specified, only containers with that name are returned (supports wildcards and regex)</para>
|
||||
/// </summary>
|
||||
/// <example>
|
||||
/// <code>Get-ProxmoxContainer</code>
|
||||
/// <para>Gets all containers from the Proxmox server</para>
|
||||
/// </example>
|
||||
/// <example>
|
||||
/// <code>Get-ProxmoxContainer -CTID 100</code>
|
||||
/// <para>Gets the container with CTID 100</para>
|
||||
/// </example>
|
||||
/// <example>
|
||||
/// <code>Get-ProxmoxContainer -Node "pve1"</code>
|
||||
/// <para>Gets all containers on node pve1</para>
|
||||
/// </example>
|
||||
/// <example>
|
||||
/// <code>Get-ProxmoxContainer -Name "web*"</code>
|
||||
/// <para>Gets all containers with names starting with "web" (wildcard)</para>
|
||||
/// </example>
|
||||
/// <example>
|
||||
/// <code>Get-ProxmoxContainer -Name "^web\d+$"</code>
|
||||
/// <para>Gets all containers with names matching the regex pattern "^web\d+$"</para>
|
||||
/// </example>
|
||||
[Cmdlet(VerbsCommon.Get, "ProxmoxContainer")]
|
||||
[OutputType(typeof(ProxmoxContainer))]
|
||||
public class GetProxmoxContainerCmdlet : ProxmoxCmdlet
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the container ID
|
||||
/// </summary>
|
||||
[Parameter(Position = 0, ValueFromPipeline = true, ValueFromPipelineByPropertyName = true)]
|
||||
public int? CTID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the node name
|
||||
/// </summary>
|
||||
[Parameter(Position = 1, ValueFromPipelineByPropertyName = true)]
|
||||
public string Node { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the container name (supports wildcards and regex)
|
||||
/// </summary>
|
||||
[Parameter(Position = 2, ValueFromPipelineByPropertyName = true)]
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Processes the cmdlet
|
||||
/// </summary>
|
||||
protected override void ProcessRecord()
|
||||
{
|
||||
base.ProcessRecord();
|
||||
|
||||
try
|
||||
{
|
||||
if (CTID.HasValue && !string.IsNullOrEmpty(Node))
|
||||
{
|
||||
// Get a specific container on a specific node
|
||||
var container = GetContainer(Node, CTID.Value);
|
||||
if (container != null)
|
||||
{
|
||||
WriteObject(container);
|
||||
}
|
||||
}
|
||||
else if (CTID.HasValue)
|
||||
{
|
||||
// Get a specific container on any node
|
||||
var nodes = GetNodes();
|
||||
foreach (var node in nodes)
|
||||
{
|
||||
var container = GetContainer(node.Name, CTID.Value);
|
||||
if (container != null)
|
||||
{
|
||||
WriteObject(container);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(Node))
|
||||
{
|
||||
// Get all containers on a specific node
|
||||
var containers = GetContainers(Node);
|
||||
|
||||
// Filter by name if specified
|
||||
if (!string.IsNullOrEmpty(Name))
|
||||
{
|
||||
containers = FilterContainersByName(containers, Name);
|
||||
}
|
||||
|
||||
WriteObject(containers, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Get all containers on all nodes
|
||||
var nodes = GetNodes();
|
||||
var allContainers = new List<ProxmoxContainer>();
|
||||
|
||||
foreach (var node in nodes)
|
||||
{
|
||||
var containers = GetContainers(node.Name);
|
||||
allContainers.AddRange(containers);
|
||||
}
|
||||
|
||||
// Filter by name if specified
|
||||
if (!string.IsNullOrEmpty(Name))
|
||||
{
|
||||
allContainers = FilterContainersByName(allContainers, Name);
|
||||
}
|
||||
|
||||
WriteObject(allContainers, true);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
WriteError(new ErrorRecord(ex, "GetProxmoxContainerError", ErrorCategory.OperationStopped, null));
|
||||
}
|
||||
}
|
||||
|
||||
private List<ProxmoxNode> GetNodes()
|
||||
{
|
||||
var response = Connection.GetJson("/nodes");
|
||||
var data = response["data"];
|
||||
|
||||
var nodes = new List<ProxmoxNode>();
|
||||
foreach (var item in data)
|
||||
{
|
||||
var node = item.ToObject<ProxmoxNode>();
|
||||
nodes.Add(node);
|
||||
}
|
||||
|
||||
return nodes;
|
||||
}
|
||||
|
||||
private List<ProxmoxContainer> GetContainers(string node)
|
||||
{
|
||||
var response = Connection.GetJson($"/nodes/{node}/lxc");
|
||||
var data = response["data"];
|
||||
|
||||
var containers = new List<ProxmoxContainer>();
|
||||
foreach (var item in data)
|
||||
{
|
||||
var container = item.ToObject<ProxmoxContainer>();
|
||||
container.Node = node;
|
||||
containers.Add(container);
|
||||
}
|
||||
|
||||
return containers;
|
||||
}
|
||||
|
||||
private ProxmoxContainer GetContainer(string node, int ctid)
|
||||
{
|
||||
try
|
||||
{
|
||||
var response = Connection.GetJson($"/nodes/{node}/lxc/{ctid}/status/current");
|
||||
var data = response["data"];
|
||||
|
||||
var container = data.ToObject<ProxmoxContainer>();
|
||||
container.Node = node;
|
||||
container.CTID = ctid;
|
||||
|
||||
// Get additional configuration
|
||||
var configResponse = Connection.GetJson($"/nodes/{node}/lxc/{ctid}/config");
|
||||
var configData = configResponse["data"];
|
||||
|
||||
container.Config = configData.ToObject<Dictionary<string, object>>();
|
||||
|
||||
return container;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// Container not found on this node
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private List<ProxmoxContainer> FilterContainersByName(List<ProxmoxContainer> containers, string namePattern)
|
||||
{
|
||||
// Check if the pattern is a regex
|
||||
if (IsRegexPattern(namePattern))
|
||||
{
|
||||
var regex = new Regex(namePattern);
|
||||
return containers.Where(c => regex.IsMatch(c.Name)).ToList();
|
||||
}
|
||||
|
||||
// Otherwise, treat it as a wildcard pattern
|
||||
return containers.Where(c => IsWildcardMatch(c.Name, namePattern)).ToList();
|
||||
}
|
||||
|
||||
private bool IsRegexPattern(string pattern)
|
||||
{
|
||||
// Simple heuristic: if the pattern contains regex-specific characters, treat it as regex
|
||||
return pattern.StartsWith("^") || pattern.EndsWith("$") ||
|
||||
pattern.Contains("(") || pattern.Contains(")") ||
|
||||
pattern.Contains("[") || pattern.Contains("]") ||
|
||||
pattern.Contains("\\");
|
||||
}
|
||||
|
||||
private bool IsWildcardMatch(string input, string pattern)
|
||||
{
|
||||
// Convert wildcard pattern to regex
|
||||
string regexPattern = "^" + Regex.Escape(pattern)
|
||||
.Replace("\\*", ".*")
|
||||
.Replace("\\?", ".") + "$";
|
||||
|
||||
return Regex.IsMatch(input, regexPattern, RegexOptions.IgnoreCase);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,242 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Management.Automation;
|
||||
using System.Text.RegularExpressions;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using PSProxmox.Models;
|
||||
using PSProxmox.Session;
|
||||
|
||||
namespace PSProxmox.Cmdlets
|
||||
{
|
||||
/// <summary>
|
||||
/// <para type="synopsis">Gets TurnKey Linux templates for Proxmox LXC containers</para>
|
||||
/// <para type="description">Gets TurnKey Linux templates for Proxmox LXC containers from a Proxmox server</para>
|
||||
/// <para type="description">If no parameters are specified, all templates are returned</para>
|
||||
/// <para type="description">If a node is specified, only templates available on that node are returned</para>
|
||||
/// <para type="description">If a name is specified, only templates with that name are returned (supports wildcards and regex)</para>
|
||||
/// </summary>
|
||||
/// <example>
|
||||
/// <code>Get-ProxmoxTurnKeyTemplate</code>
|
||||
/// <para>Gets all TurnKey Linux templates from the Proxmox server</para>
|
||||
/// </example>
|
||||
/// <example>
|
||||
/// <code>Get-ProxmoxTurnKeyTemplate -Node "pve1"</code>
|
||||
/// <para>Gets all TurnKey Linux templates available on node pve1</para>
|
||||
/// </example>
|
||||
/// <example>
|
||||
/// <code>Get-ProxmoxTurnKeyTemplate -Name "wordpress*"</code>
|
||||
/// <para>Gets all TurnKey Linux templates with names starting with "wordpress" (wildcard)</para>
|
||||
/// </example>
|
||||
/// <example>
|
||||
/// <code>Get-ProxmoxTurnKeyTemplate -Name "^wordpress\d+$"</code>
|
||||
/// <para>Gets all TurnKey Linux templates with names matching the regex pattern "^wordpress\d+$"</para>
|
||||
/// </example>
|
||||
[Cmdlet(VerbsCommon.Get, "ProxmoxTurnKeyTemplate")]
|
||||
[OutputType(typeof(ProxmoxTurnKeyTemplate))]
|
||||
public class GetProxmoxTurnKeyTemplateCmdlet : ProxmoxCmdlet
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the node name
|
||||
/// </summary>
|
||||
[Parameter(Position = 0, ValueFromPipelineByPropertyName = true)]
|
||||
public string Node { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the template name (supports wildcards and regex)
|
||||
/// </summary>
|
||||
[Parameter(Position = 1, ValueFromPipelineByPropertyName = true)]
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether to include downloaded templates
|
||||
/// </summary>
|
||||
[Parameter(Mandatory = false)]
|
||||
public SwitchParameter IncludeDownloaded { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Processes the cmdlet
|
||||
/// </summary>
|
||||
protected override void ProcessRecord()
|
||||
{
|
||||
base.ProcessRecord();
|
||||
|
||||
try
|
||||
{
|
||||
if (string.IsNullOrEmpty(Node))
|
||||
{
|
||||
// Get all nodes
|
||||
var nodes = GetNodes();
|
||||
var allTemplates = new List<ProxmoxTurnKeyTemplate>();
|
||||
|
||||
foreach (var node in nodes)
|
||||
{
|
||||
var templates = GetTemplates(node.Name);
|
||||
allTemplates.AddRange(templates);
|
||||
}
|
||||
|
||||
// Remove duplicates
|
||||
allTemplates = allTemplates.GroupBy(t => t.Name).Select(g => g.First()).ToList();
|
||||
|
||||
// Filter by name if specified
|
||||
if (!string.IsNullOrEmpty(Name))
|
||||
{
|
||||
allTemplates = FilterTemplatesByName(allTemplates, Name);
|
||||
}
|
||||
|
||||
WriteObject(allTemplates, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Get templates for the specified node
|
||||
var templates = GetTemplates(Node);
|
||||
|
||||
// Filter by name if specified
|
||||
if (!string.IsNullOrEmpty(Name))
|
||||
{
|
||||
templates = FilterTemplatesByName(templates, Name);
|
||||
}
|
||||
|
||||
WriteObject(templates, true);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
WriteError(new ErrorRecord(ex, "GetProxmoxTurnKeyTemplateError", ErrorCategory.OperationStopped, null));
|
||||
}
|
||||
}
|
||||
|
||||
private List<ProxmoxNode> GetNodes()
|
||||
{
|
||||
var response = Connection.GetJson("/nodes");
|
||||
var data = response["data"];
|
||||
|
||||
var nodes = new List<ProxmoxNode>();
|
||||
foreach (var item in data)
|
||||
{
|
||||
var node = item.ToObject<ProxmoxNode>();
|
||||
nodes.Add(node);
|
||||
}
|
||||
|
||||
return nodes;
|
||||
}
|
||||
|
||||
private List<ProxmoxTurnKeyTemplate> GetTemplates(string node)
|
||||
{
|
||||
var templates = new List<ProxmoxTurnKeyTemplate>();
|
||||
|
||||
try
|
||||
{
|
||||
// Get available templates from the appliance info
|
||||
var response = Connection.GetJson($"/nodes/{node}/aplinfo");
|
||||
var data = response["data"];
|
||||
|
||||
foreach (var item in data)
|
||||
{
|
||||
// Only include TurnKey templates
|
||||
if (item["package"] != null && item["package"].ToString().Contains("turnkey"))
|
||||
{
|
||||
var template = item.ToObject<ProxmoxTurnKeyTemplate>();
|
||||
templates.Add(template);
|
||||
}
|
||||
}
|
||||
|
||||
// Get downloaded templates if requested
|
||||
if (IncludeDownloaded.IsPresent)
|
||||
{
|
||||
var storages = GetStorages(node);
|
||||
foreach (var storage in storages)
|
||||
{
|
||||
try
|
||||
{
|
||||
var contentResponse = Connection.GetJson($"/nodes/{node}/storage/{storage.Storage}/content");
|
||||
var contentData = contentResponse["data"];
|
||||
|
||||
foreach (var item in contentData)
|
||||
{
|
||||
if (item["content"] != null && item["content"].ToString() == "vztmpl" &&
|
||||
item["volid"] != null && item["volid"].ToString().Contains("turnkey"))
|
||||
{
|
||||
var volid = item["volid"].ToString();
|
||||
var name = System.IO.Path.GetFileNameWithoutExtension(volid.Split('/').Last());
|
||||
|
||||
// Check if this template is already in the list
|
||||
if (!templates.Any(t => t.Name == name))
|
||||
{
|
||||
var template = new ProxmoxTurnKeyTemplate
|
||||
{
|
||||
Name = name,
|
||||
Title = name,
|
||||
Description = "Downloaded template",
|
||||
Source = storage.Storage,
|
||||
Location = volid
|
||||
};
|
||||
|
||||
templates.Add(template);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// Skip this storage if there's an error
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// Skip this node if there's an error
|
||||
}
|
||||
|
||||
return templates;
|
||||
}
|
||||
|
||||
private List<ProxmoxStorage> GetStorages(string node)
|
||||
{
|
||||
var response = Connection.GetJson($"/nodes/{node}/storage");
|
||||
var data = response["data"];
|
||||
|
||||
var storages = new List<ProxmoxStorage>();
|
||||
foreach (var item in data)
|
||||
{
|
||||
var storage = item.ToObject<ProxmoxStorage>();
|
||||
storages.Add(storage);
|
||||
}
|
||||
|
||||
return storages;
|
||||
}
|
||||
|
||||
private List<ProxmoxTurnKeyTemplate> FilterTemplatesByName(List<ProxmoxTurnKeyTemplate> templates, string namePattern)
|
||||
{
|
||||
// Check if the pattern is a regex
|
||||
if (IsRegexPattern(namePattern))
|
||||
{
|
||||
var regex = new Regex(namePattern);
|
||||
return templates.Where(t => regex.IsMatch(t.Name)).ToList();
|
||||
}
|
||||
|
||||
// Otherwise, treat it as a wildcard pattern
|
||||
return templates.Where(t => IsWildcardMatch(t.Name, namePattern)).ToList();
|
||||
}
|
||||
|
||||
private bool IsRegexPattern(string pattern)
|
||||
{
|
||||
// Simple heuristic: if the pattern contains regex-specific characters, treat it as regex
|
||||
return pattern.StartsWith("^") || pattern.EndsWith("$") ||
|
||||
pattern.Contains("(") || pattern.Contains(")") ||
|
||||
pattern.Contains("[") || pattern.Contains("]") ||
|
||||
pattern.Contains("\\");
|
||||
}
|
||||
|
||||
private bool IsWildcardMatch(string input, string pattern)
|
||||
{
|
||||
// Convert wildcard pattern to regex
|
||||
string regexPattern = "^" + Regex.Escape(pattern)
|
||||
.Replace("\\*", ".*")
|
||||
.Replace("\\?", ".") + "$";
|
||||
|
||||
return Regex.IsMatch(input, regexPattern, RegexOptions.IgnoreCase);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
using System.Management.Automation;
|
||||
using PSProxmox.Models;
|
||||
|
||||
namespace PSProxmox.Cmdlets
|
||||
{
|
||||
/// <summary>
|
||||
/// <para type="synopsis">Creates a new Proxmox container builder</para>
|
||||
/// <para type="description">Creates a new Proxmox container builder for creating LXC containers</para>
|
||||
/// </summary>
|
||||
/// <example>
|
||||
/// <code>$builder = New-ProxmoxContainerBuilder -Name "web-container"
|
||||
/// $builder.WithOSTemplate("local:vztmpl/ubuntu-20.04-standard_20.04-1_amd64.tar.gz")
|
||||
/// .WithStorage("local-lvm")
|
||||
/// .WithMemory(512)
|
||||
/// .WithSwap(512)
|
||||
/// .WithCores(1)
|
||||
/// .WithDiskSize(8)
|
||||
/// .WithUnprivileged($true)
|
||||
/// .WithStartOnBoot($true)
|
||||
/// .WithStart($true)
|
||||
/// New-ProxmoxContainer -Node "pve1" -Builder $builder</code>
|
||||
/// <para>Creates a new container builder and uses it to create a container</para>
|
||||
/// </example>
|
||||
[Cmdlet(VerbsCommon.New, "ProxmoxContainerBuilder")]
|
||||
[OutputType(typeof(ProxmoxContainerBuilder))]
|
||||
public class NewProxmoxContainerBuilderCmdlet : PSCmdlet
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the container name
|
||||
/// </summary>
|
||||
[Parameter(Mandatory = true, Position = 0)]
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Processes the cmdlet
|
||||
/// </summary>
|
||||
protected override void ProcessRecord()
|
||||
{
|
||||
var builder = new ProxmoxContainerBuilder(Name);
|
||||
WriteObject(builder);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,298 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Management.Automation;
|
||||
using System.Security;
|
||||
using PSProxmox.Models;
|
||||
using PSProxmox.Session;
|
||||
|
||||
namespace PSProxmox.Cmdlets
|
||||
{
|
||||
/// <summary>
|
||||
/// <para type="synopsis">Creates a new Proxmox LXC container</para>
|
||||
/// <para type="description">Creates a new Proxmox LXC container on a Proxmox server</para>
|
||||
/// </summary>
|
||||
/// <example>
|
||||
/// <code>New-ProxmoxContainer -Node "pve1" -Name "web-container" -OSTemplate "local:vztmpl/ubuntu-20.04-standard_20.04-1_amd64.tar.gz" -Storage "local-lvm" -Memory 512 -Swap 512 -Cores 1 -DiskSize 8</code>
|
||||
/// <para>Creates a new LXC container on node pve1</para>
|
||||
/// </example>
|
||||
/// <example>
|
||||
/// <code>$builder = New-ProxmoxContainerBuilder -Name "web-container"
|
||||
/// $builder.WithOSTemplate("local:vztmpl/ubuntu-20.04-standard_20.04-1_amd64.tar.gz")
|
||||
/// .WithStorage("local-lvm")
|
||||
/// .WithMemory(512)
|
||||
/// .WithSwap(512)
|
||||
/// .WithCores(1)
|
||||
/// .WithDiskSize(8)
|
||||
/// .WithUnprivileged($true)
|
||||
/// .WithStartOnBoot($true)
|
||||
/// .WithStart($true)
|
||||
/// New-ProxmoxContainer -Node "pve1" -Builder $builder</code>
|
||||
/// <para>Creates a new LXC container on node pve1 using a builder</para>
|
||||
/// </example>
|
||||
[Cmdlet(VerbsCommon.New, "ProxmoxContainer")]
|
||||
[OutputType(typeof(ProxmoxContainer))]
|
||||
public class NewProxmoxContainerCmdlet : ProxmoxCmdlet
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the node name
|
||||
/// </summary>
|
||||
[Parameter(Mandatory = true, Position = 0, ValueFromPipelineByPropertyName = true)]
|
||||
public string Node { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the container builder
|
||||
/// </summary>
|
||||
[Parameter(Mandatory = false, Position = 1, ValueFromPipeline = true)]
|
||||
public ProxmoxContainerBuilder Builder { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the container ID
|
||||
/// </summary>
|
||||
[Parameter(Mandatory = false, ValueFromPipelineByPropertyName = true)]
|
||||
public int? CTID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the container name
|
||||
/// </summary>
|
||||
[Parameter(Mandatory = false, ValueFromPipelineByPropertyName = true)]
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the container OS template
|
||||
/// </summary>
|
||||
[Parameter(Mandatory = false, ValueFromPipelineByPropertyName = true)]
|
||||
public string OSTemplate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the container storage
|
||||
/// </summary>
|
||||
[Parameter(Mandatory = false, ValueFromPipelineByPropertyName = true)]
|
||||
public string Storage { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the container memory limit in MB
|
||||
/// </summary>
|
||||
[Parameter(Mandatory = false, ValueFromPipelineByPropertyName = true)]
|
||||
public int? Memory { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the container swap limit in MB
|
||||
/// </summary>
|
||||
[Parameter(Mandatory = false, ValueFromPipelineByPropertyName = true)]
|
||||
public int? Swap { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the container CPU cores
|
||||
/// </summary>
|
||||
[Parameter(Mandatory = false, ValueFromPipelineByPropertyName = true)]
|
||||
public int? Cores { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the container disk size in GB
|
||||
/// </summary>
|
||||
[Parameter(Mandatory = false, ValueFromPipelineByPropertyName = true)]
|
||||
public int? DiskSize { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the container is unprivileged
|
||||
/// </summary>
|
||||
[Parameter(Mandatory = false, ValueFromPipelineByPropertyName = true)]
|
||||
public SwitchParameter Unprivileged { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the container password
|
||||
/// </summary>
|
||||
[Parameter(Mandatory = false, ValueFromPipelineByPropertyName = true)]
|
||||
public SecureString Password { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the container SSH public key
|
||||
/// </summary>
|
||||
[Parameter(Mandatory = false, ValueFromPipelineByPropertyName = true)]
|
||||
public string SSHKey { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the container description
|
||||
/// </summary>
|
||||
[Parameter(Mandatory = false, ValueFromPipelineByPropertyName = true)]
|
||||
public string Description { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether to start the container on boot
|
||||
/// </summary>
|
||||
[Parameter(Mandatory = false, ValueFromPipelineByPropertyName = true)]
|
||||
public SwitchParameter StartOnBoot { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether to start the container after creation
|
||||
/// </summary>
|
||||
[Parameter(Mandatory = false, ValueFromPipelineByPropertyName = true)]
|
||||
public SwitchParameter Start { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Processes the cmdlet
|
||||
/// </summary>
|
||||
protected override void ProcessRecord()
|
||||
{
|
||||
base.ProcessRecord();
|
||||
|
||||
try
|
||||
{
|
||||
Dictionary<string, object> parameters;
|
||||
|
||||
if (Builder != null)
|
||||
{
|
||||
// Use the builder parameters
|
||||
parameters = Builder.Parameters;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Build parameters from individual properties
|
||||
parameters = new Dictionary<string, object>();
|
||||
|
||||
if (!string.IsNullOrEmpty(Name))
|
||||
{
|
||||
parameters["hostname"] = Name;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(OSTemplate))
|
||||
{
|
||||
parameters["ostemplate"] = OSTemplate;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(Storage))
|
||||
{
|
||||
parameters["storage"] = Storage;
|
||||
}
|
||||
|
||||
if (Memory.HasValue)
|
||||
{
|
||||
parameters["memory"] = Memory.Value;
|
||||
}
|
||||
|
||||
if (Swap.HasValue)
|
||||
{
|
||||
parameters["swap"] = Swap.Value;
|
||||
}
|
||||
|
||||
if (Cores.HasValue)
|
||||
{
|
||||
parameters["cores"] = Cores.Value;
|
||||
}
|
||||
|
||||
if (DiskSize.HasValue && !string.IsNullOrEmpty(Storage))
|
||||
{
|
||||
parameters["rootfs"] = $"{Storage}:{DiskSize.Value}";
|
||||
}
|
||||
|
||||
if (Unprivileged.IsPresent)
|
||||
{
|
||||
parameters["unprivileged"] = 1;
|
||||
}
|
||||
|
||||
if (Password != null)
|
||||
{
|
||||
parameters["password"] = ConvertSecureStringToString(Password);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(SSHKey))
|
||||
{
|
||||
parameters["ssh-public-keys"] = SSHKey;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(Description))
|
||||
{
|
||||
parameters["description"] = Description;
|
||||
}
|
||||
|
||||
if (StartOnBoot.IsPresent)
|
||||
{
|
||||
parameters["onboot"] = 1;
|
||||
}
|
||||
|
||||
if (Start.IsPresent)
|
||||
{
|
||||
parameters["start"] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Add CTID if specified
|
||||
if (CTID.HasValue)
|
||||
{
|
||||
parameters["vmid"] = CTID.Value;
|
||||
}
|
||||
|
||||
// Create the container
|
||||
var response = Connection.PostJson($"/nodes/{Node}/lxc", parameters);
|
||||
var data = response["data"];
|
||||
var ctid = (int)data["vmid"];
|
||||
|
||||
// Wait for the task to complete
|
||||
var taskId = (string)data["upid"];
|
||||
var taskStatus = WaitForTask(Node, taskId);
|
||||
|
||||
if (taskStatus != "OK")
|
||||
{
|
||||
throw new Exception($"Failed to create container: {taskStatus}");
|
||||
}
|
||||
|
||||
// Get the created container
|
||||
var container = GetContainer(Node, ctid);
|
||||
WriteObject(container);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
WriteError(new ErrorRecord(ex, "NewProxmoxContainerError", ErrorCategory.OperationStopped, null));
|
||||
}
|
||||
}
|
||||
|
||||
private string WaitForTask(string node, string taskId)
|
||||
{
|
||||
var status = "";
|
||||
var attempts = 0;
|
||||
var maxAttempts = 60; // Wait up to 60 seconds
|
||||
|
||||
while (attempts < maxAttempts)
|
||||
{
|
||||
var response = Connection.GetJson($"/nodes/{node}/tasks/{taskId}/status");
|
||||
var data = response["data"];
|
||||
status = (string)data["status"];
|
||||
|
||||
if (status == "stopped")
|
||||
{
|
||||
return (string)data["exitstatus"];
|
||||
}
|
||||
|
||||
System.Threading.Thread.Sleep(1000);
|
||||
attempts++;
|
||||
}
|
||||
|
||||
throw new Exception("Timeout waiting for task to complete");
|
||||
}
|
||||
|
||||
private ProxmoxContainer GetContainer(string node, int ctid)
|
||||
{
|
||||
var response = Connection.GetJson($"/nodes/{node}/lxc/{ctid}/status/current");
|
||||
var data = response["data"];
|
||||
|
||||
var container = data.ToObject<ProxmoxContainer>();
|
||||
container.Node = node;
|
||||
container.CTID = ctid;
|
||||
|
||||
return container;
|
||||
}
|
||||
|
||||
private string ConvertSecureStringToString(SecureString secureString)
|
||||
{
|
||||
var ptr = System.Runtime.InteropServices.Marshal.SecureStringToBSTR(secureString);
|
||||
try
|
||||
{
|
||||
return System.Runtime.InteropServices.Marshal.PtrToStringBSTR(ptr);
|
||||
}
|
||||
finally
|
||||
{
|
||||
System.Runtime.InteropServices.Marshal.ZeroFreeBSTR(ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,277 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Management.Automation;
|
||||
using System.Security;
|
||||
using PSProxmox.Models;
|
||||
using PSProxmox.Session;
|
||||
|
||||
namespace PSProxmox.Cmdlets
|
||||
{
|
||||
/// <summary>
|
||||
/// <para type="synopsis">Creates a new Proxmox LXC container from a TurnKey Linux template</para>
|
||||
/// <para type="description">Creates a new Proxmox LXC container from a TurnKey Linux template on a Proxmox server</para>
|
||||
/// </summary>
|
||||
/// <example>
|
||||
/// <code>New-ProxmoxContainerFromTurnKey -Node "pve1" -Name "wordpress" -Template "wordpress" -Storage "local-lvm" -Memory 512 -Cores 1 -DiskSize 8</code>
|
||||
/// <para>Creates a new LXC container from the WordPress TurnKey Linux template on node pve1</para>
|
||||
/// </example>
|
||||
[Cmdlet(VerbsCommon.New, "ProxmoxContainerFromTurnKey")]
|
||||
[OutputType(typeof(ProxmoxContainer))]
|
||||
public class NewProxmoxContainerFromTurnKeyCmdlet : ProxmoxCmdlet
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the node name
|
||||
/// </summary>
|
||||
[Parameter(Mandatory = true, Position = 0, ValueFromPipelineByPropertyName = true)]
|
||||
public string Node { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the container name
|
||||
/// </summary>
|
||||
[Parameter(Mandatory = true, Position = 1, ValueFromPipelineByPropertyName = true)]
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the TurnKey template name
|
||||
/// </summary>
|
||||
[Parameter(Mandatory = true, Position = 2, ValueFromPipelineByPropertyName = true)]
|
||||
public string Template { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the container ID
|
||||
/// </summary>
|
||||
[Parameter(Mandatory = false, ValueFromPipelineByPropertyName = true)]
|
||||
public int? CTID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the storage name
|
||||
/// </summary>
|
||||
[Parameter(Mandatory = false, ValueFromPipelineByPropertyName = true)]
|
||||
public string Storage { get; set; } = "local";
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the container memory limit in MB
|
||||
/// </summary>
|
||||
[Parameter(Mandatory = false, ValueFromPipelineByPropertyName = true)]
|
||||
public int Memory { get; set; } = 512;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the container swap limit in MB
|
||||
/// </summary>
|
||||
[Parameter(Mandatory = false, ValueFromPipelineByPropertyName = true)]
|
||||
public int Swap { get; set; } = 512;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the container CPU cores
|
||||
/// </summary>
|
||||
[Parameter(Mandatory = false, ValueFromPipelineByPropertyName = true)]
|
||||
public int Cores { get; set; } = 1;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the container disk size in GB
|
||||
/// </summary>
|
||||
[Parameter(Mandatory = false, ValueFromPipelineByPropertyName = true)]
|
||||
public int DiskSize { get; set; } = 8;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the container is unprivileged
|
||||
/// </summary>
|
||||
[Parameter(Mandatory = false, ValueFromPipelineByPropertyName = true)]
|
||||
public SwitchParameter Unprivileged { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the container password
|
||||
/// </summary>
|
||||
[Parameter(Mandatory = false, ValueFromPipelineByPropertyName = true)]
|
||||
public SecureString Password { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the container SSH public key
|
||||
/// </summary>
|
||||
[Parameter(Mandatory = false, ValueFromPipelineByPropertyName = true)]
|
||||
public string SSHKey { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether to start the container on boot
|
||||
/// </summary>
|
||||
[Parameter(Mandatory = false, ValueFromPipelineByPropertyName = true)]
|
||||
public SwitchParameter StartOnBoot { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether to start the container after creation
|
||||
/// </summary>
|
||||
[Parameter(Mandatory = false, ValueFromPipelineByPropertyName = true)]
|
||||
public SwitchParameter Start { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Processes the cmdlet
|
||||
/// </summary>
|
||||
protected override void ProcessRecord()
|
||||
{
|
||||
base.ProcessRecord();
|
||||
|
||||
try
|
||||
{
|
||||
// Get the template
|
||||
var templatePath = GetTemplatePath(Node, Template, Storage);
|
||||
if (string.IsNullOrEmpty(templatePath))
|
||||
{
|
||||
// Try to download the template
|
||||
WriteVerbose($"Template '{Template}' not found, attempting to download...");
|
||||
var downloadCmdlet = new SaveProxmoxTurnKeyTemplateCmdlet
|
||||
{
|
||||
Connection = Connection,
|
||||
Node = Node,
|
||||
Name = Template,
|
||||
Storage = Storage
|
||||
};
|
||||
|
||||
var result = InvokeCommand.InvokeScript(false, ScriptBlock.Create("param($cmdlet) & { $cmdlet.ProcessRecord(); return $cmdlet.CommandRuntime.ToString() }"), null, downloadCmdlet).FirstOrDefault();
|
||||
templatePath = result?.ToString();
|
||||
|
||||
if (string.IsNullOrEmpty(templatePath))
|
||||
{
|
||||
throw new Exception($"Failed to download template '{Template}'");
|
||||
}
|
||||
}
|
||||
|
||||
// Create the container
|
||||
var parameters = new Dictionary<string, object>
|
||||
{
|
||||
{ "hostname", Name },
|
||||
{ "ostemplate", templatePath },
|
||||
{ "storage", Storage },
|
||||
{ "memory", Memory },
|
||||
{ "swap", Swap },
|
||||
{ "cores", Cores },
|
||||
{ "rootfs", $"{Storage}:{DiskSize}" }
|
||||
};
|
||||
|
||||
if (CTID.HasValue)
|
||||
{
|
||||
parameters["vmid"] = CTID.Value;
|
||||
}
|
||||
|
||||
if (Unprivileged.IsPresent)
|
||||
{
|
||||
parameters["unprivileged"] = 1;
|
||||
}
|
||||
|
||||
if (Password != null)
|
||||
{
|
||||
parameters["password"] = ConvertSecureStringToString(Password);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(SSHKey))
|
||||
{
|
||||
parameters["ssh-public-keys"] = SSHKey;
|
||||
}
|
||||
|
||||
if (StartOnBoot.IsPresent)
|
||||
{
|
||||
parameters["onboot"] = 1;
|
||||
}
|
||||
|
||||
if (Start.IsPresent)
|
||||
{
|
||||
parameters["start"] = 1;
|
||||
}
|
||||
|
||||
var response = Connection.PostJson($"/nodes/{Node}/lxc", parameters);
|
||||
var data = response["data"];
|
||||
var ctid = (int)data["vmid"];
|
||||
|
||||
// Wait for the task to complete
|
||||
var taskId = (string)data["upid"];
|
||||
var taskStatus = WaitForTask(Node, taskId);
|
||||
|
||||
if (taskStatus != "OK")
|
||||
{
|
||||
throw new Exception($"Failed to create container: {taskStatus}");
|
||||
}
|
||||
|
||||
// Get the created container
|
||||
var container = GetContainer(Node, ctid);
|
||||
WriteObject(container);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
WriteError(new ErrorRecord(ex, "NewProxmoxContainerFromTurnKeyError", ErrorCategory.OperationStopped, null));
|
||||
}
|
||||
}
|
||||
|
||||
private string GetTemplatePath(string node, string templateName, string storage)
|
||||
{
|
||||
try
|
||||
{
|
||||
var response = Connection.GetJson($"/nodes/{node}/storage/{storage}/content");
|
||||
var data = response["data"];
|
||||
|
||||
foreach (var item in data)
|
||||
{
|
||||
if (item["content"] != null && item["content"].ToString() == "vztmpl" &&
|
||||
item["volid"] != null && item["volid"].ToString().Contains(templateName))
|
||||
{
|
||||
return item["volid"].ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// Ignore errors and return null
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private string WaitForTask(string node, string taskId)
|
||||
{
|
||||
var status = "";
|
||||
var attempts = 0;
|
||||
var maxAttempts = 60; // Wait up to 60 seconds
|
||||
|
||||
while (attempts < maxAttempts)
|
||||
{
|
||||
var response = Connection.GetJson($"/nodes/{node}/tasks/{taskId}/status");
|
||||
var data = response["data"];
|
||||
status = (string)data["status"];
|
||||
|
||||
if (status == "stopped")
|
||||
{
|
||||
return (string)data["exitstatus"];
|
||||
}
|
||||
|
||||
System.Threading.Thread.Sleep(1000);
|
||||
attempts++;
|
||||
}
|
||||
|
||||
throw new Exception("Timeout waiting for task to complete");
|
||||
}
|
||||
|
||||
private ProxmoxContainer GetContainer(string node, int ctid)
|
||||
{
|
||||
var response = Connection.GetJson($"/nodes/{node}/lxc/{ctid}/status/current");
|
||||
var data = response["data"];
|
||||
|
||||
var container = data.ToObject<ProxmoxContainer>();
|
||||
container.Node = node;
|
||||
container.CTID = ctid;
|
||||
|
||||
return container;
|
||||
}
|
||||
|
||||
private string ConvertSecureStringToString(SecureString secureString)
|
||||
{
|
||||
var ptr = System.Runtime.InteropServices.Marshal.SecureStringToBSTR(secureString);
|
||||
try
|
||||
{
|
||||
return System.Runtime.InteropServices.Marshal.PtrToStringBSTR(ptr);
|
||||
}
|
||||
finally
|
||||
{
|
||||
System.Runtime.InteropServices.Marshal.ZeroFreeBSTR(ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
using System;
|
||||
using System.Management.Automation;
|
||||
using PSProxmox.Session;
|
||||
|
||||
namespace PSProxmox.Cmdlets
|
||||
{
|
||||
/// <summary>
|
||||
/// <para type="synopsis">Removes a Proxmox LXC container</para>
|
||||
/// <para type="description">Removes a Proxmox LXC container from a Proxmox server</para>
|
||||
/// </summary>
|
||||
/// <example>
|
||||
/// <code>Remove-ProxmoxContainer -Node "pve1" -CTID 100</code>
|
||||
/// <para>Removes the container with CTID 100 from node pve1</para>
|
||||
/// </example>
|
||||
/// <example>
|
||||
/// <code>Remove-ProxmoxContainer -Node "pve1" -CTID 100 -Confirm:$false</code>
|
||||
/// <para>Removes the container with CTID 100 from node pve1 without confirmation</para>
|
||||
/// </example>
|
||||
[Cmdlet(VerbsCommon.Remove, "ProxmoxContainer", SupportsShouldProcess = true, ConfirmImpact = ConfirmImpact.High)]
|
||||
public class RemoveProxmoxContainerCmdlet : ProxmoxCmdlet
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the node name
|
||||
/// </summary>
|
||||
[Parameter(Mandatory = true, Position = 0, ValueFromPipelineByPropertyName = true)]
|
||||
public string Node { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the container ID
|
||||
/// </summary>
|
||||
[Parameter(Mandatory = true, Position = 1, ValueFromPipelineByPropertyName = true)]
|
||||
public int CTID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether to force removal
|
||||
/// </summary>
|
||||
[Parameter(Mandatory = false)]
|
||||
public SwitchParameter Force { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Processes the cmdlet
|
||||
/// </summary>
|
||||
protected override void ProcessRecord()
|
||||
{
|
||||
base.ProcessRecord();
|
||||
|
||||
try
|
||||
{
|
||||
if (ShouldProcess($"Container {CTID} on node {Node}", "Remove"))
|
||||
{
|
||||
var parameters = new System.Collections.Generic.Dictionary<string, object>();
|
||||
|
||||
if (Force.IsPresent)
|
||||
{
|
||||
parameters["force"] = 1;
|
||||
}
|
||||
|
||||
var response = Connection.DeleteJson($"/nodes/{Node}/lxc/{CTID}", parameters);
|
||||
var data = response["data"];
|
||||
var taskId = (string)data["upid"];
|
||||
|
||||
var taskStatus = WaitForTask(Node, taskId);
|
||||
if (taskStatus != "OK")
|
||||
{
|
||||
throw new Exception($"Failed to remove container: {taskStatus}");
|
||||
}
|
||||
|
||||
WriteVerbose($"Container {CTID} on node {Node} removed successfully");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
WriteError(new ErrorRecord(ex, "RemoveProxmoxContainerError", ErrorCategory.OperationStopped, null));
|
||||
}
|
||||
}
|
||||
|
||||
private string WaitForTask(string node, string taskId)
|
||||
{
|
||||
var status = "";
|
||||
var attempts = 0;
|
||||
var maxAttempts = 60; // Wait up to 60 seconds
|
||||
|
||||
while (attempts < maxAttempts)
|
||||
{
|
||||
var response = Connection.GetJson($"/nodes/{node}/tasks/{taskId}/status");
|
||||
var data = response["data"];
|
||||
status = (string)data["status"];
|
||||
|
||||
if (status == "stopped")
|
||||
{
|
||||
return (string)data["exitstatus"];
|
||||
}
|
||||
|
||||
System.Threading.Thread.Sleep(1000);
|
||||
attempts++;
|
||||
}
|
||||
|
||||
throw new Exception("Timeout waiting for task to complete");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Management.Automation;
|
||||
using PSProxmox.Models;
|
||||
using PSProxmox.Session;
|
||||
|
||||
namespace PSProxmox.Cmdlets
|
||||
{
|
||||
/// <summary>
|
||||
/// <para type="synopsis">Restarts a Proxmox LXC container</para>
|
||||
/// <para type="description">Restarts a Proxmox LXC container on a Proxmox server</para>
|
||||
/// </summary>
|
||||
/// <example>
|
||||
/// <code>Restart-ProxmoxContainer -Node "pve1" -CTID 100</code>
|
||||
/// <para>Restarts the container with CTID 100 on node pve1</para>
|
||||
/// </example>
|
||||
[Cmdlet(VerbsLifecycle.Restart, "ProxmoxContainer")]
|
||||
[OutputType(typeof(ProxmoxContainer))]
|
||||
public class RestartProxmoxContainerCmdlet : ProxmoxCmdlet
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the node name
|
||||
/// </summary>
|
||||
[Parameter(Mandatory = true, Position = 0, ValueFromPipelineByPropertyName = true)]
|
||||
public string Node { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the container ID
|
||||
/// </summary>
|
||||
[Parameter(Mandatory = true, Position = 1, ValueFromPipelineByPropertyName = true)]
|
||||
public int CTID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether to wait for the container to restart
|
||||
/// </summary>
|
||||
[Parameter(Mandatory = false)]
|
||||
public SwitchParameter Wait { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the timeout in seconds
|
||||
/// </summary>
|
||||
[Parameter(Mandatory = false)]
|
||||
public int Timeout { get; set; } = 60;
|
||||
|
||||
/// <summary>
|
||||
/// Processes the cmdlet
|
||||
/// </summary>
|
||||
protected override void ProcessRecord()
|
||||
{
|
||||
base.ProcessRecord();
|
||||
|
||||
try
|
||||
{
|
||||
var parameters = new Dictionary<string, object>();
|
||||
|
||||
if (Timeout > 0)
|
||||
{
|
||||
parameters["timeout"] = Timeout;
|
||||
}
|
||||
|
||||
var response = Connection.PostJson($"/nodes/{Node}/lxc/{CTID}/status/restart", parameters);
|
||||
var data = response["data"];
|
||||
var taskId = (string)data["upid"];
|
||||
|
||||
if (Wait.IsPresent)
|
||||
{
|
||||
var taskStatus = WaitForTask(Node, taskId);
|
||||
if (taskStatus != "OK")
|
||||
{
|
||||
throw new Exception($"Failed to restart container: {taskStatus}");
|
||||
}
|
||||
|
||||
// Get the container status
|
||||
var container = GetContainer(Node, CTID);
|
||||
WriteObject(container);
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteVerbose($"Container {CTID} on node {Node} restart initiated");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
WriteError(new ErrorRecord(ex, "RestartProxmoxContainerError", ErrorCategory.OperationStopped, null));
|
||||
}
|
||||
}
|
||||
|
||||
private string WaitForTask(string node, string taskId)
|
||||
{
|
||||
var status = "";
|
||||
var attempts = 0;
|
||||
var maxAttempts = Timeout > 0 ? Timeout : 60;
|
||||
|
||||
while (attempts < maxAttempts)
|
||||
{
|
||||
var response = Connection.GetJson($"/nodes/{node}/tasks/{taskId}/status");
|
||||
var data = response["data"];
|
||||
status = (string)data["status"];
|
||||
|
||||
if (status == "stopped")
|
||||
{
|
||||
return (string)data["exitstatus"];
|
||||
}
|
||||
|
||||
System.Threading.Thread.Sleep(1000);
|
||||
attempts++;
|
||||
}
|
||||
|
||||
throw new Exception("Timeout waiting for task to complete");
|
||||
}
|
||||
|
||||
private ProxmoxContainer GetContainer(string node, int ctid)
|
||||
{
|
||||
var response = Connection.GetJson($"/nodes/{node}/lxc/{ctid}/status/current");
|
||||
var data = response["data"];
|
||||
|
||||
var container = data.ToObject<ProxmoxContainer>();
|
||||
container.Node = node;
|
||||
container.CTID = ctid;
|
||||
|
||||
return container;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,206 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Management.Automation;
|
||||
using PSProxmox.Models;
|
||||
using PSProxmox.Session;
|
||||
|
||||
namespace PSProxmox.Cmdlets
|
||||
{
|
||||
/// <summary>
|
||||
/// <para type="synopsis">Downloads a TurnKey Linux template to a Proxmox server</para>
|
||||
/// <para type="description">Downloads a TurnKey Linux template to a Proxmox server for use with LXC containers</para>
|
||||
/// </summary>
|
||||
/// <example>
|
||||
/// <code>Save-ProxmoxTurnKeyTemplate -Node "pve1" -Name "wordpress" -Storage "local"</code>
|
||||
/// <para>Downloads the WordPress TurnKey Linux template to the local storage on node pve1</para>
|
||||
/// </example>
|
||||
[Cmdlet(VerbsData.Save, "ProxmoxTurnKeyTemplate")]
|
||||
[OutputType(typeof(string))]
|
||||
public class SaveProxmoxTurnKeyTemplateCmdlet : ProxmoxCmdlet
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the node name
|
||||
/// </summary>
|
||||
[Parameter(Mandatory = true, Position = 0, ValueFromPipelineByPropertyName = true)]
|
||||
public string Node { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the template name
|
||||
/// </summary>
|
||||
[Parameter(Mandatory = true, Position = 1, ValueFromPipelineByPropertyName = true)]
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the storage name
|
||||
/// </summary>
|
||||
[Parameter(Mandatory = true, Position = 2, ValueFromPipelineByPropertyName = true)]
|
||||
public string Storage { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether to force download even if the template already exists
|
||||
/// </summary>
|
||||
[Parameter(Mandatory = false)]
|
||||
public SwitchParameter Force { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Processes the cmdlet
|
||||
/// </summary>
|
||||
protected override void ProcessRecord()
|
||||
{
|
||||
base.ProcessRecord();
|
||||
|
||||
try
|
||||
{
|
||||
// Get the template information
|
||||
var templates = GetTemplates(Node);
|
||||
var template = templates.FirstOrDefault(t => t.Name.Equals(Name, StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
if (template == null)
|
||||
{
|
||||
throw new Exception($"Template '{Name}' not found");
|
||||
}
|
||||
|
||||
// Check if the template is already downloaded
|
||||
if (!Force.IsPresent)
|
||||
{
|
||||
var existingTemplates = GetDownloadedTemplates(Node, Storage);
|
||||
var existingTemplate = existingTemplates.FirstOrDefault(t => t.Contains(template.Name));
|
||||
|
||||
if (existingTemplate != null)
|
||||
{
|
||||
WriteVerbose($"Template '{Name}' already exists at '{existingTemplate}'");
|
||||
WriteObject(existingTemplate);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Download the template
|
||||
var parameters = new Dictionary<string, object>
|
||||
{
|
||||
{ "template", template.URL },
|
||||
{ "storage", Storage }
|
||||
};
|
||||
|
||||
var response = Connection.PostJson($"/nodes/{Node}/aplinfo", parameters);
|
||||
var data = response["data"];
|
||||
var taskId = (string)data["upid"];
|
||||
|
||||
var taskStatus = WaitForTask(Node, taskId);
|
||||
if (taskStatus != "OK")
|
||||
{
|
||||
throw new Exception($"Failed to download template: {taskStatus}");
|
||||
}
|
||||
|
||||
// Get the downloaded template path
|
||||
var downloadedTemplates = GetDownloadedTemplates(Node, Storage);
|
||||
var downloadedTemplate = downloadedTemplates.FirstOrDefault(t => t.Contains(template.Name));
|
||||
|
||||
if (downloadedTemplate == null)
|
||||
{
|
||||
throw new Exception($"Failed to find downloaded template '{Name}'");
|
||||
}
|
||||
|
||||
WriteVerbose($"Template '{Name}' downloaded to '{downloadedTemplate}'");
|
||||
WriteObject(downloadedTemplate);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
WriteError(new ErrorRecord(ex, "SaveProxmoxTurnKeyTemplateError", ErrorCategory.OperationStopped, null));
|
||||
}
|
||||
}
|
||||
|
||||
private List<ProxmoxTurnKeyTemplate> GetTemplates(string node)
|
||||
{
|
||||
var templates = new List<ProxmoxTurnKeyTemplate>();
|
||||
|
||||
try
|
||||
{
|
||||
// Get available templates from the appliance info
|
||||
var response = Connection.GetJson($"/nodes/{node}/aplinfo");
|
||||
var data = response["data"];
|
||||
|
||||
foreach (var item in data)
|
||||
{
|
||||
// Only include TurnKey templates
|
||||
if (item["package"] != null && item["package"].ToString().Contains("turnkey"))
|
||||
{
|
||||
var template = item.ToObject<ProxmoxTurnKeyTemplate>();
|
||||
templates.Add(template);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new Exception($"Failed to get templates: {ex.Message}");
|
||||
}
|
||||
|
||||
return templates;
|
||||
}
|
||||
|
||||
private List<string> GetDownloadedTemplates(string node, string storage)
|
||||
{
|
||||
var templates = new List<string>();
|
||||
|
||||
try
|
||||
{
|
||||
var response = Connection.GetJson($"/nodes/{node}/storage/{storage}/content");
|
||||
var data = response["data"];
|
||||
|
||||
foreach (var item in data)
|
||||
{
|
||||
if (item["content"] != null && item["content"].ToString() == "vztmpl" &&
|
||||
item["volid"] != null && item["volid"].ToString().Contains("turnkey"))
|
||||
{
|
||||
templates.Add(item["volid"].ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new Exception($"Failed to get downloaded templates: {ex.Message}");
|
||||
}
|
||||
|
||||
return templates;
|
||||
}
|
||||
|
||||
private string WaitForTask(string node, string taskId)
|
||||
{
|
||||
var status = "";
|
||||
var attempts = 0;
|
||||
var maxAttempts = 300; // Wait up to 5 minutes
|
||||
|
||||
while (attempts < maxAttempts)
|
||||
{
|
||||
var response = Connection.GetJson($"/nodes/{node}/tasks/{taskId}/status");
|
||||
var data = response["data"];
|
||||
status = (string)data["status"];
|
||||
|
||||
if (status == "stopped")
|
||||
{
|
||||
return (string)data["exitstatus"];
|
||||
}
|
||||
|
||||
// Show progress
|
||||
if (data["pid"] != null)
|
||||
{
|
||||
var progressResponse = Connection.GetJson($"/nodes/{node}/tasks/{taskId}/log?start=0");
|
||||
var progressData = progressResponse["data"];
|
||||
|
||||
foreach (var item in progressData)
|
||||
{
|
||||
if (item["t"] != null && item["t"].ToString() == "TASK_STATUS")
|
||||
{
|
||||
WriteProgress(new ProgressRecord(1, "Downloading template", item["t"].ToString()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
System.Threading.Thread.Sleep(1000);
|
||||
attempts++;
|
||||
}
|
||||
|
||||
throw new Exception("Timeout waiting for task to complete");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
using System;
|
||||
using System.Management.Automation;
|
||||
using PSProxmox.Models;
|
||||
using PSProxmox.Session;
|
||||
|
||||
namespace PSProxmox.Cmdlets
|
||||
{
|
||||
/// <summary>
|
||||
/// <para type="synopsis">Starts a Proxmox LXC container</para>
|
||||
/// <para type="description">Starts a Proxmox LXC container on a Proxmox server</para>
|
||||
/// </summary>
|
||||
/// <example>
|
||||
/// <code>Start-ProxmoxContainer -Node "pve1" -CTID 100</code>
|
||||
/// <para>Starts the container with CTID 100 on node pve1</para>
|
||||
/// </example>
|
||||
[Cmdlet(VerbsLifecycle.Start, "ProxmoxContainer")]
|
||||
[OutputType(typeof(ProxmoxContainer))]
|
||||
public class StartProxmoxContainerCmdlet : ProxmoxCmdlet
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the node name
|
||||
/// </summary>
|
||||
[Parameter(Mandatory = true, Position = 0, ValueFromPipelineByPropertyName = true)]
|
||||
public string Node { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the container ID
|
||||
/// </summary>
|
||||
[Parameter(Mandatory = true, Position = 1, ValueFromPipelineByPropertyName = true)]
|
||||
public int CTID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether to wait for the container to start
|
||||
/// </summary>
|
||||
[Parameter(Mandatory = false)]
|
||||
public SwitchParameter Wait { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Processes the cmdlet
|
||||
/// </summary>
|
||||
protected override void ProcessRecord()
|
||||
{
|
||||
base.ProcessRecord();
|
||||
|
||||
try
|
||||
{
|
||||
var response = Connection.PostJson($"/nodes/{Node}/lxc/{CTID}/status/start", null);
|
||||
var data = response["data"];
|
||||
var taskId = (string)data["upid"];
|
||||
|
||||
if (Wait.IsPresent)
|
||||
{
|
||||
var taskStatus = WaitForTask(Node, taskId);
|
||||
if (taskStatus != "OK")
|
||||
{
|
||||
throw new Exception($"Failed to start container: {taskStatus}");
|
||||
}
|
||||
|
||||
// Get the container status
|
||||
var container = GetContainer(Node, CTID);
|
||||
WriteObject(container);
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteVerbose($"Container {CTID} on node {Node} start initiated");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
WriteError(new ErrorRecord(ex, "StartProxmoxContainerError", ErrorCategory.OperationStopped, null));
|
||||
}
|
||||
}
|
||||
|
||||
private string WaitForTask(string node, string taskId)
|
||||
{
|
||||
var status = "";
|
||||
var attempts = 0;
|
||||
var maxAttempts = 60; // Wait up to 60 seconds
|
||||
|
||||
while (attempts < maxAttempts)
|
||||
{
|
||||
var response = Connection.GetJson($"/nodes/{node}/tasks/{taskId}/status");
|
||||
var data = response["data"];
|
||||
status = (string)data["status"];
|
||||
|
||||
if (status == "stopped")
|
||||
{
|
||||
return (string)data["exitstatus"];
|
||||
}
|
||||
|
||||
System.Threading.Thread.Sleep(1000);
|
||||
attempts++;
|
||||
}
|
||||
|
||||
throw new Exception("Timeout waiting for task to complete");
|
||||
}
|
||||
|
||||
private ProxmoxContainer GetContainer(string node, int ctid)
|
||||
{
|
||||
var response = Connection.GetJson($"/nodes/{node}/lxc/{ctid}/status/current");
|
||||
var data = response["data"];
|
||||
|
||||
var container = data.ToObject<ProxmoxContainer>();
|
||||
container.Node = node;
|
||||
container.CTID = ctid;
|
||||
|
||||
return container;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Management.Automation;
|
||||
using PSProxmox.Models;
|
||||
using PSProxmox.Session;
|
||||
|
||||
namespace PSProxmox.Cmdlets
|
||||
{
|
||||
/// <summary>
|
||||
/// <para type="synopsis">Stops a Proxmox LXC container</para>
|
||||
/// <para type="description">Stops a Proxmox LXC container on a Proxmox server</para>
|
||||
/// </summary>
|
||||
/// <example>
|
||||
/// <code>Stop-ProxmoxContainer -Node "pve1" -CTID 100</code>
|
||||
/// <para>Stops the container with CTID 100 on node pve1</para>
|
||||
/// </example>
|
||||
/// <example>
|
||||
/// <code>Stop-ProxmoxContainer -Node "pve1" -CTID 100 -Force</code>
|
||||
/// <para>Forces the container with CTID 100 on node pve1 to stop</para>
|
||||
/// </example>
|
||||
[Cmdlet(VerbsLifecycle.Stop, "ProxmoxContainer")]
|
||||
[OutputType(typeof(ProxmoxContainer))]
|
||||
public class StopProxmoxContainerCmdlet : ProxmoxCmdlet
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the node name
|
||||
/// </summary>
|
||||
[Parameter(Mandatory = true, Position = 0, ValueFromPipelineByPropertyName = true)]
|
||||
public string Node { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the container ID
|
||||
/// </summary>
|
||||
[Parameter(Mandatory = true, Position = 1, ValueFromPipelineByPropertyName = true)]
|
||||
public int CTID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether to force stop the container
|
||||
/// </summary>
|
||||
[Parameter(Mandatory = false)]
|
||||
public SwitchParameter Force { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether to wait for the container to stop
|
||||
/// </summary>
|
||||
[Parameter(Mandatory = false)]
|
||||
public SwitchParameter Wait { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the timeout in seconds
|
||||
/// </summary>
|
||||
[Parameter(Mandatory = false)]
|
||||
public int Timeout { get; set; } = 60;
|
||||
|
||||
/// <summary>
|
||||
/// Processes the cmdlet
|
||||
/// </summary>
|
||||
protected override void ProcessRecord()
|
||||
{
|
||||
base.ProcessRecord();
|
||||
|
||||
try
|
||||
{
|
||||
var parameters = new Dictionary<string, object>();
|
||||
|
||||
if (Force.IsPresent)
|
||||
{
|
||||
parameters["force"] = 1;
|
||||
}
|
||||
|
||||
if (Timeout > 0)
|
||||
{
|
||||
parameters["timeout"] = Timeout;
|
||||
}
|
||||
|
||||
var response = Connection.PostJson($"/nodes/{Node}/lxc/{CTID}/status/stop", parameters);
|
||||
var data = response["data"];
|
||||
var taskId = (string)data["upid"];
|
||||
|
||||
if (Wait.IsPresent)
|
||||
{
|
||||
var taskStatus = WaitForTask(Node, taskId);
|
||||
if (taskStatus != "OK")
|
||||
{
|
||||
throw new Exception($"Failed to stop container: {taskStatus}");
|
||||
}
|
||||
|
||||
// Get the container status
|
||||
var container = GetContainer(Node, CTID);
|
||||
WriteObject(container);
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteVerbose($"Container {CTID} on node {Node} stop initiated");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
WriteError(new ErrorRecord(ex, "StopProxmoxContainerError", ErrorCategory.OperationStopped, null));
|
||||
}
|
||||
}
|
||||
|
||||
private string WaitForTask(string node, string taskId)
|
||||
{
|
||||
var status = "";
|
||||
var attempts = 0;
|
||||
var maxAttempts = Timeout > 0 ? Timeout : 60;
|
||||
|
||||
while (attempts < maxAttempts)
|
||||
{
|
||||
var response = Connection.GetJson($"/nodes/{node}/tasks/{taskId}/status");
|
||||
var data = response["data"];
|
||||
status = (string)data["status"];
|
||||
|
||||
if (status == "stopped")
|
||||
{
|
||||
return (string)data["exitstatus"];
|
||||
}
|
||||
|
||||
System.Threading.Thread.Sleep(1000);
|
||||
attempts++;
|
||||
}
|
||||
|
||||
throw new Exception("Timeout waiting for task to complete");
|
||||
}
|
||||
|
||||
private ProxmoxContainer GetContainer(string node, int ctid)
|
||||
{
|
||||
var response = Connection.GetJson($"/nodes/{node}/lxc/{ctid}/status/current");
|
||||
var data = response["data"];
|
||||
|
||||
var container = data.ToObject<ProxmoxContainer>();
|
||||
container.Node = node;
|
||||
container.CTID = ctid;
|
||||
|
||||
return container;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,229 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace PSProxmox.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a Proxmox LXC container
|
||||
/// </summary>
|
||||
public class ProxmoxContainer
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the container ID
|
||||
/// </summary>
|
||||
[JsonProperty("vmid")]
|
||||
public int CTID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the container name
|
||||
/// </summary>
|
||||
[JsonProperty("name")]
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the node name
|
||||
/// </summary>
|
||||
[JsonProperty("node")]
|
||||
public string Node { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the container status
|
||||
/// </summary>
|
||||
[JsonProperty("status")]
|
||||
public string Status { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the container uptime in seconds
|
||||
/// </summary>
|
||||
[JsonProperty("uptime")]
|
||||
public long Uptime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the container CPU usage
|
||||
/// </summary>
|
||||
[JsonProperty("cpu")]
|
||||
public double CPU { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the container memory usage in bytes
|
||||
/// </summary>
|
||||
[JsonProperty("mem")]
|
||||
public long Memory { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the container maximum memory in bytes
|
||||
/// </summary>
|
||||
[JsonProperty("maxmem")]
|
||||
public long MaxMemory { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the container disk usage in bytes
|
||||
/// </summary>
|
||||
[JsonProperty("disk")]
|
||||
public long Disk { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the container maximum disk size in bytes
|
||||
/// </summary>
|
||||
[JsonProperty("maxdisk")]
|
||||
public long MaxDisk { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the container swap usage in bytes
|
||||
/// </summary>
|
||||
[JsonProperty("swap")]
|
||||
public long Swap { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the container maximum swap in bytes
|
||||
/// </summary>
|
||||
[JsonProperty("maxswap")]
|
||||
public long MaxSwap { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the container network receive rate in bytes per second
|
||||
/// </summary>
|
||||
[JsonProperty("netin")]
|
||||
public long NetworkIn { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the container network transmit rate in bytes per second
|
||||
/// </summary>
|
||||
[JsonProperty("netout")]
|
||||
public long NetworkOut { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the container disk read rate in bytes per second
|
||||
/// </summary>
|
||||
[JsonProperty("diskread")]
|
||||
public long DiskRead { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the container disk write rate in bytes per second
|
||||
/// </summary>
|
||||
[JsonProperty("diskwrite")]
|
||||
public long DiskWrite { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the container template flag
|
||||
/// </summary>
|
||||
[JsonProperty("template")]
|
||||
public int Template { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the container description
|
||||
/// </summary>
|
||||
[JsonProperty("description")]
|
||||
public string Description { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the container OS type
|
||||
/// </summary>
|
||||
[JsonProperty("ostype")]
|
||||
public string OSType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the container IP address
|
||||
/// </summary>
|
||||
[JsonProperty("ip")]
|
||||
public string IPAddress { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the container hostname
|
||||
/// </summary>
|
||||
[JsonProperty("hostname")]
|
||||
public string Hostname { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the container creation time
|
||||
/// </summary>
|
||||
[JsonProperty("creation")]
|
||||
public long CreationTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the container tags
|
||||
/// </summary>
|
||||
[JsonProperty("tags")]
|
||||
public string Tags { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the container lock
|
||||
/// </summary>
|
||||
[JsonProperty("lock")]
|
||||
public string Lock { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the container unprivileged flag
|
||||
/// </summary>
|
||||
[JsonProperty("unprivileged")]
|
||||
public int Unprivileged { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the container features
|
||||
/// </summary>
|
||||
[JsonProperty("features")]
|
||||
public string Features { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the container configuration
|
||||
/// </summary>
|
||||
[JsonProperty("config")]
|
||||
public Dictionary<string, object> Config { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the container creation date
|
||||
/// </summary>
|
||||
public DateTime CreationDate
|
||||
{
|
||||
get
|
||||
{
|
||||
return DateTimeOffset.FromUnixTimeSeconds(CreationTime).DateTime;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the container uptime as a TimeSpan
|
||||
/// </summary>
|
||||
public TimeSpan UptimeSpan
|
||||
{
|
||||
get
|
||||
{
|
||||
return TimeSpan.FromSeconds(Uptime);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the container is running
|
||||
/// </summary>
|
||||
public bool IsRunning
|
||||
{
|
||||
get
|
||||
{
|
||||
return Status == "running";
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the container is a template
|
||||
/// </summary>
|
||||
public bool IsTemplate
|
||||
{
|
||||
get
|
||||
{
|
||||
return Template == 1;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the container is unprivileged
|
||||
/// </summary>
|
||||
public bool IsUnprivileged
|
||||
{
|
||||
get
|
||||
{
|
||||
return Unprivileged == 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,187 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace PSProxmox.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// Builder class for creating Proxmox LXC containers
|
||||
/// </summary>
|
||||
public class ProxmoxContainerBuilder
|
||||
{
|
||||
private readonly Dictionary<string, object> _parameters;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ProxmoxContainerBuilder"/> class
|
||||
/// </summary>
|
||||
/// <param name="name">The container name</param>
|
||||
public ProxmoxContainerBuilder(string name)
|
||||
{
|
||||
_parameters = new Dictionary<string, object>
|
||||
{
|
||||
{ "hostname", name }
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the parameters for creating the container
|
||||
/// </summary>
|
||||
public Dictionary<string, object> Parameters => _parameters;
|
||||
|
||||
/// <summary>
|
||||
/// Sets the container OS template
|
||||
/// </summary>
|
||||
/// <param name="ostemplate">The OS template</param>
|
||||
/// <returns>The builder instance</returns>
|
||||
public ProxmoxContainerBuilder WithOSTemplate(string ostemplate)
|
||||
{
|
||||
_parameters["ostemplate"] = ostemplate;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the container storage
|
||||
/// </summary>
|
||||
/// <param name="storage">The storage name</param>
|
||||
/// <returns>The builder instance</returns>
|
||||
public ProxmoxContainerBuilder WithStorage(string storage)
|
||||
{
|
||||
_parameters["storage"] = storage;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the container memory limit
|
||||
/// </summary>
|
||||
/// <param name="memory">The memory limit in MB</param>
|
||||
/// <returns>The builder instance</returns>
|
||||
public ProxmoxContainerBuilder WithMemory(int memory)
|
||||
{
|
||||
_parameters["memory"] = memory;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the container swap limit
|
||||
/// </summary>
|
||||
/// <param name="swap">The swap limit in MB</param>
|
||||
/// <returns>The builder instance</returns>
|
||||
public ProxmoxContainerBuilder WithSwap(int swap)
|
||||
{
|
||||
_parameters["swap"] = swap;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the container CPU cores
|
||||
/// </summary>
|
||||
/// <param name="cores">The number of CPU cores</param>
|
||||
/// <returns>The builder instance</returns>
|
||||
public ProxmoxContainerBuilder WithCores(int cores)
|
||||
{
|
||||
_parameters["cores"] = cores;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the container disk size
|
||||
/// </summary>
|
||||
/// <param name="diskSize">The disk size in GB</param>
|
||||
/// <returns>The builder instance</returns>
|
||||
public ProxmoxContainerBuilder WithDiskSize(int diskSize)
|
||||
{
|
||||
_parameters["rootfs"] = $"local-lvm:{diskSize}";
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the container disk size with specific storage
|
||||
/// </summary>
|
||||
/// <param name="storage">The storage name</param>
|
||||
/// <param name="diskSize">The disk size in GB</param>
|
||||
/// <returns>The builder instance</returns>
|
||||
public ProxmoxContainerBuilder WithDiskSize(string storage, int diskSize)
|
||||
{
|
||||
_parameters["rootfs"] = $"{storage}:{diskSize}";
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the container to be unprivileged
|
||||
/// </summary>
|
||||
/// <param name="unprivileged">Whether the container is unprivileged</param>
|
||||
/// <returns>The builder instance</returns>
|
||||
public ProxmoxContainerBuilder WithUnprivileged(bool unprivileged)
|
||||
{
|
||||
_parameters["unprivileged"] = unprivileged ? 1 : 0;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the container password
|
||||
/// </summary>
|
||||
/// <param name="password">The container password</param>
|
||||
/// <returns>The builder instance</returns>
|
||||
public ProxmoxContainerBuilder WithPassword(string password)
|
||||
{
|
||||
_parameters["password"] = password;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the container SSH public key
|
||||
/// </summary>
|
||||
/// <param name="sshKey">The SSH public key</param>
|
||||
/// <returns>The builder instance</returns>
|
||||
public ProxmoxContainerBuilder WithSSHKey(string sshKey)
|
||||
{
|
||||
_parameters["ssh-public-keys"] = sshKey;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the container network interface
|
||||
/// </summary>
|
||||
/// <param name="name">The interface name</param>
|
||||
/// <param name="bridge">The bridge name</param>
|
||||
/// <param name="ip">The IP address</param>
|
||||
/// <param name="gateway">The gateway address</param>
|
||||
/// <returns>The builder instance</returns>
|
||||
public ProxmoxContainerBuilder WithNetwork(string name, string bridge, string ip, string gateway)
|
||||
{
|
||||
_parameters[$"net{name}"] = $"name=eth0,bridge={bridge},ip={ip},gw={gateway}";
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the container description
|
||||
/// </summary>
|
||||
/// <param name="description">The container description</param>
|
||||
/// <returns>The builder instance</returns>
|
||||
public ProxmoxContainerBuilder WithDescription(string description)
|
||||
{
|
||||
_parameters["description"] = description;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the container start on boot flag
|
||||
/// </summary>
|
||||
/// <param name="start">Whether to start the container on boot</param>
|
||||
/// <returns>The builder instance</returns>
|
||||
public ProxmoxContainerBuilder WithStartOnBoot(bool start)
|
||||
{
|
||||
_parameters["onboot"] = start ? 1 : 0;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the container start after creation flag
|
||||
/// </summary>
|
||||
/// <param name="start">Whether to start the container after creation</param>
|
||||
/// <returns>The builder instance</returns>
|
||||
public ProxmoxContainerBuilder WithStart(bool start)
|
||||
{
|
||||
_parameters["start"] = start ? 1 : 0;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
using System;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace PSProxmox.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a TurnKey Linux template for Proxmox LXC containers
|
||||
/// </summary>
|
||||
public class ProxmoxTurnKeyTemplate
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the template name
|
||||
/// </summary>
|
||||
[JsonProperty("template")]
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the template title
|
||||
/// </summary>
|
||||
[JsonProperty("title")]
|
||||
public string Title { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the template description
|
||||
/// </summary>
|
||||
[JsonProperty("description")]
|
||||
public string Description { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the template section
|
||||
/// </summary>
|
||||
[JsonProperty("section")]
|
||||
public string Section { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the template OS
|
||||
/// </summary>
|
||||
[JsonProperty("os")]
|
||||
public string OS { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the template version
|
||||
/// </summary>
|
||||
[JsonProperty("version")]
|
||||
public string Version { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the template package
|
||||
/// </summary>
|
||||
[JsonProperty("package")]
|
||||
public string Package { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the template source
|
||||
/// </summary>
|
||||
[JsonProperty("source")]
|
||||
public string Source { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the template URL
|
||||
/// </summary>
|
||||
[JsonProperty("url")]
|
||||
public string URL { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the template size in bytes
|
||||
/// </summary>
|
||||
[JsonProperty("size")]
|
||||
public long Size { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the template MD5 checksum
|
||||
/// </summary>
|
||||
[JsonProperty("md5sum")]
|
||||
public string MD5Sum { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the template SHA1 checksum
|
||||
/// </summary>
|
||||
[JsonProperty("sha1sum")]
|
||||
public string SHA1Sum { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the template SHA256 checksum
|
||||
/// </summary>
|
||||
[JsonProperty("sha256sum")]
|
||||
public string SHA256Sum { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the template architecture
|
||||
/// </summary>
|
||||
[JsonProperty("architecture")]
|
||||
public string Architecture { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the template infopage URL
|
||||
/// </summary>
|
||||
[JsonProperty("infopage")]
|
||||
public string InfoPage { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the template download URL
|
||||
/// </summary>
|
||||
[JsonProperty("location")]
|
||||
public string Location { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the template size in a human-readable format
|
||||
/// </summary>
|
||||
public string HumanSize
|
||||
{
|
||||
get
|
||||
{
|
||||
string[] sizes = { "B", "KB", "MB", "GB", "TB" };
|
||||
double len = Size;
|
||||
int order = 0;
|
||||
while (len >= 1024 && order < sizes.Length - 1)
|
||||
{
|
||||
order++;
|
||||
len = len / 1024;
|
||||
}
|
||||
return $"{len:0.##} {sizes[order]}";
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the full template name including version
|
||||
/// </summary>
|
||||
public string FullName
|
||||
{
|
||||
get
|
||||
{
|
||||
return $"{Name}-{Version}";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,10 +5,12 @@ PSProxmox is a C#-based PowerShell module for managing Proxmox VE clusters. It p
|
||||
## Features
|
||||
|
||||
- **Session Management**: Authenticate and persist sessions with Proxmox VE clusters
|
||||
- **Core CRUD Operations**: Manage VMs, Storage, Network, Users, Roles, SDN, and Clusters
|
||||
- **Core CRUD Operations**: Manage VMs, LXC Containers, Storage, Network, Users, Roles, SDN, and Clusters
|
||||
- **Templates**: Create and use VM deployment templates
|
||||
- **Cloud Images**: Download, customize, and create templates from cloud images
|
||||
- **Cloud-Init Support**: Configure VMs with Cloud-Init for easy customization
|
||||
- **LXC Containers**: Create and manage Linux Containers with full CRUD operations
|
||||
- **TurnKey Templates**: Download and use TurnKey Linux templates for LXC containers
|
||||
- **Mass Creation**: Bulk create VMs with prefix/counter
|
||||
- **IP Management**: CIDR parsing, subnetting, FIFO IP queue assignment
|
||||
- **Structured Objects**: All outputs are typed C# classes (PowerShell-native)
|
||||
@@ -249,6 +251,59 @@ $pool = Get-ProxmoxIPPool -Name "Production"
|
||||
Clear-ProxmoxIPPool -Name "Production"
|
||||
```
|
||||
|
||||
### Managing LXC Containers
|
||||
|
||||
```powershell
|
||||
# Get all LXC containers
|
||||
$containers = Get-ProxmoxContainer
|
||||
|
||||
# Get a specific container
|
||||
$container = Get-ProxmoxContainer -CTID 100
|
||||
|
||||
# Get containers by name pattern (supports wildcards and regex)
|
||||
$webContainers = Get-ProxmoxContainer -Name "web*"
|
||||
$dbContainers = Get-ProxmoxContainer -Name "^db\d+$"
|
||||
|
||||
# Create a new container
|
||||
$container = New-ProxmoxContainer -Node "pve1" -Name "web-container" -OSTemplate "local:vztmpl/ubuntu-20.04-standard_20.04-1_amd64.tar.gz" -Storage "local-lvm" -Memory 512 -Cores 1 -DiskSize 8 -Unprivileged -Start
|
||||
|
||||
# Create a container using a builder
|
||||
$builder = New-ProxmoxContainerBuilder -Name "db-container"
|
||||
$builder.WithOSTemplate("local:vztmpl/ubuntu-20.04-standard_20.04-1_amd64.tar.gz")
|
||||
.WithStorage("local-lvm")
|
||||
.WithMemory(1024)
|
||||
.WithCores(2)
|
||||
.WithDiskSize(16)
|
||||
.WithUnprivileged($true)
|
||||
.WithStart($true)
|
||||
|
||||
$container = New-ProxmoxContainer -Node "pve1" -Builder $builder
|
||||
|
||||
# Start, stop, and restart containers
|
||||
Start-ProxmoxContainer -Node "pve1" -CTID 100 -Wait
|
||||
Stop-ProxmoxContainer -Node "pve1" -CTID 100 -Wait
|
||||
Restart-ProxmoxContainer -Node "pve1" -CTID 100 -Wait
|
||||
|
||||
# Remove a container
|
||||
Remove-ProxmoxContainer -Node "pve1" -CTID 100 -Confirm:$false
|
||||
```
|
||||
|
||||
### Working with TurnKey Linux Templates
|
||||
|
||||
```powershell
|
||||
# List available TurnKey templates
|
||||
$templates = Get-ProxmoxTurnKeyTemplate
|
||||
|
||||
# Get TurnKey templates by name pattern
|
||||
$wordpressTemplates = Get-ProxmoxTurnKeyTemplate -Name "wordpress*"
|
||||
|
||||
# Download a TurnKey template
|
||||
$templatePath = Save-ProxmoxTurnKeyTemplate -Node "pve1" -Name "wordpress" -Storage "local"
|
||||
|
||||
# Create a container from a TurnKey template
|
||||
$container = New-ProxmoxContainerFromTurnKey -Node "pve1" -Name "wordpress" -Template "wordpress" -Storage "local-lvm" -Memory 512 -Cores 1 -DiskSize 8 -Start
|
||||
```
|
||||
|
||||
## Disconnecting
|
||||
|
||||
```powershell
|
||||
@@ -290,6 +345,7 @@ For detailed documentation, see the [Documentation](Documentation) directory. Th
|
||||
- [Guides](Documentation/guides/README.md)
|
||||
- [Installation Guide](Documentation/guides/Installation.md)
|
||||
- [Cloud Image Templates Guide](Documentation/guides/CloudImageTemplates.md)
|
||||
- [LXC Containers Guide](Documentation/guides/LXCContainers.md)
|
||||
|
||||
## Contributing
|
||||
|
||||
|
||||
Reference in New Issue
Block a user