Giter VIP home page Giter VIP logo

go-proxmox's Introduction

Proxmox API Client Go Package

Continuous Integration GitHub license GitHub issues GitHub release codecov Go Report Card Go Reference

Join the community to discuss ongoing client development usage, the proxmox API or tooling in the #go-proxmox channel on the Gophers Slack and see the self generated docs for more usage details.

Slack

A go client for Proxmox VE. The client implements /api2/json and inspiration was drawn from the existing Telmate package but looking to improve in the following ways...

  • Treated as a proper standalone go package
  • Types and JSON marshal/unmarshalling for all end points
  • Full Testing, unit testing with mocks and integration tests against an API endpoint
  • Configuration options when creating a client for flexible usage
  • Client logging for debugging within your code
  • Context support
  • Added functionality for better go tooling built on this library, some things we'd like
    • Boot VM from qcow URL, inspiration: Proxmox Linux Templates
    • Dynamic host targeting for VM, Proxmox lacks a scheduler when given VM params it will try and locate a host with resources to put it
    • cloud-init support via no-cloud ISOs uploaded to node data stores and auto-mounted before boot, inspiration quiso
    • Unattended XML Support via ISOs similar to cloud-init ideas
    • node/vm/container shell command support via KVM proxy already built into proxmox

Core developers are home lab enthusiasts working in the virtualization and kubernetes space. The common use case we have for Proxmox is dev stress testing and validation of functionality in the products we work on, we plan to build the following tooling around this library to make that easier.

Usage

Create a client and use the public methods to access Proxmox resources.

Basic usage with login with a username and password credential

package main

import (
	"context"
	"fmt"
	
	"github.com/luthermonson/go-proxmox"
)

func main() {
    credentials := proxmox.Credentials{
		Username: "root@pam", 
		Password: "12345",
    }
    client := proxmox.NewClient("https://localhost:8006/api2/json",
		proxmox.WithCredentials(&credentials),
    )
	
    version, err := client.Version(context.Background())
    if err != nil {
        panic(err)
    }
    fmt.Println(version.Release) // 7.4
}

Usage with Client Options

package main

import (
	"context"
	"crypto/tls"
	"fmt"
	"net/http"
	
	"github.com/luthermonson/go-proxmox"
)

func main() {
    insecureHTTPClient := http.Client{
        Transport: &http.Transport{
            TLSClientConfig: &tls.Config{
                InsecureSkipVerify: true,
            },
        },
    }
    tokenID := "root@pam!mytoken"
    secret := "somegeneratedapitokenguidefromtheproxmoxui"
    
    client := proxmox.NewClient("https://localhost:8006/api2/json",
        proxmox.WithHTTPClient(&insecureHTTPClient),
        proxmox.WithAPIToken(tokenID, secret),
    )
    
    version, err := client.Version(context.Background())
    if err != nil {
        panic(err)
    }
    fmt.Println(version.Release) // 6.3
}

Developing

This project relies on Mage for cross os/arch compatibility, please see their installation guide.

Unit Testing

Run mage test to run the unit tests in the root directory.

Integration Testing

To run the integration testing suite against an existing Proxmox API set some env vars in your shell before running mage testIntegration. The integration tests will test logging in and using an API token credentials so make sure you set all five env vars before running tests for them to pass.

Please leave no trace when developing integration tests. All tests should create and remove all testing data they generate then they can be repeatably run against the same proxmox environment. Most people working on this package will likely use their personal Proxmox VE home lab and consuming extra resources via tests will lead to frustration.

Bash

export PROXMOX_URL="https://192.168.1.6:8006/api2/json"
export PROXMOX_USERNAME="root@pam"
export PROXMOX_PASSWORD="password"
export PROXMOX_TOKENID="root@pam!mytoken"
export PROXMOX_SECRET="somegeneratedapitokenguidefromtheproxmoxui"

mage test:integration

Powershell

$Env:PROXMOX_URL = "https://192.168.1.6:8006/api2/json"
$Env:PROXMOX_USERNAME = "root@pam"
$Env:PROXMOX_PASSWORD = "password"
$Env:PROXMOX_TOKENID = "root@pam!mytoken"
$Env:PROXMOX_SECRET = "somegeneratedapitokenguidefromtheproxmoxui"

