Repository: bpg/terraform-provider-proxmox

Issue:
Ceph Squid is missing in CephVersionName
**Describe the bug**
It has been added to the docs via #2044 but it is still missing in `proxmox/types/nodes/apt/ceph_version_name.go`

This only affects PVE9.

Related problem: #2219 

**To Reproduce**

```hcl
resource "proxmox_virtual_environment_apt_standard_repository" "example" {
  handle = "ceph-squid-no-subscription"
  node   = "pve"
}
```

**Expected behavior**
It succeeds.

- Single or clustered Proxmox: Single
- Proxmox version: 9.0
- Provider version (ideally it should be the latest version): 0.86.0
- Terraform/OpenTofu version: Terraform v1.13.4
- OS (where you run Terraform/OpenTofu from): Fedora Silverblue


Discussion:

Solution patch:
diff --git a/.all-contributorsrc b/.all-contributorsrc
index 5f1cfdca..b2e63f88 100644
--- a/.all-contributorsrc
+++ b/.all-contributorsrc
@@ -1528,6 +1528,15 @@
       "contributions": [
         "code"
       ]
+    },
+    {
+      "login": "alexhaydock",
+      "name": "Alex Haydock",
+      "avatar_url": "https://avatars.githubusercontent.com/u/13152214?v=4",
+      "profile": "https://github.com/alexhaydock",
+      "contributions": [
+        "doc"
+      ]
     }
   ],
   "contributorsPerLine": 7,
diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md
index 4cee34dc..97cb76be 100644
--- a/CONTRIBUTORS.md
+++ b/CONTRIBUTORS.md
@@ -215,6 +215,7 @@
     <tr>
       <td align="center" valign="top" width="14.28%"><a href="https://mlit.pro"><img src="https://avatars.githubusercontent.com/u/693906?v=4?s=100" width="100px;" alt="Maciej Lech"/><br /><sub><b>Maciej Lech</b></sub></a><br /><a href="https://github.com/bpg/terraform-provider-proxmox/commits?author=maciej-lech" title="Tests">⚠️</a> <a href="https://github.com/bpg/terraform-provider-proxmox/commits?author=maciej-lech" title="Code">💻</a></td>
       <td align="center" valign="top" width="14.28%"><a href="https://github.com/JustasUmbrasas"><img src="https://avatars.githubusercontent.com/u/70886320?v=4?s=100" width="100px;" alt="Justas Umbrasas"/><br /><sub><b>Justas Umbrasas</b></sub></a><br /><a href="https://github.com/bpg/terraform-provider-proxmox/commits?author=JustasUmbrasas" title="Code">💻</a></td>
+      <td align="center" valign="top" width="14.28%"><a href="https://github.com/alexhaydock"><img src="https://avatars.githubusercontent.com/u/13152214?v=4?s=100" width="100px;" alt="Alex Haydock"/><br /><sub><b>Alex Haydock</b></sub></a><br /><a href="https://github.com/bpg/terraform-provider-proxmox/commits?author=alexhaydock" title="Documentation">📖</a></td>
     </tr>
   </tbody>
   <tfoot>
diff --git a/docs/data-sources/virtual_environment_sdn_vnet.md b/docs/data-sources/virtual_environment_sdn_vnet.md
index 3497dd73..a1b2ffdf 100644
--- a/docs/data-sources/virtual_environment_sdn_vnet.md
+++ b/docs/data-sources/virtual_environment_sdn_vnet.md
@@ -11,7 +11,24 @@ description: |-
 
 Retrieves information about an existing SDN VNet.
 
-
+## Example Usage
+
+```terraform
+data "proxmox_virtual_environment_sdn_vnet" "example" {
+  id = "vnet1"
+}
+
+output "data_proxmox_virtual_environment_sdn_vnet" {
+  value = {
+    id            = data.proxmox_virtual_environment_sdn_vnet.example.id
+    zone          = data.proxmox_virtual_environment_sdn_vnet.example.zone
+    alias         = data.proxmox_virtual_environment_sdn_vnet.example.alias
+    isolate_ports = data.proxmox_virtual_environment_sdn_vnet.example.isolate_ports
+    tag           = data.proxmox_virtual_environment_sdn_vnet.example.tag
+    vlan_aware    = data.proxmox_virtual_environment_sdn_vnet.example.vlan_aware
+  }
+}
+```
 
 <!-- schema generated by tfplugindocs -->
 ## Schema
