[GH-ISSUE #145] API calls for doing a disk import? #35

Open
opened 2026-03-03 15:29:46 +03:00 by kerem · 9 comments
Owner

Originally created by @justinclift on GitHub (Apr 29, 2024).
Original GitHub issue: https://github.com/luthermonson/go-proxmox/issues/145

Trying to do a disk import, as would be done using qm disk import, but remotely using the API:

# qm disk import 100 /path/to/some/disk.qcow2 local-zfs

Not really seeing anything obviously correct for this, and nothing suitable is showing up in the official API viewer either as I look through it.

Anyone have suggestions? 😄

Originally created by @justinclift on GitHub (Apr 29, 2024). Original GitHub issue: https://github.com/luthermonson/go-proxmox/issues/145 Trying to do a disk import, as would be done using `qm disk import`, but remotely using the API: ``` # qm disk import 100 /path/to/some/disk.qcow2 local-zfs ``` Not really seeing anything obviously correct for this, and nothing suitable is showing up in the [official API viewer](https://pve.proxmox.com/pve-docs/api-viewer) either as I look through it. Anyone have suggestions? :smile:
Author
Owner

@justinclift commented on GitHub (Apr 29, 2024):

Hmmm, this might be the correct API call:

https://pve.proxmox.com/pve-docs/api-viewer/#/nodes/{node}/storage/{storage}/content

Will probably try that out later on today. 😄

<!-- gh-comment-id:2083826698 --> @justinclift commented on GitHub (Apr 29, 2024): Hmmm, this **might** be the correct API call: https://pve.proxmox.com/pve-docs/api-viewer/#/nodes/{node}/storage/{storage}/content Will probably try that out later on today. :smile:
Author
Owner

@justinclift commented on GitHub (Apr 30, 2024):

That API end point can indeed create new VM disk/volume definitions:

# pvesh create /nodes/somenode/storage/local-zfs/content --filename "vm-100-disk-4" --size 1G --vmid 100

That creates the new ZFS volume in the local-zfs storage, and also creates the matching (empty) ZFS volume in the backend ZFS pool.

I'm not (yet) seeing how to fill that volume with actual disk data though. If the Go code was running on the server then it could just directly write into the disk device.

But how to do it remotely? That's the next needed step.

<!-- gh-comment-id:2084685778 --> @justinclift commented on GitHub (Apr 30, 2024): That API end point can indeed create new VM disk/volume definitions: ``` # pvesh create /nodes/somenode/storage/local-zfs/content --filename "vm-100-disk-4" --size 1G --vmid 100 ``` That creates the new ZFS volume in the `local-zfs` storage, and also creates the matching (empty) ZFS volume in the backend ZFS pool. I'm not (yet) seeing how to fill that volume with actual disk data though. If the Go code was running on the server then it could just directly write into the disk device. But how to do it remotely? That's the next needed step.
Author
Owner

@justinclift commented on GitHub (Apr 30, 2024):

Looking at the qm source code, it seems like the loading of data into the newly created volume is done by qemu-img running on the node itself and writing directly into the destination device:

That may mean there's no mechanism in place (yet) for uploading disk images remotely via the API. Well, data other than ISO images and templates.

Will probably need to ask on the Proxmox forum somewhere, or pve-devel mailing list. 😄

<!-- gh-comment-id:2084785939 --> @justinclift commented on GitHub (Apr 30, 2024): Looking at the `qm` source code, it seems like the loading of data into the newly created volume is done by `qemu-img` running on the node itself and writing directly into the destination device: * https://github.com/proxmox/qemu-server/blob/54aa98cea5071b5cd325cfaeb21b7aaa4af9bb4d/PVE/QemuServer/ImportDisk.pm#L76 * https://github.com/proxmox/qemu-server/blob/54aa98cea5071b5cd325cfaeb21b7aaa4af9bb4d/PVE/QemuServer.pm#L7835-L7862 That may mean there's no mechanism in place (yet) for uploading disk images remotely via the API. Well, data other than ISO images and templates. Will probably need to ask on the Proxmox forum somewhere, or pve-devel mailing list. :smile:
Author
Owner

@justinclift commented on GitHub (May 23, 2024):

Looks like this isn't yet possible. 😦

https://forum.proxmox.com/threads/proxmox-api-import-disk.68171/

<!-- gh-comment-id:2127571217 --> @justinclift commented on GitHub (May 23, 2024): Looks like this isn't yet possible. :frowning: https://forum.proxmox.com/threads/proxmox-api-import-disk.68171/
Author
Owner

@luthermonson commented on GitHub (May 23, 2024):

well that's a bummer

<!-- gh-comment-id:2128007902 --> @luthermonson commented on GitHub (May 23, 2024): well that's a bummer
Author
Owner

@AndreiLacatos commented on GitHub (Nov 29, 2025):

Kinda late to the party but figured out you can import a disk by specifying STORAGE_ID:0 and import-from.

curl -vv --insecure  --cookie "$(<cookie)" --header "$(<csrftoken)" -X 
 --data-urlencode scsi0=SOME_STORAGE:0,import-from=/path/to/some/image \
 https://localhost:8006/api2/json/nodes/$TARGETNODE/qemu/$VMID/config

The following snippet is the equivalent of the above curl request:

    insecureHTTPClient := &http.Client{
		Transport: &http.Transport{
			TLSClientConfig: &tls.Config{
				InsecureSkipVerify: true,
			},
		},
	}

	proxmox := px.NewClient(
		"https://localhost:8006/api2/json",
		px.WithHTTPClient(insecureHTTPClient),
		px.WithCredentials(&px.Credentials{
			Username: "root",
			Password: "somepassword",
			Realm:    "pam",
		}),
		px.WithLogger(&px.LeveledLogger{
			Level: px.LevelDebug,
		}),
	)

	node, _ := proxmox.Node(context.Background(), proxmoxNode)
	vm, _ := node.VirtualMachine(context.Background(), vmId)
	task, _ := vm.Config(context.Background(), px.VirtualMachineOption{
		Name:  "scsi0",
		Value: "SOME_STORAGE:0,import-from=/path/to/some/image",
	})

Notice that it requires root auth credentials instead of API token. Have not figured out how replace that with an API token, seems like it refuses to do anything even if the API token is issued for root@pam

<!-- gh-comment-id:3591949991 --> @AndreiLacatos commented on GitHub (Nov 29, 2025): Kinda late to the party but figured out you can import a disk by specifying `STORAGE_ID:0` and `import-from`. ```sh curl -vv --insecure --cookie "$(<cookie)" --header "$(<csrftoken)" -X --data-urlencode scsi0=SOME_STORAGE:0,import-from=/path/to/some/image \ https://localhost:8006/api2/json/nodes/$TARGETNODE/qemu/$VMID/config ``` The following snippet is the equivalent of the above `curl` request: ```go insecureHTTPClient := &http.Client{ Transport: &http.Transport{ TLSClientConfig: &tls.Config{ InsecureSkipVerify: true, }, }, } proxmox := px.NewClient( "https://localhost:8006/api2/json", px.WithHTTPClient(insecureHTTPClient), px.WithCredentials(&px.Credentials{ Username: "root", Password: "somepassword", Realm: "pam", }), px.WithLogger(&px.LeveledLogger{ Level: px.LevelDebug, }), ) node, _ := proxmox.Node(context.Background(), proxmoxNode) vm, _ := node.VirtualMachine(context.Background(), vmId) task, _ := vm.Config(context.Background(), px.VirtualMachineOption{ Name: "scsi0", Value: "SOME_STORAGE:0,import-from=/path/to/some/image", }) ``` Notice that it requires root auth credentials instead of API token. Have not figured out how replace that with an API token, seems like it refuses to do anything even if the API token is issued for `root@pam`
Author
Owner

@justinclift commented on GitHub (Nov 30, 2025):

While that's useful, it seems like the Proxmox API still doesn't allow for directly passing the actual image content itself in the call. So, it's still relying on a previous upload of the image to a location accessible via (for example) file://.

Really wish they'd get the last outstanding piece of this puzzle implemented, so people could just pass the entire image via API instead. Without that last piece, the API isn't complete enough to be a replacement for just a series of ssh calls. ☹️

<!-- gh-comment-id:3592067348 --> @justinclift commented on GitHub (Nov 30, 2025): While that's useful, it seems like the Proxmox API still doesn't allow for directly passing the actual image content itself in the call. So, it's still relying on a previous upload of the image to a location accessible via (for example) `file://`. Really wish they'd get the last outstanding piece of this puzzle implemented, so people could just pass the entire image via API instead. Without that last piece, the API isn't complete enough to be a replacement for just a series of ssh calls. ☹️
Author
Owner

@AndreiLacatos commented on GitHub (Nov 30, 2025):

If you have the luxury to edit files on the Proxmox environment:

Found a dirty hack/workaround that you can apply to the authorization process. /usr/share/perl5/PVE/Storage.pm handles path check & authorization, that is where the Only root can pass arbitrary filesystem paths. error originates from. Instead of $user ne 'root@pam' you could do something like $user ne 'johndoe@pam!sometoken' to allow a specific API token.

Could be fine if you are running Proxmox in a sealed/sandboxed environment in single node setup as hobbyist.

Note: with high probability, Proxmox updates at one point might overwrite these changes
Note: production usage strongly discouraged

<!-- gh-comment-id:3592394643 --> @AndreiLacatos commented on GitHub (Nov 30, 2025): If you have the luxury to edit files on the Proxmox environment: Found a dirty hack/workaround that you can apply to the authorization process. `/usr/share/perl5/PVE/Storage.pm` handles path check & authorization, that is where the [`Only root can pass arbitrary filesystem paths.`](https://github.com/proxmox/pve-storage/blob/6f49432acc6d030017c5f8833a17b33c6ae00324/src/PVE/Storage.pm#L651C14-L651C60) error originates from. Instead of [`$user ne 'root@pam'`](https://github.com/proxmox/pve-storage/blob/6f49432acc6d030017c5f8833a17b33c6ae00324/src/PVE/Storage.pm#L652C16-L652C35) you could do something like `$user ne 'johndoe@pam!sometoken'` to allow a specific API token. Could be fine if you are running Proxmox in a sealed/sandboxed environment in single node setup as hobbyist. Note: with high probability, Proxmox updates at one point might overwrite these changes Note: production usage strongly discouraged
Author
Owner

@jqueuniet commented on GitHub (Nov 30, 2025):

Regarding the API token issue, it's indeed related to root@pam being hardcoded all over the source code. There's a patch for adding a sys.Root permission that has been rotting away on mailing lists and butrackers for years.

https://bugzilla.proxmox.com/show_bug.cgi?id=2582

<!-- gh-comment-id:3592409733 --> @jqueuniet commented on GitHub (Nov 30, 2025): Regarding the API token issue, it's indeed related to `root@pam` being hardcoded all over the source code. There's a patch for adding a `sys.Root` permission that has been rotting away on mailing lists and butrackers for years. https://bugzilla.proxmox.com/show_bug.cgi?id=2582
Sign in to join this conversation.
No labels
pull-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/go-proxmox#35
No description provided.