mage test:integration

go-proxmox's People

Contributors

alperencelik avatar armmaster17 avatar bl4ko avatar boyvinall avatar federicoantoniazzi avatar hilaoyu avatar jlan45 avatar jqueuniet avatar luthermonson avatar mcbenjemaa avatar mhkarimi1383 avatar mperezd avatar phillipsj avatar pivnoy avatar ricardoalcantara avatar simplysoft avatar stormyudi avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

go-proxmox's Issues

VirtualMachine.IsRunning and VirtualMachine.IsStopped unconditionally rely on fields that VirtualMachine may not have

Starting this issue with the full disclosure that I know enough Go and enough Proxmox to be dangerous, but not much more than that.

It seems that the VirtualMachine type is written in such a way that it is not necessarily expected to always get a value for QMPStatus:

QMPStatus      string `json:"qmpstatus,omitempty"`

But the VirtualMachine.IsRunning() and VirtualMachine.IsStopped() functions (and likely others) essentially require QMPStatus to be set to work.

func (v *VirtualMachine) IsRunning() bool {
	return v.Status == StatusVirtualMachineRunning && v.QMPStatus == StatusVirtualMachineRunning
}

As such (for reasons not clear to me), I have VMs on my Proxmox server that are not returning anything for QMPStatus, so IsRunning() always returns false despite the fact that the VMs are running.

Should this be checking for empty values before comparing QMPStatus? If so, I am willing to try to make a PR for that. I Just wanted to make sure I'm not misunderstanding what is happening before I attempt that.

Thanks!

cloud-init returns unexpected end of JSON input

Hey, Ive been trying this for at least 6hs now and cant really wrap my head around it. Ive created two very basic cloudinit files as strings (just metadata and the cloudinit file, the rest should be optional after checking the code).
It keeps returning unexpected end of JSON input despite being valid yaml. Ive also tried just passing JSON directly, but this also fails with the same issue.
Also, there is no real documentation of what device should be.
I have tried numerous values but that does not affect the end result.

	// Define the cloud-init configuration strings
	userdata := `
#cloud-config
users:
  - name: default
	  
	  `

	metadata := `
instance-id: iid-123456

`
	device := "ide2"

	// Call the CloudInit method
	err = createdVM.CloudInit(ctx, device, userdata, metadata, "", "")

ISO Management + VM Tests

we should do a similar create/start/stop/remove integration test like we do for containers but on a qemu virtual machine. perhaps when we get to the iso upload/management apis we figure out how to upload a small linux iso and boot a vm and see if it comes up.

Considerer remove the 'auto' breakline in VNCWebSocket

Hi there! I'm currently developing a middleware in Go that interfaces between Proxmox and a web console. In the frontend, I'm utilizing xtermjs. However, I've encountered an issue where a line break is added after every key sent to Proxmox, disrupting the seamless usage of xtermjs.

Here's the relevant code snippet where the issue occurs: proxmox.go#L436

It seems that the current implementation is designed to send complete commands, but I'd prefer a solution where every character, including line breaks, can be sent individually. This would enable smoother interaction with xtermjs, allowing even backspace functionality to work seamlessly.

Text enhanced by ChatGPT.

API calls for doing a disk import?

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? 😄

[test] Get termproxy/vnc websocket Running

proxmox offers a tunnel into everything via a termproxy end point and a websocket. the UI seems to make a call to termproxy, grab a ticket and then issue a websocket call to tunnel in. we should figure out how to get the socket started and tunnel into the node, vms and containers so we can tunnel in and run shell commands against them.

Virtual Machine VNC Web Socket

After getting the termproxy and vncwebsocket end points working I've run into something with virtual machines which I will document here for others to see. The basics are you need a serial terminal for the websocket to work properly. You will need to add a serial0: socket config to the VM like this

	task, err = vm.Config(
		VirtualMachineOption{Name: "serial0", Value: "socket"},
	)

if you do not have the interface setup your proxy will return unable to find a serial interface. When you have the socket seriali interface configured you will see the following starting serial terminal on interface serial0.

Just adding the interface is not everything, you will need to follow the guide to configure the guest Virtual Machine actually use it, ideally this can be documented on how to setup cloud-init or ignition to bootstrap the serial0 socket device properly and move to a wiki how-to guide.