diff --git a/docs/data-sources/virtual_environment_sdn_vnets.md b/docs/data-sources/virtual_environment_sdn_vnets.md
new file mode 100644
index 00000000..01353bfd
--- /dev/null
+++ b/docs/data-sources/virtual_environment_sdn_vnets.md
@@ -0,0 +1,44 @@
+---
+layout: page
+title: proxmox_virtual_environment_sdn_vnets
+parent: Data Sources
+subcategory: Virtual Environment
+description: |-
+  Retrieves information about all SDN VNets in Proxmox. This data source lists all virtual networks configured in the Software-Defined Networking setup.
+---
+
+# Data Source: proxmox_virtual_environment_sdn_vnets
+
+Retrieves information about all SDN VNets in Proxmox. This data source lists all virtual networks configured in the Software-Defined Networking setup.
+
+## Example Usage
+
+```terraform
+# List all SDN VNets
+data "proxmox_virtual_environment_sdn_vnets" "all" {}
+
+output "data_proxmox_virtual_environment_sdn_vnets_all" {
+  value = {
+    vnets = data.proxmox_virtual_environment_sdn_vnets.all.vnets
+  }
+}
+```
+
+<!-- schema generated by tfplugindocs -->
+## Schema
+
+### Read-Only
+
+- `vnets` (List of Object) List of SDN VNets. (see [below for nested schema](#nestedatt--vnets))
+
+<a id="nestedatt--vnets"></a>
+### Nested Schema for `vnets`
+
+Read-Only:
+
+- `alias` (String)
+- `id` (String)
+- `isolate_ports` (Boolean)
+- `tag` (Number)
+- `vlan_aware` (Boolean)
+- `zone` (String)
diff --git a/docs/index.md b/docs/index.md
index dba630d4..1444e2fd 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -45,6 +45,14 @@ Use the navigation to the left to read about the available resources.
 | `PROXMOX_VE_SSH_USERNAME` | SSH username | No |
 | `PROXMOX_VE_SSH_PASSWORD` | SSH password | No |
 | `PROXMOX_VE_SSH_PRIVATE_KEY` | SSH private key | No |
+| `PROXMOX_VE_SSH_AGENT` | Use SSH agent for authentication | No |
+| `PROXMOX_VE_SSH_AUTH_SOCK` | SSH agent socket path | No |
+| `PROXMOX_VE_SSH_AGENT_FORWARDING` | Enable SSH agent forwarding | No |
+| `PROXMOX_VE_SSH_SOCKS5_SERVER` | SOCKS5 proxy server address | No |
+| `PROXMOX_VE_SSH_SOCKS5_USERNAME` | SOCKS5 proxy username | No |
+| `PROXMOX_VE_SSH_SOCKS5_PASSWORD` | SOCKS5 proxy password | No |
+| `PROXMOX_VE_MIN_TLS` | Minimum TLS version | No |
+| `PROXMOX_VE_OTP` | One-time password (deprecated) | No |
 | `PROXMOX_VE_TMPDIR` | Custom temporary directory | No |
 
 *One of these authentication methods is required
@@ -76,7 +84,7 @@ provider "proxmox" {
 ## Authentication
 
 The Proxmox provider offers a flexible means of providing credentials for authentication.
-Static credentials and pre-authenticated session-ticket can be provided to the `proxmox` block through one of the choices of arguments below, ordered by precedence:
+Static credentials and pre-authenticated session ticket can be provided to the `proxmox` block through one of the choices of arguments below, ordered by precedence:
 
 - `api_token`
 - `auth_ticket` and `csrf_prevention_token`
@@ -192,20 +200,20 @@ See the [Argument Reference](#argument-reference) section for the supported vari
 ### API Token Authentication
 
 API Token authentication can be used to authenticate with the Proxmox API without the need to provide a password.
-In combination with the `ssh` block and `ssh-agent` support, this allows for a fully password-less authentication.
+In combination with the `ssh` block and SSH agent support, this allows for a fully password-less authentication.
 
 You can create an API Token for a user via the Proxmox UI, or via the command line on the Proxmox host or cluster:
 
 - Create a user:
 
     ```sh
-    sudo pveum user add terraform@pve
+    pveum user add terraform@pve
     ```
 
 - Create a role for the user (you can skip this step if you want to use any of the existing roles):
 
     ```sh
-    sudo pveum role add Terraform -privs "Realm.AllocateUser, VM.PowerMgmt, VM.GuestAgent.Unrestricted, Sys.Console, Sys.Audit, Sys.AccessNetwork, VM.Config.Cloudinit, VM.Replicate, Pool.Allocate, SDN.Audit, Realm.Allocate, SDN.Use, Mapping.Modify, VM.Config.Memory, VM.GuestAgent.FileSystemMgmt, VM.Allocate, SDN.Allocate, VM.Console, VM.Clone, VM.Backup, Datastore.AllocateTemplate, VM.Snapshot, VM.Config.Network, Sys.Incoming, Sys.Modify, VM.Snapshot.Rollback, VM.Config.Disk, Datastore.Allocate, VM.Config.CPU, VM.Config.CDROM, Group.Allocate, Datastore.Audit, VM.Migrate, VM.GuestAgent.FileWrite, Mapping.Use, Datastore.AllocateSpace, Sys.Syslog, VM.Config.Options, Pool.Audit, User.Modify, VM.Config.HWType, VM.Audit, Sys.PowerMgmt, VM.GuestAgent.Audit, Mapping.Audit, VM.GuestAgent.FileRead, Permissions.Modify"
+    pveum role add Terraform -privs "Realm.AllocateUser, VM.PowerMgmt, VM.GuestAgent.Unrestricted, Sys.Console, Sys.Audit, Sys.AccessNetwork, VM.Config.Cloudinit, VM.Replicate, Pool.Allocate, SDN.Audit, Realm.Allocate, SDN.Use, Mapping.Modify, VM.Config.Memory, VM.GuestAgent.FileSystemMgmt, VM.Allocate, SDN.Allocate, VM.Console, VM.Clone, VM.Backup, Datastore.AllocateTemplate, VM.Snapshot, VM.Config.Network, Sys.Incoming, Sys.Modify, VM.Snapshot.Rollback, VM.Config.Disk, Datastore.Allocate, VM.Config.CPU, VM.Config.CDROM, Group.Allocate, Datastore.Audit, VM.Migrate, VM.GuestAgent.FileWrite, Mapping.Use, Datastore.AllocateSpace, Sys.Syslog, VM.Config.Options, Pool.Audit, User.Modify, VM.Config.HWType, VM.Audit, Sys.PowerMgmt, VM.GuestAgent.Audit, Mapping.Audit, VM.GuestAgent.FileRead, Permissions.Modify"
     ```
 
   ~> The list of available privileges has been changed in PVE 9.0, and the above list is only an example (and most likely too excessive for most use cases), please review it and adjust to your needs.
@@ -214,15 +222,17 @@ You can create an API Token for a user via the Proxmox UI, or via the command li
 - Assign the role to the previously created user:
 
     ```sh
-    sudo pveum aclmod / -user terraform@pve -role Terraform
+    pveum aclmod / -user terraform@pve -role Terraform
     ```
 
 - Create an API token for the user:
 
     ```sh
-    sudo pveum user token add terraform@pve provider --privsep=0
+    pveum user token add terraform@pve provider --privsep=0
     ```
 
+    -> Make sure you copy the token value, as it will not be displayed again.
+
 Refer to the upstream docs as needed for additional details concerning [PVE User Management](https://pve.proxmox.com/wiki/User_Management).
 
 Generating the token will output a table containing the token's ID and secret which are meant to be concatenated into a single string for use with either the `api_token` field of the `provider` block (fine for testing but should be avoided) or sourced from the `PROXMOX_VE_API_TOKEN` environment variable.
@@ -322,7 +332,7 @@ Please refer to the [Argument Reference](#argument-reference) section to view th
 ### SSH Agent
 
 The provider does not use OS-specific SSH configuration files, such as `~/.ssh/config`.
-Instead, it uses the SSH protocol directly, and supports the `SSH_AUTH_SOCK` environment variable (or `agent_socket` argument) to connect to the `ssh-agent`.
+Instead, it uses the SSH protocol directly, and supports the `SSH_AUTH_SOCK` environment variable (or `agent_socket` argument) to connect to the SSH agent.
 This allows the provider to use the SSH agent configured by the user, and to support multiple SSH agents running on the same machine.
 You can find more details on the SSH Agent [here](https://www.digitalocean.com/community/tutorials/ssh-essentials-working-with-ssh-servers-clients-and-keys#adding-your-ssh-keys-to-an-ssh-agent-to-avoid-typing-the-passphrase).
 The SSH agent authentication takes precedence over the `private_key` and `password` authentication.
@@ -436,7 +446,7 @@ In the example below, we create a user `terraform` and assign the `sudo` privile
 
   You should be able to connect to the target node and see the output containing `APIVER <number>` on the screen without being prompted for your password.
 
-Alternatively if `pam_ssh_agent_auth` is configured on the target node the SSH Config option `agent_forwarding` may be used to forward the SSH Agent that was used for the connection to the remote server. This can allow `sudo` without a password which validates public ssh key configured for `pam_ssh_agent_auth`.
+Alternatively if `pam_ssh_agent_auth` is configured on the target node the SSH Config option `agent_forwarding` may be used to forward the SSH agent that was used for the connection to the remote server. This can allow `sudo` without a password which validates public SSH key configured for `pam_ssh_agent_auth`.
 
 ### Node IP address used for SSH connection
 
diff --git a/docs/resources/virtual_environment_container.md b/docs/resources/virtual_environment_container.md
index 0255b9e1..13542a17 100644
--- a/docs/resources/virtual_environment_container.md
+++ b/docs/resources/virtual_environment_container.md
@@ -160,9 +160,9 @@ output "ubuntu_container_public_key" {
         - `ipv6` - (Optional) The IPv6 configuration.
             - `address` - (Optional) The IPv6 address in CIDR notation
               (e.g. fd1c::7334/64). Alternatively, set this
-              to `dhcp` for autodiscovery.
+              to `dhcp` for DHCPv6, or `auto` for SLAAC.
             - `gateway` - (Optional) The IPv6 gateway (must be omitted
-                when `dhcp` is used as the address).
+                when `dhcp` or `auto` are used as the address).
     - `user_account` - (Optional) The user account configuration.
         - `keys` - (Optional) The SSH keys for the root account.
         - `password` - (Optional) The password for the root account.
@@ -225,7 +225,8 @@ output "ubuntu_container_public_key" {
         - `opensuse` - openSUSE.
         - `ubuntu` - Ubuntu.
         - `unmanaged` - Unmanaged.
-- `pool_id` - (Optional) The identifier for a pool to assign the container to.
+- `pool_id` - (Optional, **Deprecated**) The identifier for a pool to assign the container to.
+  This field is deprecated and will be removed in a future release. To assign the container to a pool, use the `proxmox_virtual_environment_pool_membership` resource instead. 
 - `protection` - (Optional) Whether to set the protection flag of the container (defaults to `false`). This will prevent the container itself and its disk for remove/update operations.
 - `started` - (Optional) Whether to start the container (defaults to `true`).
 - `startup` - (Optional) Defines startup and shutdown behavior of the container.
diff --git a/docs/resources/virtual_environment_vm.md b/docs/resources/virtual_environment_vm.md
index a52777be..07cab635 100755
--- a/docs/resources/virtual_environment_vm.md
+++ b/docs/resources/virtual_environment_vm.md
@@ -390,9 +390,9 @@ output "ubuntu_vm_public_key" {
         - `ipv6` - (Optional) The IPv6 configuration.
             - `address` - (Optional) The IPv6 address in CIDR notation
                 (e.g. fd1c::7334/64). Alternatively, set this
-                to `dhcp` for autodiscovery.
+                to `dhcp` for DHCPv6, or `auto` for SLAAC.
             - `gateway` - (Optional) The IPv6 gateway (must be omitted
-                when `dhcp` is used as the address).
+                when `dhcp` or `auto` are used as the address).
     - `user_account` - (Optional) The user account configuration (conflicts
         with `user_data_file_id`).
         - `keys` - (Optional) The SSH keys.
@@ -503,7 +503,8 @@ output "ubuntu_vm_public_key" {
         - `win11` - Windows 11
         - `wvista` - Windows Vista.
         - `wxp` - Windows XP.
-- `pool_id` - (Optional) The identifier for a pool to assign the virtual machine to.
+- `pool_id` - (Optional, **Deprecated**) The identifier for a pool to assign the virtual machine to.
+  This field is deprecated and will be removed in a future release. To assign the VM to a pool, use the `proxmox_virtual_environment_pool_membership` resource instead.
 - `protection` - (Optional) Sets the protection flag of the VM. This will disable the remove VM and remove disk operations (defaults to `false`).
 - `reboot` - (Optional) Reboot the VM after initial creation (defaults to `false`).
 - `reboot_after_update` - (Optional) Reboot the VM after update if needed (defaults to `true`).
diff --git a/example/data_source_virtual_environment_sdn.tf b/example/data_source_virtual_environment_sdn.tf
index 42553d17..13852e48 100644
--- a/example/data_source_virtual_environment_sdn.tf
+++ b/example/data_source_virtual_environment_sdn.tf
@@ -23,6 +23,13 @@ data "proxmox_virtual_environment_sdn_vnet" "test_vnet_1" {
   id = proxmox_virtual_environment_sdn_vnet.test_vnet_1.id
 }
 
+data "proxmox_virtual_environment_sdn_vnets" "all" {
+  depends_on = [
+    proxmox_virtual_environment_sdn_vnet.test_vnet_1,
+    proxmox_virtual_environment_sdn_vnet.test_vnet_2,
+  ]
+}
+
 data "proxmox_virtual_environment_sdn_subnet" "test_subnet_dhcp" {
   depends_on = [proxmox_virtual_environment_sdn_subnet.test_subnet_dhcp]
   cidr = proxmox_virtual_environment_sdn_subnet.test_subnet_dhcp.cidr
@@ -45,6 +52,10 @@ output "proxmox_virtual_environment_sdn_vnet" {
   value = data.proxmox_virtual_environment_sdn_vnet.test_vnet_1
 }
 
+output "proxmox_virtual_environment_sdn_vnets" {
+  value = data.proxmox_virtual_environment_sdn_vnets.all
+}
+
 output "proxmox_virtual_environment_sdn_subnet" {
   value = data.proxmox_virtual_environment_sdn_subnet.test_subnet_dhcp
 }
diff --git a/examples/data-sources/proxmox_virtual_environment_sdn_vnet/data-source.tf b/examples/data-sources/proxmox_virtual_environment_sdn_vnet/data-source.tf
new file mode 100644
index 00000000..724d9c38
--- /dev/null
+++ b/examples/data-sources/proxmox_virtual_environment_sdn_vnet/data-source.tf
@@ -0,0 +1,14 @@
+data "proxmox_virtual_environment_sdn_vnet" "example" {
+  id = "vnet1"
+}
+
+output "data_proxmox_virtual_environment_sdn_vnet" {
+  value = {
+    id            = data.proxmox_virtual_environment_sdn_vnet.example.id
+    zone          = data.proxmox_virtual_environment_sdn_vnet.example.zone
+    alias         = data.proxmox_virtual_environment_sdn_vnet.example.alias
+    isolate_ports = data.proxmox_virtual_environment_sdn_vnet.example.isolate_ports
+    tag           = data.proxmox_virtual_environment_sdn_vnet.example.tag
+    vlan_aware    = data.proxmox_virtual_environment_sdn_vnet.example.vlan_aware
+  }
+}
diff --git a/examples/data-sources/proxmox_virtual_environment_sdn_vnets/data-source.tf b/examples/data-sources/proxmox_virtual_environment_sdn_vnets/data-source.tf
new file mode 100644
index 00000000..94c8e364
--- /dev/null
+++ b/examples/data-sources/proxmox_virtual_environment_sdn_vnets/data-source.tf
@@ -0,0 +1,8 @@
+# List all SDN VNets
+data "proxmox_virtual_environment_sdn_vnets" "all" {}
+
+output "data_proxmox_virtual_environment_sdn_vnets_all" {
+  value = {
+    vnets = data.proxmox_virtual_environment_sdn_vnets.all.vnets
+  }
+}
diff --git a/fwprovider/cluster/sdn/vnet/datasource_vnets.go b/fwprovider/cluster/sdn/vnet/datasource_vnets.go
new file mode 100644
index 00000000..e93e0993
--- /dev/null
+++ b/fwprovider/cluster/sdn/vnet/datasource_vnets.go
@@ -0,0 +1,169 @@
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/.
+ */
+
+package vnet
+
+import (
+	"context"
+	"fmt"
+
+	"github.com/hashicorp/terraform-plugin-framework/attr"
+	"github.com/hashicorp/terraform-plugin-framework/datasource"
+	"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
+	"github.com/hashicorp/terraform-plugin-framework/types"
+
+	"github.com/bpg/terraform-provider-proxmox/fwprovider/config"
+	"github.com/bpg/terraform-provider-proxmox/proxmox/cluster/sdn"
+	"github.com/bpg/terraform-provider-proxmox/proxmox/cluster/sdn/vnets"
+)
+
+// Ensure the implementation satisfies the required interfaces.
+var (
+	_ datasource.DataSource              = &vnetsDataSource{}
+	_ datasource.DataSourceWithConfigure = &vnetsDataSource{}
+)
+
+// vnetsDataSource is the data source implementation for SDN VNets.
+type vnetsDataSource struct {
+	client *vnets.Client
+}
+
+// vnetsDataSourceModel represents the data source model for listing VNets.
+type vnetsDataSourceModel struct {
+	VNets types.List `tfsdk:"vnets"`
+}
+
+// vnetDataModel represents individual VNet data in the list.
+type vnetDataModel struct {
+	ID           types.String `tfsdk:"id"`
+	Zone         types.String `tfsdk:"zone"`
+	Alias        types.String `tfsdk:"alias"`
+	IsolatePorts types.Bool   `tfsdk:"isolate_ports"`
+	Tag          types.Int64  `tfsdk:"tag"`
+	VlanAware    types.Bool   `tfsdk:"vlan_aware"`
+}
+
+// Configure adds the provider-configured client to the data source.
+func (d *vnetsDataSource) Configure(_ context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) {
+	if req.ProviderData == nil {
+		return
+	}
+
+	cfg, ok := req.ProviderData.(config.DataSource)
+	if !ok {
+		resp.Diagnostics.AddError(
+			"Unexpected DataSource Configure Type",
+			fmt.Sprintf("Expected config.DataSource, got: %T", req.ProviderData),
+		)
+
+		return
+	}
+
+	d.client = &vnets.Client{Client: cfg.Client.Cluster()}
+}
+
+// Metadata returns the data source type name.
+func (d *vnetsDataSource) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
+	resp.TypeName = req.ProviderTypeName + "_sdn_vnets"
+}
+
+// Schema defines the schema for the data source.
+func (d *vnetsDataSource) Schema(_ context.Context, _ datasource.SchemaRequest, resp *datasource.SchemaResponse) {
+	resp.Schema = schema.Schema{
+		Description: "Retrieves information about all SDN VNets in Proxmox.",
+		MarkdownDescription: "Retrieves information about all SDN VNets in Proxmox. " +
+			"This data source lists all virtual networks configured in the Software-Defined Networking setup.",
+		Attributes: map[string]schema.Attribute{
+			"vnets": schema.ListAttribute{
+				Description: "List of SDN VNets.",
+				Computed:    true,
+				ElementType: types.ObjectType{
+					AttrTypes: map[string]attr.Type{
+						"id":            types.StringType,
+						"zone":          types.StringType,
+						"alias":         types.StringType,
+						"isolate_ports": types.BoolType,
+						"tag":           types.Int64Type,
+						"vlan_aware":    types.BoolType,
+					},
+				},
+			},
+		},
+	}
+}
+
+// Read fetches all SDN VNets from the Proxmox VE API.
+func (d *vnetsDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
+	var data vnetsDataSourceModel
+	resp.Diagnostics.Append(req.Config.Get(ctx, &data)...)
+
+	if resp.Diagnostics.HasError() {
+		return
+	}
+
+	vnetsList, err := d.client.GetVnetsWithParams(ctx, &sdn.QueryParams{})
+	if err != nil {
+		resp.Diagnostics.AddError(
+			"Unable to Read SDN VNets",
+			err.Error(),
+		)
+
+		return
+	}
+
+	// Convert VNets to list elements
+	vnetElements := make([]attr.Value, len(vnetsList))
+	for i, vnet := range vnetsList {
+		vnetData := vnetDataModel{
+			ID:           types.StringValue(vnet.ID),
+			Zone:         types.StringPointerValue(vnet.Zone),
+			Alias:        types.StringPointerValue(vnet.Alias),
+			IsolatePorts: types.BoolPointerValue(vnet.IsolatePorts.PointerBool()),
+			Tag:          types.Int64PointerValue(vnet.Tag),
+			VlanAware:    types.BoolPointerValue(vnet.VlanAware.PointerBool()),
+		}
+
+		objValue, objDiag := types.ObjectValueFrom(ctx, map[string]attr.Type{
+			"id":            types.StringType,
+			"zone":          types.StringType,
+			"alias":         types.StringType,
+			"isolate_ports": types.BoolType,
+			"tag":           types.Int64Type,
+			"vlan_aware":    types.BoolType,
+		}, vnetData)
+		resp.Diagnostics.Append(objDiag...)
+
+		if resp.Diagnostics.HasError() {
+			return
+		}
+
+		vnetElements[i] = objValue
+	}
+
+	listValue, listDiag := types.ListValue(types.ObjectType{
+		AttrTypes: map[string]attr.Type{
+			"id":            types.StringType,
+			"zone":          types.StringType,
+			"alias":         types.StringType,
+			"isolate_ports": types.BoolType,
+			"tag":           types.Int64Type,
+			"vlan_aware":    types.BoolType,
+		},
+	}, vnetElements)
+	resp.Diagnostics.Append(listDiag...)
+
+	if resp.Diagnostics.HasError() {
+		return
+	}
+
+	data.VNets = listValue
+	resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
+}
+
+// NewVNetsDataSource returns a new data source for SDN VNets.
+func NewVNetsDataSource() datasource.DataSource {
+	return &vnetsDataSource{}
+}
diff --git a/fwprovider/provider.go b/fwprovider/provider.go
index eb453f06..828f9270 100644
--- a/fwprovider/provider.go
+++ b/fwprovider/provider.go
@@ -573,6 +573,7 @@ func (p *proxmoxProvider) DataSources(_ context.Context) []func() datasource.Dat
 		sdnzone.NewZonesDataSource,
 		sdnsubnet.NewDataSource,
 		sdnvnet.NewDataSource,
+		sdnvnet.NewVNetsDataSource,
 		vm.NewDataSource,
 	}
 }
diff --git a/main.go b/main.go
index 507539cf..ea74f7b8 100644
--- a/main.go
+++ b/main.go
@@ -49,6 +49,7 @@ import (
 //go:generate cp ./build/docs-gen/data-sources/virtual_environment_haresource.md ./docs/data-sources/
 //go:generate cp ./build/docs-gen/data-sources/virtual_environment_haresources.md ./docs/data-sources/
 //go:generate cp ./build/docs-gen/data-sources/virtual_environment_sdn_vnet.md ./docs/data-sources/
+//go:generate cp ./build/docs-gen/data-sources/virtual_environment_sdn_vnets.md ./docs/data-sources/
 //go:generate cp ./build/docs-gen/data-sources/virtual_environment_sdn_zones.md ./docs/data-sources/
 //go:generate cp ./build/docs-gen/data-sources/virtual_environment_sdn_zone_simple.md ./docs/data-sources/
 //go:generate cp ./build/docs-gen/data-sources/virtual_environment_sdn_subnet.md ./docs/data-sources/
diff --git a/proxmox/cluster/sdn/vnets/vnets_types.go b/proxmox/cluster/sdn/vnets/vnets_types.go
index 3fc58e37..84c668ef 100644
--- a/proxmox/cluster/sdn/vnets/vnets_types.go
+++ b/proxmox/cluster/sdn/vnets/vnets_types.go
@@ -28,7 +28,8 @@ type VNet struct {
 type VNetData struct {
 	VNet
 
-	Pending *VNet `json:"pending,omitempty" url:"pending,omitempty"`
+	ID      string `json:"vnet"              url:"vnet"`
+	Pending *VNet  `json:"pending,omitempty" url:"pending,omitempty"`
 }
 
 type VNetCreate struct {
diff --git a/proxmox/types/nodes/apt/repositories/ceph_version_name.go b/proxmox/types/nodes/apt/repositories/ceph_version_name.go
index 68344413..7df4ea03 100644
--- a/proxmox/types/nodes/apt/repositories/ceph_version_name.go
+++ b/proxmox/types/nodes/apt/repositories/ceph_version_name.go
@@ -31,6 +31,9 @@ var (
 	// CephVersionNameReef is the name for the "Reef" Ceph major version.
 	CephVersionNameReef = CephVersionName{"reef"}
 
+	// CephVersionNameSquid is the name for the "Squid" Ceph major version.
+	CephVersionNameSquid = CephVersionName{"squid"}
+
 	// CephVersionNameUnknown is the name for an unknown Ceph major version.
 	CephVersionNameUnknown = CephVersionName{"unknown"}
 )
@@ -99,6 +102,8 @@ func ParseCephVersionName(input string) (CephVersionName, error) {
 		return CephVersionNameQuincy, nil
 	case CephVersionNameReef.String():
 		return CephVersionNameReef, nil
+	case CephVersionNameSquid.String():
+		return CephVersionNameSquid, nil
 	default:
 		return CephVersionName{}, ErrCephVersionNameIllegal(input)
 	}
diff --git a/proxmoxtf/resource/container/container.go b/proxmoxtf/resource/container/container.go
index acb0c790..31fc00b3 100644
--- a/proxmoxtf/resource/container/container.go
+++ b/proxmoxtf/resource/container/container.go
@@ -891,6 +891,8 @@ func Container() *schema.Resource {
 				Optional:    true,
 				ForceNew:    true,
 				Default:     dvPoolID,
+				Deprecated: "This field is deprecated and will be removed in a future release. " +
+					"To assign the container to a pool, use `proxmox_virtual_environment_pool_membership` resource instead",
 			},
 			mkProtection: {
 				Type: schema.TypeBool,
diff --git a/proxmoxtf/resource/vm/vm.go b/proxmoxtf/resource/vm/vm.go
index 3b4c769c..2beaea6e 100644
--- a/proxmoxtf/resource/vm/vm.go
+++ b/proxmoxtf/resource/vm/vm.go
@@ -1261,6 +1261,8 @@ func VM() *schema.Resource {
 			Description: "The ID of the pool to assign the virtual machine to",
 			Optional:    true,
 			Default:     dvPoolID,
+			Deprecated: "This field is deprecated and will be removed in a future release. " +
+				"To assign the VM to a pool, use `proxmox_virtual_environment_pool_membership` resource instead.",
 		},
 		mkProtection: {
 			Type:        schema.TypeBool,



Test patch:
diff --git a/fwprovider/cluster/sdn/vnet/datasource_vnets_test.go b/fwprovider/cluster/sdn/vnet/datasource_vnets_test.go
new file mode 100644
index 00000000..6b676bd7
--- /dev/null
+++ b/fwprovider/cluster/sdn/vnet/datasource_vnets_test.go
@@ -0,0 +1,249 @@
+//go:build acceptance || all
+
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/.
+ */
+
+package vnet_test
+
+import (
+	"testing"
+
+	"github.com/hashicorp/terraform-plugin-testing/helper/resource"
+
+	"github.com/bpg/terraform-provider-proxmox/fwprovider/test"
+)
+
+func TestAccDataSourceSDNVNets(t *testing.T) {
+	t.Parallel()
+
+	te := test.InitEnvironment(t)
+
+	tests := []struct {
+		name  string
+		steps []resource.TestStep
+	}{
+		{"create multiple VNets with all attributes and read with vnets datasource", []resource.TestStep{{
+			Config: te.RenderConfig(`
+				resource "proxmox_virtual_environment_sdn_zone_simple" "test" {
+					id    = "vnetstst"
+					nodes = ["{{.NodeName}}"]
+				}
+
+				resource "proxmox_virtual_environment_sdn_vnet" "test1" {
+					id            = "dsvnet1"
+					zone          = proxmox_virtual_environment_sdn_zone_simple.test.id
+					alias         = "Test VNet 1"
+					isolate_ports = true
+					vlan_aware    = false
+				}
+
+				resource "proxmox_virtual_environment_sdn_vnet" "test2" {
+					id            = "dsvnet2"
+					zone          = proxmox_virtual_environment_sdn_zone_simple.test.id
+					alias         = "Test VNet 2"
+					isolate_ports = false
+					vlan_aware    = true
+				}
+
+				resource "proxmox_virtual_environment_sdn_applier" "test_applier" {
+					depends_on = [
+						proxmox_virtual_environment_sdn_vnet.test1,
+						proxmox_virtual_environment_sdn_vnet.test2
+					]
+				}
+
+				data "proxmox_virtual_environment_sdn_vnets" "all" {
+					depends_on = [
+						proxmox_virtual_environment_sdn_applier.test_applier
+					]
+				}
+			`),
+			Check: resource.ComposeTestCheckFunc(
+				// Check that the vnets datasource returns multiple vnets
+				resource.TestCheckResourceAttrSet("data.proxmox_virtual_environment_sdn_vnets.all", "vnets.#"),
+				// Verify that vnets contain expected attributes
+				resource.TestCheckTypeSetElemNestedAttrs("data.proxmox_virtual_environment_sdn_vnets.all", "vnets.*", map[string]string{
+					"id":            "dsvnet1",
+					"zone":          "vnetstst",
+					"alias":         "Test VNet 1",
+					"isolate_ports": "true",
+					"vlan_aware":    "false",
+				}),
+				resource.TestCheckTypeSetElemNestedAttrs("data.proxmox_virtual_environment_sdn_vnets.all", "vnets.*", map[string]string{
+					"id":            "dsvnet2",
+					"zone":          "vnetstst",
+					"alias":         "Test VNet 2",
+					"isolate_ports": "false",
+					"vlan_aware":    "true",
+				}),
+			),
+		}}},
+		{"create VNets with VLAN zone and tags", []resource.TestStep{{
+			Config: te.RenderConfig(`
+				resource "proxmox_virtual_environment_sdn_zone_vlan" "test_vlan" {
+					id     = "vnetvlan"
+					nodes  = ["{{.NodeName}}"]
+					bridge = "vmbr0"
+				}
+
+				resource "proxmox_virtual_environment_sdn_vnet" "vlan1" {
+					id         = "vlan1"
+					zone       = proxmox_virtual_environment_sdn_zone_vlan.test_vlan.id
+					alias      = "VLAN VNet 1"
+					tag        = 100
+					vlan_aware = true
+				}
+
+				resource "proxmox_virtual_environment_sdn_vnet" "vlan2" {
+					id         = "vlan2"
+					zone       = proxmox_virtual_environment_sdn_zone_vlan.test_vlan.id
+					alias      = "VLAN VNet 2"
+					tag        = 200
+					vlan_aware = false
+				}
+
+				resource "proxmox_virtual_environment_sdn_applier" "test_applier" {
+					depends_on = [
+						proxmox_virtual_environment_sdn_vnet.vlan1,
+						proxmox_virtual_environment_sdn_vnet.vlan2
+					]
+				}
+
+				data "proxmox_virtual_environment_sdn_vnets" "all" {
+					depends_on = [
+						proxmox_virtual_environment_sdn_applier.test_applier
+					]
+				}
+			`),
+			Check: resource.ComposeTestCheckFunc(
+				resource.TestCheckResourceAttrSet("data.proxmox_virtual_environment_sdn_vnets.all", "vnets.#"),
+				resource.TestCheckTypeSetElemNestedAttrs("data.proxmox_virtual_environment_sdn_vnets.all", "vnets.*", map[string]string{
+					"id":         "vlan1",
+					"zone":       "vnetvlan",
+					"alias":      "VLAN VNet 1",
+					"tag":        "100",
+					"vlan_aware": "true",
+				}),
+				resource.TestCheckTypeSetElemNestedAttrs("data.proxmox_virtual_environment_sdn_vnets.all", "vnets.*", map[string]string{
+					"id":         "vlan2",
+					"zone":       "vnetvlan",
+					"alias":      "VLAN VNet 2",
+					"tag":        "200",
+					"vlan_aware": "false",
+				}),
+			),
+		}}},
+		{"create VNets with minimal attributes", []resource.TestStep{{
+			Config: te.RenderConfig(`
+				resource "proxmox_virtual_environment_sdn_zone_simple" "test_minimal" {
+					id    = "vnetmin"
+					nodes = ["{{.NodeName}}"]
+				}
+
+				resource "proxmox_virtual_environment_sdn_vnet" "minimal1" {
+					id   = "minvnet1"
+					zone = proxmox_virtual_environment_sdn_zone_simple.test_minimal.id
+				}
+
+				resource "proxmox_virtual_environment_sdn_vnet" "minimal2" {
+					id   = "minvnet2"
+					zone = proxmox_virtual_environment_sdn_zone_simple.test_minimal.id
+				}
+
+				resource "proxmox_virtual_environment_sdn_applier" "test_applier" {
+					depends_on = [
+						proxmox_virtual_environment_sdn_vnet.minimal1,
+						proxmox_virtual_environment_sdn_vnet.minimal2
+					]
+				}
+
+				data "proxmox_virtual_environment_sdn_vnets" "all" {
+					depends_on = [
+						proxmox_virtual_environment_sdn_applier.test_applier
+					]
+				}
+			`),
+			Check: resource.ComposeTestCheckFunc(
+				resource.TestCheckResourceAttrSet("data.proxmox_virtual_environment_sdn_vnets.all", "vnets.#"),
+				resource.TestCheckTypeSetElemNestedAttrs("data.proxmox_virtual_environment_sdn_vnets.all", "vnets.*", map[string]string{
+					"id":   "minvnet1",
+					"zone": "vnetmin",
+				}),
+				resource.TestCheckTypeSetElemNestedAttrs("data.proxmox_virtual_environment_sdn_vnets.all", "vnets.*", map[string]string{
+					"id":   "minvnet2",
+					"zone": "vnetmin",
+				}),
+			),
+		}}},
+		{"read vnets datasource with mixed zone types", []resource.TestStep{{
+			Config: te.RenderConfig(`
+				resource "proxmox_virtual_environment_sdn_zone_simple" "simple" {
+					id    = "mixsimpl"
+					nodes = ["{{.NodeName}}"]
+				}
+
+				resource "proxmox_virtual_environment_sdn_zone_vlan" "vlan" {
+					id     = "mixvlan"
+					nodes  = ["{{.NodeName}}"]
+					bridge = "vmbr0"
+				}
+
+				resource "proxmox_virtual_environment_sdn_vnet" "simple_vnet" {
+					id         = "mixvnet1"
+					zone       = proxmox_virtual_environment_sdn_zone_simple.simple.id
+					alias      = "Simple Zone VNet"
+					vlan_aware = false
+				}
+
+				resource "proxmox_virtual_environment_sdn_vnet" "vlan_vnet" {
+					id         = "mixvnet2"
+					zone       = proxmox_virtual_environment_sdn_zone_vlan.vlan.id
+					alias      = "VLAN Zone VNet"
+					tag        = 300
+					vlan_aware = true
+				}
+
+				resource "proxmox_virtual_environment_sdn_applier" "test_applier" {
+					depends_on = [
+						proxmox_virtual_environment_sdn_vnet.simple_vnet,
+						proxmox_virtual_environment_sdn_vnet.vlan_vnet
+					]
+				}
+
+				data "proxmox_virtual_environment_sdn_vnets" "all" {
+					depends_on = [
+						proxmox_virtual_environment_sdn_applier.test_applier
+					]
+				}
+			`),
+			Check: resource.ComposeTestCheckFunc(
+				resource.TestCheckResourceAttrSet("data.proxmox_virtual_environment_sdn_vnets.all", "vnets.#"),
+				resource.TestCheckTypeSetElemNestedAttrs("data.proxmox_virtual_environment_sdn_vnets.all", "vnets.*", map[string]string{
+					"id":         "mixvnet1",
+					"zone":       "mixsimpl",
+					"alias":      "Simple Zone VNet",
+					"vlan_aware": "false",
+				}),
+				resource.TestCheckTypeSetElemNestedAttrs("data.proxmox_virtual_environment_sdn_vnets.all", "vnets.*", map[string]string{
+					"id":         "mixvnet2",
+					"zone":       "mixvlan",
+					"alias":      "VLAN Zone VNet",
+					"tag":        "300",
+					"vlan_aware": "true",
+				}),
+			),
+		}}},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			resource.ParallelTest(t, resource.TestCase{
+				ProtoV6ProviderFactories: te.AccProviders,
+				Steps:                    tt.steps,
+			})
+		})
+	}
+}
diff --git a/fwprovider/types/nodes/apt/standard_repo_handle_test.go b/fwprovider/types/nodes/apt/standard_repo_handle_test.go
index d99ac347..39692724 100644
--- a/fwprovider/types/nodes/apt/standard_repo_handle_test.go
+++ b/fwprovider/types/nodes/apt/standard_repo_handle_test.go
@@ -44,7 +44,7 @@ func TestStandardRepoHandleValueFromTerraform(t *testing.T) {
 					val.ValueString() == "ceph-foo-enterprise"
 			},
 		},
-		"valid Ceph APT standard repository handle": {
+		`valid Ceph "enterprise" APT standard repository handle`: {
 			val: tftypes.NewValue(tftypes.String, "ceph-quincy-enterprise"),
 			expected: func(val StandardRepoHandleValue) bool {
 				return val.kind == apitypes.StandardRepoHandleKindEnterprise &&
@@ -55,15 +55,26 @@ func TestStandardRepoHandleValueFromTerraform(t *testing.T) {
 					val.ValueString() == "ceph-quincy-enterprise"
 			},
 		},
+		`valid Ceph "no subscription" APT standard repository handle`: {
+			val: tftypes.NewValue(tftypes.String, "ceph-reef-no-subscription"),
+			expected: func(val StandardRepoHandleValue) bool {
+				return val.kind == apitypes.StandardRepoHandleKindNoSubscription &&
+					val.CephVersionName() == apitypes.CephVersionNameReef &&
+					val.IsCephHandle() &&
+					val.IsSupportedFilePath(apitypes.StandardRepoFilePathCeph) &&
+					val.ComponentName() == "no-subscription" &&
+					val.ValueString() == "ceph-reef-no-subscription"
+			},
+		},
 		`valid Ceph "test" APT standard repository handle`: {
-			val: tftypes.NewValue(tftypes.String, "ceph-reef-test"),
+			val: tftypes.NewValue(tftypes.String, "ceph-squid-test"),
 			expected: func(val StandardRepoHandleValue) bool {
 				return val.kind == apitypes.StandardRepoHandleKindTest &&
-					val.CephVersionName() == apitypes.CephVersionNameReef &&
+					val.CephVersionName() == apitypes.CephVersionNameSquid &&
 					val.IsCephHandle() &&
 					val.IsSupportedFilePath(apitypes.StandardRepoFilePathCeph) &&
 					val.ComponentName() == "test" &&
-					val.ValueString() == "ceph-reef-test"
+					val.ValueString() == "ceph-squid-test"
 			},
 		},
 		"invalid APT repository handle": {
diff --git a/proxmox/types/nodes/apt/repositories/ceph_version_name_test.go b/proxmox/types/nodes/apt/repositories/ceph_version_name_test.go
new file mode 100644
index 00000000..68f6cf1b
--- /dev/null
+++ b/proxmox/types/nodes/apt/repositories/ceph_version_name_test.go
@@ -0,0 +1,182 @@
+/*
+	This Source Code Form is subject to the terms of the Mozilla Public
+	License, v. 2.0. If a copy of the MPL was not distributed with this
+	file, You can obtain one at https://mozilla.org/MPL/2.0/.
+*/
+
+package repositories
+
+import (
+	"encoding/json"
+	"testing"
+
+	"github.com/stretchr/testify/require"
+)
+
+func TestParseCephVersionName(t *testing.T) {
+	t.Parallel()
+
+	tests := map[string]struct {
+		input       string
+		expected    CephVersionName
+		expectError bool
+	}{
+		"quincy": {
+			input:    "quincy",
+			expected: CephVersionNameQuincy,
+		},
+		"reef": {
+			input:    "reef",
+			expected: CephVersionNameReef,
+		},
+		"squid": {
+			input:    "squid",
+			expected: CephVersionNameSquid,
+		},
+		"invalid": {
+			input:       "invalid",
+			expectError: true,
+		},
+		"empty": {
+			input:       "",
+			expectError: true,
+		},
+		"uppercase": {
+			input:       "QUINCY",
+			expectError: true,
+		},
+	}
+
+	for name, test := range tests {
+		t.Run(name, func(t *testing.T) {
+			t.Parallel()
+
+			result, err := ParseCephVersionName(test.input)
+
+			if test.expectError {
+				require.Error(t, err)
+			} else {
+				require.NoError(t, err)
+				require.Equal(t, test.expected, result)
+			}
+		})
+	}
+}
+
+func TestCephVersionNameString(t *testing.T) {
+	t.Parallel()
+
+	tests := map[string]struct {
+		version  CephVersionName
+		expected string
+	}{
+		"quincy": {
+			version:  CephVersionNameQuincy,
+			expected: "quincy",
+		},
+		"reef": {
+			version:  CephVersionNameReef,
+			expected: "reef",
+		},
+		"squid": {
+			version:  CephVersionNameSquid,
+			expected: "squid",
+		},
+		"unknown": {
+			version:  CephVersionNameUnknown,
+			expected: "unknown",
+		},
+	}
+
+	for name, test := range tests {
+		t.Run(name, func(t *testing.T) {
+			t.Parallel()
+
+			result := test.version.String()
+			require.Equal(t, test.expected, result)
+		})
+	}
+}
+
+func TestCephVersionNameMarshalJSON(t *testing.T) {
+	t.Parallel()
+
+	tests := map[string]struct {
+		version  CephVersionName
+		expected string
+	}{
+		"quincy": {
+			version:  CephVersionNameQuincy,
+			expected: `"quincy"`,
+		},
+		"reef": {
+			version:  CephVersionNameReef,
+			expected: `"reef"`,
+		},
+		"squid": {
+			version:  CephVersionNameSquid,
+			expected: `"squid"`,
+		},
+		"unknown": {
+			version:  CephVersionNameUnknown,
+			expected: `"unknown"`,
+		},
+	}
+
+	for name, test := range tests {
+		t.Run(name, func(t *testing.T) {
+			t.Parallel()
+
+			result, err := json.Marshal(test.version)
+			require.NoError(t, err)
+			require.Equal(t, test.expected, string(result))
+		})
+	}
+}
+
+func TestCephVersionNameUnmarshalJSON(t *testing.T) {
+	t.Parallel()
+
+	tests := map[string]struct {
+		input       string
+		expected    CephVersionName
+		expectError bool
+	}{
+		"quincy": {
+			input:    `"quincy"`,
+			expected: CephVersionNameQuincy,
+		},
+		"reef": {
+			input:    `"reef"`,
+			expected: CephVersionNameReef,
+		},
+		"squid": {
+			input:    `"squid"`,
+			expected: CephVersionNameSquid,
+		},
+		"invalid": {
+			input:       `"invalid"`,
+			expectError: true,
+		},
+		"malformed json": {
+			input:       `quincy`,
+			expectError: true,
+		},
+	}
+
+	for name, test := range tests {
+		t.Run(name, func(t *testing.T) {
+			t.Parallel()
+
+			var result CephVersionName
+			err := json.Unmarshal([]byte(test.input), &result)
+
+			if test.expectError {
+				require.Error(t, err)
+			} else {
+				require.NoError(t, err)
+				require.Equal(t, test.expected, result)
+			}
+		})
+	}
+}