json: cannot unmarshal string into Go struct field VirtualMachineConfig.cpulimit of type float32

I forgot to specify that it would came from string.

https://$PROXMOX_NODE_IP:8006/api2/json/nodes/$PROXMOX_NODE_NAME/qemu/$VMID/config

{
  "data": {
    "cores": 2,
    "name": "minha-nova-vps",
    "bootdisk": "scsi0",
    "net0": "virtio=5A:95:56:B3:18:1C,bridge=vmbr0",
    "vga": "serial0",
    "ipconfig0": "gw=192.168.0.1,ip=192.168.0.154/24",
    "memory": 2048,
    "smbios1": "uuid=5059a66c-23d5-461b-a3cb-004eb3124718",
    "boot": "c",
    "scsihw": "virtio-scsi-pci",
    "serial0": "socket",
    "ide2": "local-lvm:vm-505-cloudinit,media=cdrom,size=4M",
    "meta": "creation-qemu=7.2.0,ctime=1691463271",
    "cipassword": "**********",
    "agent": "enabled=1,fstrim_cloned_disks=1",
    "vmgenid": "d4443aa6-b66f-45b2-97ff-6dee78eade44",
    "ciuser": "root",
    "cpulimit": "0.4",
    "digest": "aa9ce37c4df320889d4ab5382a2947efa4c1d815",
    "scsi0": "local-lvm:vm-505-disk-0,size=60G"
  }
}

I actually didn't know about that, I learned if from here https://stackoverflow.com/a/9573928

I should have mapped something like this

CPULimit float32 `json:"cpulimit,omitempty,string"`

This time I actually tested, sorry for the trouble!

type Tasks []*Tasks

Hi,
thanks a lot for this great interface to proxmox!
I think that line 576 of Types.go shoud not read

type Tasks []*Tasks
but
type Tasks []*Task

best regards
Andy

rrddata Endpoint Support & Missing/Outdated Elements in various structs

Hi there,

I was wondering if there is planning on implementing the rrddata Endpoint /api2/json/nodes/pve/qemu/<vmid>/rrddata
With that I also have another question, why is the VirtualMachine struct and several other structs that outdated? There are several elements missing. The Library still seems to be actively maintained and updated except for the described issue. Is this on purpose?

Thank you in advance! :)

Release v0.1.0

I think It's time to plan for the first release v0.1.0

Weird "sshkeys" SSH public key validation error

I'm trying to create a VM with a cloud-init ssh key, but the server keeps on returning 500 SSH public key validation error. 😕

It seems pretty weird, as the exact same key works fine when using qm on the server itself to create the VM.

The code in question for creating the VM:

vmProps := []proxmox.VirtualMachineOption{
	{Name: "name", Value: "test1"},
	{Name: "memory", Value: 1024 * 8},
	{Name: "cores", Value: 6},
	{Name: "cpu", Value: "host"},
	{Name: "net0", Value: "model=virtio,bridge=" + publicBridge + ",firewall=1"},
	{Name: "scsihw", Value: "virtio-scsi-single"},
	{Name: "virtio1", Value: "local-zfs:16,cache=" + cacheMode + ",discard=on,iothread=1"},
	{Name: "agent", Value: 1},
	{Name: "ostype", Value: "l26"},
	{Name: "localtime", Value: "0"},
	{Name: "ide0", Value: "local-zfs:cloudinit"},
	{Name: "ipconfig0", Value: "gw=10.1.1.1,ip=10.1.248." + strconv.Itoa(vmID) + "/16"},
	{Name: "sshkeys", Value: url.QueryEscape("/root/.ssh/id_rsa.pub")},
}
vmTask, err := node.NewVirtualMachine(ctx, vmID, vmProps...)
if err != nil {
	log.Fatal(err)
}

If I remove that last vmProps line (the sshkeys one), then the vm creation works. With that in place though, I'm getting:

2024/04/30 04:12:44 500 SSH public key validation error

The working qm version of it:

# Create a new VM
qm create ${VMID} --name "test1" \
  --cpu host \
  --cores 6 \
  --memory 8192 \
  --net0 virtio,bridge=${PUBLIC_BRIDGE},firewall=1 \
  --scsihw virtio-scsi-single \
  --virtio1 local-zfs:16,cache=${CACHE_MODE},discard=on,iothread=1 \
  --agent 1 \
  --ostype l26 \
  --localtime 0 \
  --ide0 local-zfs:cloudinit \
  --ipconfig0 gw=10.1.1.1,ip=10.1.248.${VMID}/16 \
  --sshkeys "~/.ssh/id_rsa.pub"

Anyone have ideas what could be going wrong?

Add Container Creating/Removing + Testing

Add endpoints to create and delete containers and add tests to create, start/stop and remove a container. maybe for this we use nginx base container and check for 200OK + welcome to nginx text. check out docker run -d --name nginx -p 8081:80 --restart=always nginx and what it boots on localhost:8081 and just test for that

RRDData don't return all datas

Hello,

I'm trying to pull RRDDatas for a vm with go-proxmox, however the data are not complete :
metrics, err := vm.RRDData(context.Background(), proxmox.TimeframeHour)

returns :

[00] &{MaxCPU:1 MaxMem:1073741824 Disk:0 MaxDisk:16106127360 Time:1706343600}
[00] &{MaxCPU:1 MaxMem:1073741824 Disk:0 MaxDisk:16106127360 Time:1706343660}
[00] &{MaxCPU:1 MaxMem:1073741824 Disk:0 MaxDisk:16106127360 Time:1706343720}
[00] &{MaxCPU:1 MaxMem:1073741824 Disk:0 MaxDisk:16106127360 Time:1706343780}
[00] &{MaxCPU:1 MaxMem:1073741824 Disk:0 MaxDisk:16106127360 Time:1706343840}
[00] &{MaxCPU:1 MaxMem:1073741824 Disk:0 MaxDisk:16106127360 Time:1706343900}
[00] &{MaxCPU:1 MaxMem:1073741824 Disk:0 MaxDisk:16106127360 Time:1706343960}
[00] &{MaxCPU:1 MaxMem:1073741824 Disk:0 MaxDisk:16106127360 Time:1706344020}
[00] &{MaxCPU:1 MaxMem:1073741824 Disk:0 MaxDisk:16106127360 Time:1706344080}
[00] &{MaxCPU:1 MaxMem:1073741824 Disk:0 MaxDisk:16106127360 Time:1706344140}
[00] &{MaxCPU:1 MaxMem:1073741824 Disk:0 MaxDisk:16106127360 Time:1706344200}
[00] &{MaxCPU:1 MaxMem:1073741824 Disk:0 MaxDisk:16106127360 Time:1706344260}
[00] &{MaxCPU:1 MaxMem:1073741824 Disk:0 MaxDisk:16106127360 Time:1706344320}
[00] &{MaxCPU:1 MaxMem:1073741824 Disk:0 MaxDisk:16106127360 Time:1706344380}
[00] &{MaxCPU:1 MaxMem:1073741824 Disk:0 MaxDisk:16106127360 Time:1706344440}
[00] &{MaxCPU:1 MaxMem:1073741824 Disk:0 MaxDisk:16106127360 Time:1706344500}
[00] &{MaxCPU:1 MaxMem:1073741824 Disk:0 MaxDisk:16106127360 Time:1706344560}
[00] &{MaxCPU:1 MaxMem:1073741824 Disk:0 MaxDisk:16106127360 Time:1706344620}
[00] &{MaxCPU:1 MaxMem:1073741824 Disk:0 MaxDisk:16106127360 Time:1706344680}
[00] &{MaxCPU:1 MaxMem:1073741824 Disk:0 MaxDisk:16106127360 Time:1706344740}
[00] &{MaxCPU:1 MaxMem:1073741824 Disk:0 MaxDisk:16106127360 Time:1706344800}
[00] &{MaxCPU:1 MaxMem:1073741824 Disk:0 MaxDisk:16106127360 Time:1706344860}
[00] &{MaxCPU:1 MaxMem:1073741824 Disk:0 MaxDisk:16106127360 Time:1706344920}
[00] &{MaxCPU:1 MaxMem:1073741824 Disk:0 MaxDisk:16106127360 Time:1706344980}
[00] &{MaxCPU:1 MaxMem:1073741824 Disk:0 MaxDisk:16106127360 Time:1706345040}
[00] &{MaxCPU:1 MaxMem:1073741824 Disk:0 MaxDisk:16106127360 Time:1706345100}
[00] &{MaxCPU:1 MaxMem:1073741824 Disk:0 MaxDisk:16106127360 Time:1706345160}
[00] &{MaxCPU:1 MaxMem:1073741824 Disk:0 MaxDisk:16106127360 Time:1706345220}
[00] &{MaxCPU:1 MaxMem:1073741824 Disk:0 MaxDisk:16106127360 Time:1706345280}
[00] &{MaxCPU:1 MaxMem:1073741824 Disk:0 MaxDisk:16106127360 Time:1706345340}
[00] &{MaxCPU:1 MaxMem:1073741824 Disk:0 MaxDisk:16106127360 Time:1706345400}
[00] &{MaxCPU:1 MaxMem:1073741824 Disk:0 MaxDisk:16106127360 Time:1706345460}
[00] &{MaxCPU:1 MaxMem:1073741824 Disk:0 MaxDisk:16106127360 Time:1706345520}

The datas are always the same as it only returns the "max" and there is a lot of stuff missing. If i compare it to :

pvesh get /nodes/mtl1/qemu/138/rrddata --timeframe=hour --output-format=json

which returns :

{"cpu":0.124238321859991,"disk":0,"diskread":0,"diskwrite":4724.05333333333,"maxcpu":1,"maxdisk":16106127360,"maxmem":1073741824,"mem":432397243.733333,"netin":9832.04666666667,"netout":14.38,"time":1706344620},{"cpu":0.125377080353475,"disk":0,"diskread":0,"diskwrite":4614.82666666667,"maxcpu":1,"maxdisk":16106127360,"maxmem":1073741824,"mem":432381952,"netin":10647.8133333333,"netout":22.1066666666667,"time":1706344680},{"cpu":0.12763936071886,"disk":0,"diskread":0,"diskwrite":2962.77333333333,"maxcpu":1,"maxdisk":16106127360,"maxmem":1073741824,"mem":432391782.4,"netin":11070.2933333333,"netout":29.5333333333333,"time":1706344740},{"cpu":0.127307933001489,"disk":0,"diskread":0,"diskwrite":8246.61333333333,"maxcpu":1,"maxdisk":16106127360,"maxmem":1073741824,"mem":432372121.6,"netin":10695.0533333333,"netout":21,"time":1706344800},{"cpu":0.124545909511637,"disk":0,"diskread":0,"diskwrite":3126.61333333333,"maxcpu":1,"maxdisk":16106127360,"maxmem":1073741824,"mem":432392874.666667,"netin":10415.1266666667,"netout":13.0266666666667,"time":1706344860},{"cpu":0.127210656369903,"disk":0,"diskread":0,"diskwrite":4246.18666666667,"maxcpu":1,"maxdisk":16106127360,"maxmem":1073741824,"mem":432387413.333333,"netin":10518.0533333333,"netout":22,"time":1706344920},{"cpu":0.125842717200846,"disk":0,"diskread":0,"diskwrite":3481.6,"maxcpu":1,"maxdisk":16106127360,"maxmem":1073741824,"mem":432383044.266667,"netin":10762.5466666667,"netout":12.16,"time":1706344980},{"cpu":0.128401595234267,"disk":0,"diskread":0,"diskwrite":5939.2,"maxcpu":1,"maxdisk":16106127360,"maxmem":1073741824,"mem":432385228.8,"netin":11247.9966666667,"netout":18.68,"time":1706345040},{"cpu":0.125352078722909,"disk":0,"diskread":0,"diskwrite":4191.57333333333,"maxcpu":1,"maxdisk":16106127360,"maxmem":1073741824,"mem":432388505.6,"netin":11359.26,"netout":22.3133333333333,"time":1706345100},{"cpu":0.12693991896238,"disk":0,"diskread":0,"diskwrite":4355.41333333333,"maxcpu":1,"maxdisk":16106127360,"maxmem":1073741824,"mem":432388505.6,"netin":11301.52,"netout":25.18,"time":1706345160},{"cpu":0.126816451857934,"disk":0,"diskread":0,"diskwrite":5256.53333333333,"maxcpu":1,"maxdisk":16106127360,"maxmem":1073741824,"mem":432386321.066667,"netin":11869.2633333333,"netout":18.84,"time":1706345220},{"cpu":0.126811605527418,"disk":0,"diskread":0,"diskwrite":2594.13333333333,"maxcpu":1,"maxdisk":16106127360,"maxmem":1073741824,"mem":432388505.6,"netin":11374.6933333333,"netout":15.42,"time":1706345280},{"cpu":0.124099103732564,"disk":0,"diskread":0,"diskwrite":0,"maxcpu":1,"maxdisk":16106127360,"maxmem":1073741824,"mem":432398336,"netin":10737.1366666667,"netout":22.3233333333333,"time":1706345340},{"cpu":0.124497920960517,"disk":0,"diskread":0,"diskwrite":286.72,"maxcpu":1,"maxdisk":16106127360,"maxmem":1073741824,"mem":432398336,"netin":10998.5666666667,"netout":20.82,"time":1706345400},{"cpu":0.125006141203898,"disk":0,"diskread":0,"diskwrite":54.6133333333333,"maxcpu":1,"maxdisk":16106127360,"maxmem":1073741824,"mem":432397243.733333,"netin":11047.36,"netout":16.38,"time":1706345460},{"cpu":0.124747998571836,"disk":0,"diskread":0,"diskwrite":0,"maxcpu":1,"maxdisk":16106127360,"maxmem":1073741824,"mem":432392874.666667,"netin":11656.4733333333,"netout":20.14,"time":1706345520}]

Here we have a lot more informations :
cpu, diskread, diskwrite, mem, netin, netout

Would it be possible to add the rest of the data instead of only MaxCPU, MaxMem, Disk and MaxDisk ?

Let me know if i'm missing something.

After checking it seems it have been added in this PR: #87

but it haven't made it's way to main ? I can't seem to have access to the branch "vm-updates".

complete container support

This looks like a really promising library, thank you for sharing it.

Looking over the PVE API and the functionality implemented in the library. I was thinking the following enhancements would be helpful:

  • Implement node.NewContainer()
  • Add ContainerConfig struct
  • Add ContainerConfig field to Container struct
  • Update node.Container() to include container.Config

This shouldn't break the existing API and bring it in line with existing VirtualMachine behavior. It would also complete CRUD functionality for PVE containers.

Invalid memory address or nil pointer dereference on vm.Delete()

Hi!
Function Delete for VM fails with
runtime error: invalid memory address or nil pointer dereference

My code

ctx := context.Background()
// Use vm.Status != "stopped" because vm.IsStopped()/vm.IsRunning() always returns 'false'
if vm.Status != "stopped" {
	task, err := vm.Stop(ctx)
	if err != nil {
		log.Error(err)
		return err
	}
	status, completed, err := task.WaitForCompleteStatus(ctx, 10, 3, 5, 10)
	if err != nil {
		return err
	}
	if !status && !completed {
		return fmt.Errorf("cannot stop vm %v", vmid)
	}
}

task, err := vm.Delete(ctx)
if err != nil {
	log.Error(err)
	return err
}
status, completed, err := task.WaitForCompleteStatus(ctx, 10, 3, 5, 10)
if err != nil {
	return err
}
if !status && !completed {
	return fmt.Errorf("cannot delete vm %v", vmid)
}

vm.Stop works but vm.Delete fails

runtime error: invalid memory address or nil pointer dereference
/usr/lib/go/src/runtime/panic.go:261 (0x450ef7)
        panicmem: panic(memoryError)
/usr/lib/go/src/runtime/signal_unix.go:861 (0x450ec5)
        sigpanic: panicmem()
/home/snels/go/pkg/mod/github.com/luthermonson/[email protected]/virtual_machine.go:54 (0x940e5b)
        (*VirtualMachine).HasTag: if v.VirtualMachineConfig.Tags == "" {
/home/snels/go/pkg/mod/github.com/luthermonson/[email protected]/virtual_machine.go:337 (0x943616)
        (*VirtualMachine).deleteCloudInitISO: if v.HasTag(MakeTag(TagCloudInit)) {
/home/snels/go/pkg/mod/github.com/luthermonson/[email protected]/virtual_machine.go:324 (0x943436)
        (*VirtualMachine).Delete: if ok, err := v.deleteCloudInitISO(ctx); err != nil || !ok {
/home/snels/git/pve-api-gateway/pkg/pve/vm.go:542 (0x952464)
        deleteVM: task, err := vm.Delete(ctx)

Am I doing something wrong or is the problem in the module?

argument issues with qemu Clone/MoveDisk and policy on API backward compatibility

Hi,

I'm having issues using this client implementation of qemu Clone and MoveDisk.

MoveDisk seems focused on moving disks between storage backends and forces the use of the optional storage parameter, whereas I would like to use it to move disks from one VM to another while keeping the same storage backend, for which I need the optional parameters format, target-disk and target-vmid.

Clone has similar issues and forces the usage of the target optional parameter even though it only works with shared storage backends. I'm using local ZFS pools with templates in the local filesystem, and thus needs the full, storage and format optional parameters instead.

I could do a PR implementing all this while keeping the current optional parameters, but as those methods are using hardcoded args, this either means duplicating methods or breaking API compatibility, and I would like to ask for opinions on this subject first.

Cloud-init Fails

After adding the iso the first time, the second run fails:

panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x2 addr=0x8 pc=0x104837bb0]

goroutine 1 [running]:
github.com/luthermonson/go-proxmox.(*Task).Ping(0x0)
/Users/mbenjemaa/workspace/go/pkg/mod/github.com/luthermonson/[email protected]/tasks.go:39 +0x20
github.com/luthermonson/go-proxmox.(*Task).Wait(0x0, 0x3b9aca00, 0x77359400)
/Users/mbenjemaa/workspace/go/pkg/mod/github.com/luthermonson/[email protected]/tasks.go:145 +0x2c
github.com/luthermonson/go-proxmox.(*Task).WaitFor(...)
/Users/mbenjemaa/workspace/go/pkg/mod/github.com/luthermonson/[email protected]/tasks.go:140
github.com/luthermonson/go-proxmox.(*VirtualMachine).CloudInit(0x140001980e0, {0x104844d81, 0x4}, {0x10485df67, 0x1ed}, {0x10485df67, 0x1ed})
/Users/mbenjemaa/workspace/go/pkg/mod/github.com/luthermonson/[email protected]/virtual_machine.go:149 +0x1a8

[test] Cloud-Init Support

Would like to try and offer support for taking a cloud-config and metadata file as string and then auto-generate an iso, upload it and then mount it before booting to get caught in the no-cloud boot options for cloud-init. See code I wrote for the (vsphere machine driver)[https://github.com/rancher/machine/blob/master/drivers/vmwarevsphere/cloudinit.go#L128-L202] and see if we can get full support for cloud-init using this as it would greatly improve the machine driver as well as a terraform module if we decide.

Just note... as per some things we came across with while doing the vsphere driver...

  • cleanup is important, leaving a bunch of isos lying around on the disk is annoying
  • perhaps keeping track on the qemu vm with a note about the cloud-init.iso name and we delete the associated iso when the vm is deleted
  • After boot give you should be able to safely unmount and remove the iso from the proxmox, on boot cloud-init copies everything and stores a local cache on disk so the iso should be able to be safely removed fairly quickly and deleted

Cluster backup scheduler

Hello,

The api endpoint for /cluster/backup seems to be missing, the one in node/vzdump doesn't take schedule argument, am i missing something ?

Thank you.

Convert Old Container Funcs to use UPID/Tasks

The first Container funcs were created before UPID/Tasks were done so it used a ContainerStatus struct, this was changed to a string now but should ultimately be the UPID/Task system with a func profile looking similar to this...

func (c *Container) Start(ctx context.Context) (task *Task, err error)
func (c *Container) Stop(ctx context.Context) (task *Task, err error)
func (c *Container) Suspend(ctx context.Context) (task *Task, err error)
func (c *Container) Reboot(ctx context.Context) (task *Task, err error)
func (c *Container) Resume(ctx context.Context) (task *Task, err error)
func (c *Container) Shutdown(ctx context.Context, force bool, timeout int) (task *Task, err error)

Unmount Cloudinit ISO

As part of capi provider for proxmox.

We need a way of unmounting the Cloud init ISO.

VNC Ticket

Hi Luther,

I had been moving forward using the library :) thanks a lot for it

I have a question regarding the VNC ticket. I can see here

https://github.com/luthermonson/go-proxmox/blob/main/proxmox.go#L196

the function VNCWebSocket receive a vnc argument, which seems to be a struct containing the vnc.Ticket and vnc.User.

Where are the VNC calls in the code? I had been searching but it seems am little bit blind.

I want to use it in order to access noVNC console from a reactjs app.

thanks in advance,

Define iso storage on CloudInit

Hi!
How to define storage for CloudInit function?

I'm trying to use context.WithValue something like

isoStorage, _ := node.StorageISO(context.Background())
ctxISO := context.WithValue(ctx, &isoStorage.Name, "templates")
target.CloudInit(ctxISO, "ide0", vm.CloudInit.UserData, "", "", vm.CloudInit.NetworkData)

but without success.

What am I doing wrong?

VNCProxy doesn't work

Hello! I've been experimenting with VNCProxy and encountered a crash at this specific line in the code: proxmox.go#L328. It appears that this functionality might not have been thoroughly tested, leading me to wonder if it was intended to work at all.

Is it possible that VNCProxy wasn't supposed to work in this context?

Container interfaces commented out

Hello, thanks for making great proxmox-sdk. I see that, containter interfaces function is commented out.

For me running proxmox version 8.1.4, the api path /nodes/%s/lxc/%d/interfaces, works correctly:

curl --location 'https://192.168.1.254:8006/api2/json/nodes/pve1/lxc/700/interfaces' \
--header "Authorization: $API_TOKEN" --insecure
{"data":[{"inet":"127.0.0.1/8","hwaddr":"00:00:00:00:00:00","name":"lo","inet6":"::1/128"},{"inet6":"fe80::be24:11ff:fe89:6707/64","name":"eth0","hwaddr":"bc:24:11:89:67:07","inet":"192.168.3.95/22"}]}

Is there any way of uncommenting this function?

Error: json: cannot unmarshal string into Go struct field VirtualMachineConfig.cpulimit of type int

Shouldn't cpulimit be float32? I have set mine to 0.4 to give my VM a fraction of my CPU Core? It works on proxmox but the go-proxmox API cannot unmarshal it.

[Edit]
In the documentation https://pve.proxmox.com/wiki/Qemu/KVM_Virtual_Machines it says

...
...Resource Limits...
With the cpulimit (“Host CPU Time”) option you can limit how much CPU time the whole VM can use on the host. It is a floating point value representing CPU time in percent, so 1.0 is equal to 100%, 2.5 to 250% and so on.
...

A halted vm causes failure to list vms

Hi,

VirtualMachines returns an error when there is a halted vm in node.
it's pid is null, thus does not pass isFloat pattern check in types.go

I temporarily modified it to return nil, but would be nice to handle this situation.

kudos for your work and providing this api impl

Proxmox component-specific methods are sometimes not ideal

The title of this Issue is probably a little unclear what I mean. But as an example, take the function to request a node's version details:

func (n *Node) Version(ctx context.Context) (version *Version, err error) {

This API method requires me to make a request to Node(ctx, nodeName) and then make the request to get the VE node's version from the Node struct that it returned. So, I'm making 2 API requests to get that version data, when I could do this in 1 API request if the method took a node name string instead.

I see the design decision, but I don't think it's a good assumption that I'm always going to care about all the output from Node(...) when I want the data from Version(...). For example, maybe I just made a request to Nodes(ctx), got my list of nodes (and their names) and now just want to hit the Version method, or maybe I know my node names some other way (I did name them in the first place.)

The Node/Version API method issue is just one example, that design decision with that assumption is seen across many other API methods in this library.

I actually wrote my own library for a PVE prometheus metrics exporter product I work on partially because of this constraint, but it's maybe something to think about here, since your library has more users it services.

Ping() return current state

Hi friends,

I had been trying this module and it is great.

I just have a question regarding the Ping() method. As far as I can see it returns an error if occurred.

But I had in mind that i could be useful(for me) to get the actual current information from the VM. Is there another method similar to ping that can bring the current state with its full body?

I had a look at the endpoint we are sending the request and it has different kind of information I would like to use
https://pve.proxmox.com/pve-docs/api-viewer/#/nodes/{node}/qemu/{vmid}/status/current

or is there a way to get the body of that request?

hope my question is understandable and if you need more info I can provide it

thanks in advance!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.