Giter VIP home page Giter VIP logo

proxmoxer's Introduction

Proxmoxer: A Python wrapper for Proxmox REST API

master branch: master_build_status master_coverage_status pypi_version pypi_downloads

develop branch: develop_build_status develop_coverage_status

Proxmoxer is a python wrapper around the Proxmox REST API v2. It currently supports the Proxmox services of Proxmox Virtual Environment (PVE), Proxmox Mail Gateway (PMG), and Proxmox Backup Server (PBS).

It was inspired by slumber, but it is dedicated only to Proxmox. It allows not only REST API use over HTTPS, but the same api over ssh and pvesh utility.

Like Proxmoxia, it dynamically creates attributes which responds to the attributes you've attempted to reach.

Full Documentation is available at https://proxmoxer.github.io/docs/

Migrating to version 2

Full instructions for the minimal steps needed to update to version 2 can be found in Migration Docs.

Installation

pip install proxmoxer

To use the 'https' backend, install requests

pip install requests

To use the 'ssh_paramiko' backend, install paramiko

pip install paramiko

To use the 'openssh' backend, install openssh_wrapper

pip install openssh_wrapper

Short usage information

The first thing to do is import the proxmoxer library and create ProxmoxAPI instance.

from proxmoxer import ProxmoxAPI

proxmox = ProxmoxAPI(
    "proxmox_host", user="admin@pam", password="secret_word", verify_ssl=False
)

This will connect by default to PVE through the 'https' backend.

Note: ensure you have the required libraries (listed above) for the connection method you are using

Queries are exposed via the access methods get, post, put and delete. For convenience two synonyms are available: create for post, and set for put.

Using the paths from the PVE API v2, you can create API calls using the access methods above.

>>> for node in proxmox.nodes.get():
...     for vm in proxmox.nodes(node["node"]).qemu.get():
...         print(f"{vm['vmid']}. {vm['name']} => {vm['status']}")
...

141. puppet-2.london.example.com => running
101. munki.london.example.com => running
102. redmine.london.example.com => running
140. dns-1.london.example.com => running
126. ns-3.london.example.com => running
113. rabbitmq.london.example.com => running

See Changelog in CHANGELOG.md

proxmoxer's People

Contributors

ananiasfilho avatar b2ag avatar bigjools avatar chrisplo avatar dcasier avatar developername1 avatar domrim avatar gabrielcardoso21 avatar jhollowe avatar jmeridth avatar johnbergvall avatar kristianheljas avatar m-rtijn avatar mihailstoynov avatar morph027 avatar reitermarkus avatar russoz avatar scap1784 avatar scop avatar ssi444 avatar stappersg avatar swayf avatar tiewei avatar timansky avatar trekie86 avatar wdoekes avatar whirm avatar wuillaumea 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

proxmoxer's Issues

KeyError instead of adequate exception on try to delete a running virtual machine.

After update to 1.3.0, when I try to delete a running virtual machine using HTTP bacekend, I get a KeyError exception instead of proxmoxer.core.ResourceException as it was in 1.2.0.

Traceback (most recent call last):
  File "/home/user/.cache/pypoetry/virtualenvs/vm-broker-pzDY6P43-py3.8/lib/python3.8/site-packages/uvicorn/protocols/http/httptools_impl.py", line 390, in run_asgi
    result = await app(self.scope, self.receive, self.send)
  File "/home/user/.cache/pypoetry/virtualenvs/vm-broker-pzDY6P43-py3.8/lib/python3.8/site-packages/uvicorn/middleware/proxy_headers.py", line 45, in __call__
    return await self.app(scope, receive, send)
  File "/home/user/.cache/pypoetry/virtualenvs/vm-broker-pzDY6P43-py3.8/lib/python3.8/site-packages/fastapi/applications.py", line 190, in __call__
    await super().__call__(scope, receive, send)
  File "/home/user/.cache/pypoetry/virtualenvs/vm-broker-pzDY6P43-py3.8/lib/python3.8/site-packages/starlette/applications.py", line 111, in __call__
    await self.middleware_stack(scope, receive, send)
  File "/home/user/.cache/pypoetry/virtualenvs/vm-broker-pzDY6P43-py3.8/lib/python3.8/site-packages/starlette/middleware/errors.py", line 181, in __call__
    raise exc from None
  File "/home/user/.cache/pypoetry/virtualenvs/vm-broker-pzDY6P43-py3.8/lib/python3.8/site-packages/starlette/middleware/errors.py", line 159, in __call__
    await self.app(scope, receive, _send)
  File "/home/user/.cache/pypoetry/virtualenvs/vm-broker-pzDY6P43-py3.8/lib/python3.8/site-packages/starlette/middleware/cors.py", line 86, in __call__
    await self.simple_response(scope, receive, send, request_headers=headers)
  File "/home/user/.cache/pypoetry/virtualenvs/vm-broker-pzDY6P43-py3.8/lib/python3.8/site-packages/starlette/middleware/cors.py", line 142, in simple_response
    await self.app(scope, receive, send)
  File "/home/user/.cache/pypoetry/virtualenvs/vm-broker-pzDY6P43-py3.8/lib/python3.8/site-packages/starlette/exceptions.py", line 82, in __call__
    raise exc from None
  File "/home/user/.cache/pypoetry/virtualenvs/vm-broker-pzDY6P43-py3.8/lib/python3.8/site-packages/starlette/exceptions.py", line 71, in __call__
    await self.app(scope, receive, sender)
  File "/home/user/.cache/pypoetry/virtualenvs/vm-broker-pzDY6P43-py3.8/lib/python3.8/site-packages/starlette/routing.py", line 566, in __call__
    await route.handle(scope, receive, send)
  File "/home/user/.cache/pypoetry/virtualenvs/vm-broker-pzDY6P43-py3.8/lib/python3.8/site-packages/starlette/routing.py", line 227, in handle
    await self.app(scope, receive, send)
  File "/home/user/.cache/pypoetry/virtualenvs/vm-broker-pzDY6P43-py3.8/lib/python3.8/site-packages/starlette/routing.py", line 41, in app
    response = await func(request)
  File "/home/user/.cache/pypoetry/virtualenvs/vm-broker-pzDY6P43-py3.8/lib/python3.8/site-packages/fastapi/routing.py", line 188, in app
    raw_response = await run_endpoint_function(
  File "/home/user/.cache/pypoetry/virtualenvs/vm-broker-pzDY6P43-py3.8/lib/python3.8/site-packages/fastapi/routing.py", line 135, in run_endpoint_function
    return await dependant.call(**values)
  File "/home/user/Projects/bigdata/vm_broker/src/vm_broker/api/v1/vm/views.py", line 227, in delete_vm_view
    await delete_vm(vm_uuid, proxmox, mongo, force_stop)
  File "/home/user/Projects/bigdata/vm_broker/src/vm_broker/api/v1/vm/core.py", line 86, in delete_vm
    px.delete_vm(
  File "/home/user/Projects/bigdata/vm_broker/src/vm_broker/external/proxmox/utils.py", line 86, in delete_vm
    node.qemu(vmid).delete(purge=1)
  File "/home/user/.cache/pypoetry/virtualenvs/vm-broker-pzDY6P43-py3.8/lib/python3.8/site-packages/proxmoxer/core.py", line 152, in delete
    return self(args)._request("DELETE", params=params)
  File "/home/user/.cache/pypoetry/virtualenvs/vm-broker-pzDY6P43-py3.8/lib/python3.8/site-packages/proxmoxer/core.py", line 129, in _request
    errors=(self._store["serializer"].loads_errors(resp) or {}),
  File "/home/user/.cache/pypoetry/virtualenvs/vm-broker-pzDY6P43-py3.8/lib/python3.8/site-packages/proxmoxer/backends/https.py", line 180, in loads_errors
    return json.loads(response.text)["errors"]
KeyError: 'errors'

it occurs here

class JsonSerializer(object):
    content_types = [
        "application/json",
        "application/x-javascript",
        "text/javascript",
        "text/x-javascript",
        "text/x-json",
    ]

    def get_accept_types(self):
        return ", ".join(self.content_types)

    def loads(self, response):
        try:
            return json.loads(response.content.decode("utf-8"))["data"]
        except (UnicodeDecodeError, ValueError):
            return {"errors": response.content}

    def loads_errors(self, response):
        try:
            return json.loads(response.text)["errors"]    #  <======= here
        except (UnicodeDecodeError, ValueError):
            return {"errors": response.content}

because of response.text == '{"data":null}' and there is no "errors" key in response payload.

QEMU exec commands parsed incorrectly on Windows

#90 caused a regression when running Proxmoxer on Windows hosts. shlex is designed for *nix systems, not Windows. As a result, commands that previous worked on <1.3.0 now fail due to improper escaped characters.

The behavior described in this StackOverflow ticket describes the incorrect behavior:
https://stackoverflow.com/questions/19719971/why-do-i-need-4-backslashes-in-a-python-path

Before using shlex the OS should be checked to ensure that it is *nix and not Windows.

token expiration (http backend)

I'm writing a tool which may run for several hours. It seems that the api access token times out at some point.

Do you think proxmoxer should detect that and try to aquire a new api access token by itself?

This would require that proxmoxer would need to keep username and password in memory permanently, while the instance of proxmoxer exists.

"proxmoxer required for this module", yet proxmoxer is installed on Macos

When executing an ansible playbook on Macos Catalina (Apple) I continue to have the fatal error: "fatal: [proxy-test]: FAILED! => {"changed": false, "msg": "proxmoxer required for this module"}

This is not a proxmoxer issue, but some Apple thing I assume.

pip3 show proxmoxer 1.1.1, Location: /usr/local/lib/python3.8/site-packages
ansible 2.9.13 using python version = 3.8.5
Macos: 10.15.7

Initially poxmoxer was installed in python3.7/site-packages. Removing and reinstalling proxmoxer wiht pip3 fixed that and it is now in python3.8/site-packages. Yet the behaviour remains the same. I can run the same playbook normally when I "ssh -A" into a debian10 VM running on the same Apple laptop.

What extra debug info can I enable to find the reason for the error? Is someone familiar with the same behaviour on an Apple and was that fixed?

Max

Dot-Notation issue on /nodes/{node}/qemu/{vmid}/firewall/ipset/{name}/{cidr}

When trying to access the API-Path /nodes/{node}/qemu/{vmid}/firewall/ipset/{name}/{cidr} in Dot-Notation it seems impossible to execute it as it doesn't have a "verb" before the CIDR-Address in this case.

I would expect the following to work:
proxmoxer.nodes(node_name).qemu(vm_id).firewall.ipset(ipset_name,cidr_address).delete()

However Dot-Notation building can be worked-around when using getattr to dynamically create the CIDR part of the API address:
getattr(proxmoxer.nodes(node_name).qemu(vm_id).firewall.ipset(ipset_name,cidr_address).delete()

Please support a recent version of requests

I see in test_requirements.txt a dependency on requests < 2.9, which has been released in 2015.

From what I understand, this is just a problem with tests (specifically with tests.https_tests.test_pbs_https_connection), and proxmoxer runs correctly with more recent versions of requests, right?

However, it would be nice if that dependency could be changed to a version of requests from this decade.

Thanks

PBS Support

Is anyone working on PBS support already?

Uploading large files causes OverflowError

Hello,

I was trying to upload an ISO file (large one, larger than 5 GBs) and following the example from the documentation, I got an error:

storage.upload.create(content='iso', filename=open(iso_path, 'rb'))
...
OverflowError: string longer than 2147483647 bytes

By following the stack trace, I realized that the wrong argument type is being used in the create/POST call.
When filename argument is being used, proxmoxer https backend transforms it into a files parameter for requests (basically, a dictionary):

> /tmp/env/lib/python3.9/site-packages/proxmoxer/backends/https.py(181)request()
-> return super(ProxmoxHttpSession, self).request(method, url, params, data, headers, cookies, files, auth,
(Pdb) url
'https://prox:8006/api2/json/nodes/prox/storage/local/upload'
(Pdb) method
'POST'
(Pdb) data
{'content': 'iso'}
(Pdb) files
{'filename': <_io.BufferedReader name='/path/to/iso/example.iso'>}

Since the requests' module parameter should be file and not filename, the following call succeeds:

storage.upload.create(content='iso', file=open(iso_path, 'rb'))

I suggest you test this and update the documentation if this is really the case in general, or I'm having some weird quirks:)

Also, download-url method does not work, it simply isn't parsed properly and it's dynamic generation fails.

incompatible ssh peer in asa_command module in Ansible 2.9

Hi,

Need assistance regarding error on ssh. Incompatible ssh peer (no acceptable kex algorithm).

Appreciate your response. Thank you.

Details:
The full traceback is:
Traceback (most recent call last):
File "/.ansible/tmp/ansible-local-/ansible-tmp-1584690763.67-219997475427451/AnsiballZ_asa_command.py", line 102, in
_ansiballz_main()
File "/.ansible/tmp/ansible-local-/ansible-tmp-1584690763.67-219997475427451/AnsiballZ_asa_command.py", line 94, in ansiba llz_main
invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)
File "/.ansible/tmp/ansible-local-/ansible-tmp-1584690763.67-219997475427451/AnsiballZ_asa_command.py", line 40, in invoke
module
runpy.run_module(mod_name='ansible.modules.network.asa.asa_command', init_globals=None, run_name='main', alter_sys=True)
File "/usr/lib64/python2.7/runpy.py", line 176, in run_module
fname, loader, pkg_name)
File "/usr/lib64/python2.7/runpy.py", line 82, in _run_module_code
mod_name, mod_fname, mod_loader, pkg_name)
File "/usr/lib64/python2.7/runpy.py", line 72, in _run_code
exec code in run_globals
File "/tmp/ansible_asa_command_payload_K0V1WV/ansible_asa_command_payload.zip/ansible/modules/network/asa/asa_command.py", line 186, in
File "/tmp/ansible_asa_command_payload_K0V1WV/ansible_asa_command_payload.zip/ansible/modules/network/asa/asa_command.py", line 156, in mai n
File "/tmp/ansible_asa_command_payload_K0V1WV/ansible_asa_command_payload.zip/ansible/module_utils/network/asa/asa.py", line 125, in run_co mmands
File "/tmp/ansible_asa_command_payload_K0V1WV/ansible_asa_command_payload.zip/ansible/module_utils/connection.py", line 185, in rpc
ansible.module_utils.connection.ConnectionError: Incompatible ssh peer (no acceptable kex algorithm)

fatal: [ios01]: FAILED! => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"module_stderr": "Traceback (most recent call last):\n File "/.ansible/tmp/ansible-local-/ansible-tmp-1584690763.67-219 997475427451/AnsiballZ_asa_command.py", line 102, in \n _ansiballz_main()\n File "/.ansible/tmp/ansible-local-/ ansible-tmp-1584690763.67-219997475427451/AnsiballZ_asa_command.py", line 94, in _ansiballz_main\n invoke_module(zipped_mod, temp_path, A NSIBALLZ_PARAMS)\n File "/.ansible/tmp/ansible-local-/ansible-tmp-1584690763.67-219997475427451/AnsiballZ_asa_command.py", line 40, in invoke_module\n runpy.run_module(mod_name='ansible.modules.network.asa.asa_command', init_globals=None, run_name='main', alter_sys=True)\n File "/usr/lib64/python2.7/runpy.py", line 176, in run_module\n fname, loader, pkg_name)\n File "/usr/lib64/python2 .7/runpy.py", line 82, in _run_module_code\n mod_name, mod_fname, mod_loader, pkg_name)\n File "/usr/lib64/python2.7/runpy.py", line 7 2, in _run_code\n exec code in run_globals\n File "/tmp/ansible_asa_command_payload_K0V1WV/ansible_asa_command_payload.zip/ansible/modul es/network/asa/asa_command.py", line 186, in \n File "/tmp/ansible_asa_command_payload_K0V1WV/ansible_asa_command_payload.zip/ansi ble/modules/network/asa/asa_command.py", line 156, in main\n File "/tmp/ansible_asa_command_payload_K0V1WV/ansible_asa_command_payload.zip /ansible/module_utils/network/asa/asa.py", line 125, in run_commands\n File "/tmp/ansible_asa_command_payload_K0V1WV/ansible_asa_command_p ayload.zip/ansible/module_utils/connection.py", line 185, in rpc\nansible.module_utils.connection.ConnectionError: Incompatible ssh peer (no acceptable kex algorithm)\n",
"module_stdout": "",
"msg": "MODULE FAILURE\nSee stdout/stderr for the exact error",
"rc": 1
}

Maintainers welcome

As the upstream repo https://github.com/swayf/proxmoxer/ already got abandoned leaving multiple pull requests open, i've came up with the proxmoxer organization to take care. To prevent the same happen to this repo, i'd like to invite more maintainers to this wonderful project, just drop me a message, mail, or an issue comment here.

Create a style guide and editorconfig file

Create a standard for how the code should be formatted. This includes at least a basic style guide for things that can't be linted and fixed, as well as an editorconfig file for everyone to follow and possibly set up an automatic linter.

Authentication against new user api token feature

Hi there!

Seems proxmox now supports user api tokens instead of using passwords starting with libpve-access-control 6.0-6. The biggest benefit to me is the fact that you can have different permissions for tokens than users but also that when I'm deving in my own environment I don't have to store my password or create different users with different permissions.

Is this something that you are looking into adding as an alternative auth feature? If not would be a lot of work to implement?

Thanks!

SSH backend broken ?

Hello,

Trying to use the this library I wasn't able to use it with SSH backup (openssh and ssh_paramiko). With HTTP it work.

This is my log:

Python 3.7.3 (default, Dec 20 2019, 18:57:59) 
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from proxmoxer import ProxmoxAPI
>>> proxmox = ProxmoxAPI('localhost', user='root', backend='ssh_paramiko')
2020-05-15 17:57:06,109 DEBUG:paramiko.transport: starting thread (client mode): 0xeb21de80
2020-05-15 17:57:06,117 DEBUG:paramiko.transport: Local version/idstring: SSH-2.0-paramiko_2.7.1
2020-05-15 17:57:06,117 DEBUG:paramiko.transport: Remote version/idstring: SSH-2.0-OpenSSH_7.9p1 Debian-10+deb10u2
2020-05-15 17:57:06,118 INFO:paramiko.transport: Connected (version 2.0, client OpenSSH_7.9p1)
2020-05-15 17:57:06,120 DEBUG:paramiko.transport: kex algos:['curve25519-sha256', '[email protected]', 'ecdh-sha2-nistp256', 'ecdh-sha2-nistp384', 'ecdh-sha2-nistp521', 'diffie-hellman-group-exchange-sha256', 'diffie-hellman-group16-sha512', 'diffie-hellman-group18-sha512', 'diffie-hellman-group14-sha256', 'diffie-hellman-group14-sha1'] server key:['rsa-sha2-512', 'rsa-sha2-256', 'ssh-rsa', 'ecdsa-sha2-nistp256', 'ssh-ed25519'] client encrypt:['[email protected]', 'aes128-ctr', 'aes192-ctr', 'aes256-ctr', '[email protected]', '[email protected]'] server encrypt:['[email protected]', 'aes128-ctr', 'aes192-ctr', 'aes256-ctr', '[email protected]', '[email protected]'] client mac:['[email protected]', '[email protected]', '[email protected]', '[email protected]', '[email protected]', '[email protected]', '[email protected]', 'hmac-sha2-256', 'hmac-sha2-512', 'hmac-sha1'] server mac:['[email protected]', '[email protected]', '[email protected]', '[email protected]', '[email protected]', '[email protected]', '[email protected]', 'hmac-sha2-256', 'hmac-sha2-512', 'hmac-sha1'] client compress:['none', '[email protected]'] server compress:['none', '[email protected]'] client lang:[''] server lang:[''] kex follows?False
2020-05-15 17:57:06,120 DEBUG:paramiko.transport: Kex agreed: [email protected]
2020-05-15 17:57:06,121 DEBUG:paramiko.transport: HostKey agreed: ssh-ed25519
2020-05-15 17:57:06,121 DEBUG:paramiko.transport: Cipher agreed: aes128-ctr
2020-05-15 17:57:06,121 DEBUG:paramiko.transport: MAC agreed: hmac-sha2-256
2020-05-15 17:57:06,121 DEBUG:paramiko.transport: Compression agreed: none
2020-05-15 17:57:06,129 DEBUG:paramiko.transport: kex engine KexCurve25519 specified hash_algo <built-in function openssl_sha256>
2020-05-15 17:57:06,129 DEBUG:paramiko.transport: Switch to new keys ...
2020-05-15 17:57:06,130 DEBUG:paramiko.transport: Adding ssh-ed25519 host key for localhost: b'f55d10f823755bf3a72735031f8b383e'
2020-05-15 17:57:06,132 DEBUG:paramiko.transport: Trying discovered key b'f1112b5151b104a18ed3abe4f7556e0d' in /root/.ssh/id_rsa
2020-05-15 17:57:06,133 DEBUG:paramiko.transport: userauth is OK
2020-05-15 17:57:06,149 INFO:paramiko.transport: Authentication (publickey) successful!
>>> 2020-05-15 17:57:06,179 DEBUG:paramiko.transport: Received global request "[email protected]"
2020-05-15 17:57:06,180 DEBUG:paramiko.transport: Rejecting "[email protected]" global request from server.
2020-05-15 17:57:06,184 DEBUG:paramiko.transport: Debug msg: b'/root/.ssh/authorized_keys:3: key options: agent-forwarding port-forwarding pty user-rc x11-forwarding'

>>> proxmox.version.get()
2020-05-15 17:57:18,697 INFO:proxmoxer.core: GET /version
2020-05-15 17:57:18,697 DEBUG:paramiko.transport: [chan 0] Max packet in: 32768 bytes
2020-05-15 17:57:18,698 DEBUG:paramiko.transport: [chan 0] Max packet out: 32768 bytes
2020-05-15 17:57:18,698 DEBUG:paramiko.transport: Secsh channel 0 opened.
2020-05-15 17:57:18,700 DEBUG:paramiko.transport: [chan 0] Sesch channel 0 request ok
2020-05-15 17:57:19,820 DEBUG:paramiko.transport: [chan 0] EOF received (0)
2020-05-15 17:57:19,821 DEBUG:proxmoxer.core: Status code: 500, output: {"keyboard":"fr-ch","release":"6.2","repoid":"9824574a","version":"6.2-4"}

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/tmp/venv/lib/python3.7/site-packages/proxmoxer/core.py", line 106, in get
    return self(args)._request("GET", params=params)
  File "/tmp/venv/lib/python3.7/site-packages/proxmoxer/core.py", line 101, in _request
    resp.content))
proxmoxer.core.ResourceException: 500 Internal Server Error: {"keyboard":"fr-ch","release":"6.2","repoid":"9824574a","version":"6.2-4"}

>>> 2020-05-15 17:57:19,825 DEBUG:paramiko.transport: [chan 0] EOF sent (0)

Trying to understand where is the issue I saw these lines:

stdout, stderr = self._exec(full_cmd)
match = lambda s: re.match('\d\d\d [a-zA-Z]', s)
# sometimes contains extra text like 'trying to acquire lock...OK'
status_code = next(
(int(s.split()[0]) for s in stderr.splitlines() if match(s)),
500)

As I understand we should get by stderr an error code. But In my case the stderr variable is completely empty so we don't get the value.

Note that I'm on proxmox 6.2, maybe there was some change in the API.

Add support for local

Currently you are required to access a node "remotely" through its name. But if for some reason you want to run locally and do not want to use any type of authentication, this falls flat.

I would recommend to add a service for local, where it will do exactly like ssh, but using Popen instead for local access.

Synchronous requests connection pool warnings (Home Assistant)

If more then 10 vms/containers are polled concurrently, a warning occurs. This doesn't normally happen, but the current way the Home Assistant integration works is by queueing up multiple requests all at the same time.

Here is an example of the logs if a single node has 11+ vms/containers added to it in Home Assistant.

2022-06-13 02:11:39 WARNING (SyncWorker_4) [urllib3.connectionpool] Connection pool is full, discarding connection: 192.168.0.49. Connection pool size: 10
2022-06-13 02:12:39 WARNING (SyncWorker_5) [urllib3.connectionpool] Connection pool is full, discarding connection: 192.168.0.49. Connection pool size: 10
2022-06-13 02:13:39 WARNING (SyncWorker_8) [urllib3.connectionpool] Connection pool is full, discarding connection: 192.168.0.49. Connection pool size: 10

This has been reported here: home-assistant/core#68487

According to this stack overflow post, no data is actually being lost though, so I think the warning can be disabled without any worry.

Another solution would be to increase the pool size, but this issue will just come up again when somebody with even more vms/containers breaks the limit again.

I'm not sure how to go about either solutions for this project though. Is this something that can be fixed in this library?

PUT do not… put the data in the body

I am trying to PUT some configuration using Proxmox API using:

instance.config.put({'cores': 6})

I'm getting this:

  File "/nix/store/s4lhij5bix5zcjgcl1x227mc64n7jwav-python3-3.9.9-env/lib/python3.9/site-packages/proxmoxer/core.py", line 129, in put
    return self(args)._request("PUT", data=data)
  File "/nix/store/s4lhij5bix5zcjgcl1x227mc64n7jwav-python3-3.9.9-env/lib/python3.9/site-packages/proxmoxer/core.py", line 105, in _request
    raise ResourceException(
proxmoxer.core.ResourceException: 501 Not Implemented: Method 'PUT /nodes/askeladd/qemu/401/config/{'cores': 6, 'digest': 'fe5571b2e1aa65b2d6078c1ae9b8302d7e7b98db'}' not implemented

I assume this is due to https://stackoverflow.com/questions/11832639/how-to-specify-python-requests-http-put-body which tries to put the data as a query string, it might be fixed by using json= instead of data= for PUT requests.

Include Proxmox Mail Gateway (PMG) Support

Hello, is possible to include a parameter to define if you will use PVE or PMG?

To proxmoxer lib work with proxmox mail gateway i just changed line bellow:
https://github.com/proxmoxer/proxmoxer/blob/develop/proxmoxer/backends/https.py#L83
return cookiejar_from_dict({"PVE"AuthCookie: self.pve_auth_ticket})
TO
return cookiejar_from_dict({"PMG"AuthCookie: self.pve_auth_ticket})

and call my pmg api using same resources/requests as:

Example: All users statistics - /api2/json/statistics/sender
Reference: https://pmg.proxmox.com/pmg-docs/api-viewer/index.html#/statistics/sender

#!/usr/bin/python3
from proxmoxer import ProxmoxAPI
import json
proxmox = ProxmoxAPI('pmg.mydomain.com', user='root@pam',
                     password='my_password', verify_ssl=False)

a = proxmox.statistics.sender.get()
c = json_formatted_str = json.dumps(a, indent=2)
print(c)

So we can define host, user,password and service.
Services are: PVE, PMG and in future PBS - Proxmox Backup Server.

method unclear to delete/add settings on lxc

Hi,

I'm a bit lost on how to approach something somewhat simple using pct set/delete via CLI

My main goal being moving an interface from one container to another, first step being the deletion of the said interface on the initial container...

I just don't see what method to use if any exists

Thanks for your help,

JaXX./.

Error 500 with proxmox 7 - JSON response into exception

With proxmox 7 my previous working code on proxmox 6 doesn't work anymore.

Problem is also present with python3

Distribution is Debian 11 ( proxmox 7 : pve-manager/7.1-10/6ddebafe (running kernel: 5.13.19-3-pve) )
Proxmoxer 1.2.0 release

 for node in proxmox.nodes.get():
  File "XXXX/venv-python2.7/lib/python2.7/site-packages/proxmoxer/core.py", line 123, in get
    return self(args)._request("GET", params=params)
  File "XXXX//venv-python2.7/lib/python2.7/site-packages/proxmoxer/core.py", line 117, in _request
    resp.text
proxmoxer.core.ResourceException: 500 Internal Server Error: [{"cpu":0.152678048010119,"disk":340515770368,"id":" ...... 
 .."type":"node","uptime":518181}]

Json Response seems to be good but printed as Exception.

What's the problem with Proxmox 7 ?

PyPI package

As we can clearly see, the upstream of this fork is no longer maintained.
Hovewer, there is still not PyPI package of this repo on pypi.org for easy incorporation of new PRs.

I would suggest:

  1. Clearly stating in this repo, that the upstrem is obsolete
  2. Introducing new package to pypi.org and, same stating there, that upstream is deprecated and should not be used.

Proxmoxer syntax is broken with Proxmox API v7.0

According to the proxmoxer documentation the following forms are equivalent:

proxmox.nodes(node['node']).openvz.get()
proxmox.nodes(node['node']).get('openvz')
proxmox.get('nodes/%s/openvz' % node['node'])
proxmox.get('nodes', node['node'], 'openvz')

From what I can tell from the Proxmox v7.0 API documentation, openvz was replaced by qemu.
Applying the same syntax patterns but replacing openvz with qemu, proxmoxer only partially functions:

>>> node_id = proxmox.nodes.get()[0]["node"]
>>> node_id
'n1-cls1'
>>> proxmox.nodes(node_id).qemu.get()
[{'maxmem': 2147483648, 'vmid': 100, 'netout': 0, 'uptime': 0, 'template': 1, 'cpu': 0, 'diskread': 0, 'name': 'vm1', 'cpus': 1, 'netin': 0, 'maxdisk': 10737418240, 'diskwrite': 0, 'status': 'stopped', 'mem': 0, 'disk': 0}, {'cpus': 1, 'name': 'vm2', 'diskread': 0, 'maxmem': 2147483648, 'vmid': 102, 'uptime': 0, 'cpu': 0, 'netout': 0, 'mem': 0, 'status': 'stopped', 'disk': 0, 'diskwrite': 0, 'maxdisk': 10737418240, 'netin': 0}, {'maxdisk': 10737418240, 'diskwrite': 0, 'netin': 0, 'disk': 0, 'status': 'stopped', 'mem': 0, 'netout': 0, 'uptime': 0, 'cpu': 0, 'vmid': 104, 'maxmem': 2147483648, 'name': 'vm3', 'diskread': 0, 'cpus': 1}, {'disk': 0, 'mem': 0, 'status': 'stopped', 'maxdisk': 10737418240, 'diskwrite': 0, 'netin': 0, 'cpus': 1, 'name': 'vm4', 'diskread': 0, 'uptime': 0, 'cpu': 0, 'netout': 0, 'vmid': 101, 'maxmem': 2147483648}, {'disk': 0, 'status': 'stopped', 'mem': 0, 'netin': 0, 'maxdisk': 10737418240, 'diskwrite': 0, 'diskread': 0, 'name': 'vm5', 'cpus': 1, 'netout': 0, 'cpu': 0, 'uptime': 0, 'vmid': 103, 'maxmem': 2147483648}]
>>> proxmox.nodes(node_id).get('qemu')
[{'uptime': 0, 'template': 1, 'cpu': 0, 'netout': 0, 'vmid': 100, 'maxmem': 2147483648, 'cpus': 1, 'name': 'vm1', 'diskread': 0, 'maxdisk': 10737418240, 'diskwrite': 0, 'netin': 0, 'disk': 0, 'mem': 0, 'status': 'stopped'}, {'maxdisk': 10737418240, 'diskwrite': 0, 'netin': 0, 'status': 'stopped', 'mem': 0, 'disk': 0, 'vmid': 102, 'maxmem': 2147483648, 'netout': 0, 'cpu': 0, 'uptime': 0, 'name': 'vm2', 'diskread': 0, 'cpus': 1}, {'cpus': 1, 'name': 'vm3', 'diskread': 0, 'maxmem': 2147483648, 'vmid': 104, 'cpu': 0, 'uptime': 0, 'netout': 0, 'mem': 0, 'status': 'stopped', 'disk': 0, 'diskwrite': 0, 'maxdisk': 10737418240, 'netin': 0}, {'cpu': 0, 'uptime': 0, 'netout': 0, 'maxmem': 2147483648, 'vmid': 103, 'cpus': 1, 'name': 'vm4', 'diskread': 0, 'diskwrite': 0, 'maxdisk': 10737418240, 'netin': 0, 'disk': 0, 'mem': 0, 'status': 'stopped'}, {'netout': 0, 'uptime': 0, 'cpu': 0, 'maxmem': 2147483648, 'vmid': 101, 'name': 'vm5', 'diskread': 0, 'cpus': 1, 'diskwrite': 0, 'maxdisk': 10737418240, 'netin': 0, 'disk': 0, 'status': 'stopped', 'mem': 0}]
>>> proxmox.get('nodes/%s/qemu' % node_id)
<proxmoxer.core.ProxmoxResource object at 0x7fef2e04cf50>
>>> proxmox.get('nodes', node_id, 'qemu')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: __call__() takes from 1 to 2 positional arguments but 4 were given

My use case: Automatically generate code snippets based on the API documentation. The API documentation provides the http verb and path to call which translates perfectly to proxmoxer's path string syntax, which leads to the problem raised in this issue.

Should the path syntax function or has it been deprecated/removed on purpose?

need help for vm clone

hello people,

I am currently trying to clone vms using python.
I always have a standard template from which new vms are cloned.

my code looks like this

def create_vm(message,proxmox):
    node_name = "server1"
    source_id= 111
    target_id = get_next_id(proxmox)
    vm_name= test
    node = proxmox.nodes(node_name)
    node.qemu.source_id.clone.post(name=vm_name,
        full=1,
        newid=target_id
        )

proxmoxer.core.ResourceException: 400 Bad Request: Parameter verification failed. - b'{"errors":{"vmid":"type check (\'integer\') failed - got \'source_id\'"},"data":null}'

with a variable in the path unfortunately does not work, but vmid as parameter does not work either

node.qemu.clone.post(vmid=source_id, name=vm_name ......

proxmoxer.core.ResourceException: 501 Not Implemented: Method 'POST /nodes/kronos/qemu/clone' not implemented - b'{"data":null}'

proxmox docu
https://pve.proxmox.com/pve-docs/api-viewer/index.html#/nodes/{node}/qemu/{vmid}/clone

thanks for the help

SSL error when using API Token authentication

I get the following errors when trying to use API Token authentication. The token is generated as root without privilege separation. The same error shows when using password authentication and ssl_verify=True, but not when False. The SSL cert is Proxmox default.

Running Python 3.9.5
proxmoxer 1.1.1
requests 2.26.0
requests-toolbelt 0.9.1
paramiko 2.7.2

The code I run:

from proxmoxer import ProxmoxAPI

host = '10.10.3.2'
proxmox = ProxmoxAPI(host, 
		user='root', 
		token_name='testtoken', 
		token_value='a2f1e4f6-5936-4eee-b6a2-851e67b97b0c')

print(proxmox.nodes.get())

The error:


Traceback (most recent call last):
  File "C:\Users\Logan\AppData\Roaming\Python\Python39\site-packages\urllib3\connectionpool.py", line 699, in urlopen
    httplib_response = self._make_request(
  File "C:\Users\Logan\AppData\Roaming\Python\Python39\site-packages\urllib3\connectionpool.py", line 382, in _make_request
    self._validate_conn(conn)
  File "C:\Users\Logan\AppData\Roaming\Python\Python39\site-packages\urllib3\connectionpool.py", line 1010, in _validate_conn
    conn.connect()
  File "C:\Users\Logan\AppData\Roaming\Python\Python39\site-packages\urllib3\connection.py", line 411, in connect
    self.sock = ssl_wrap_socket(
  File "C:\Users\Logan\AppData\Roaming\Python\Python39\site-packages\urllib3\util\ssl_.py", line 432, in ssl_wrap_socket
    ssl_sock = _ssl_wrap_socket_impl(sock, context, tls_in_tls)
  File "C:\Users\Logan\AppData\Roaming\Python\Python39\site-packages\urllib3\util\ssl_.py", line 474, in _ssl_wrap_socket_impl
    return ssl_context.wrap_socket(sock)
  File "C:\Program Files\Python39\lib\ssl.py", line 500, in wrap_socket
    return self.sslsocket_class._create(
  File "C:\Program Files\Python39\lib\ssl.py", line 1040, in _create
    self.do_handshake()
  File "C:\Program Files\Python39\lib\ssl.py", line 1309, in do_handshake
    self._sslobj.do_handshake()
ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1129)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\Logan\AppData\Roaming\Python\Python39\site-packages\requests\adapters.py", line 439, in send
    resp = conn.urlopen(
  File "C:\Users\Logan\AppData\Roaming\Python\Python39\site-packages\urllib3\connectionpool.py", line 755, in urlopen
    retries = retries.increment(
  File "C:\Users\Logan\AppData\Roaming\Python\Python39\site-packages\urllib3\util\retry.py", line 574, in increment
    raise MaxRetryError(_pool, url, error or ResponseError(cause))
urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='10.10.3.2', port=8006): Max retries exceeded with url: /api2/json/nodes (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1129)')))

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\Logan\Nextcloud\Arbete\Code\Proxmox\proxmox_talk.py", line 21, in <module>
    nodes = proxmox.nodes.get()
  File "C:\Users\Logan\AppData\Roaming\Python\Python39\site-packages\proxmoxer\core.py", line 105, in get
    return self(args)._request("GET", params=params)
  File "C:\Users\Logan\AppData\Roaming\Python\Python39\site-packages\proxmoxer\core.py", line 85, in _request
    resp = self._store["session"].request(method, url, data=data or None, params=params)
  File "C:\Users\Logan\AppData\Roaming\Python\Python39\site-packages\proxmoxer\backends\https.py", line 178, in request
    return super(ProxmoxHttpSession, self).request(method, url, params, data, headers, cookies, files, auth,
  File "C:\Users\Logan\AppData\Roaming\Python\Python39\site-packages\requests\sessions.py", line 542, in request
    resp = self.send(prep, **send_kwargs)
  File "C:\Users\Logan\AppData\Roaming\Python\Python39\site-packages\requests\sessions.py", line 655, in send
    r = adapter.send(request, **kwargs)
  File "C:\Users\Logan\AppData\Roaming\Python\Python39\site-packages\requests\adapters.py", line 514, in send
    raise SSLError(e, request=request)
requests.exceptions.SSLError: HTTPSConnectionPool(host='10.10.3.2', port=8006): Max retries exceeded with url: /api2/json/nodes (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1129)')))
[Finished in 208ms]

proxmox.get(item) not working?

I get errors with this code:

from proxmoxer import ProxmoxAPI

proxmox=ProxmoxAPI('proxmox.myhost.net', user='user@pve', password='secret', verify_ssl=False)

vms = []
containers = []

for node in proxmox.get("nodes"):

            for virtman in proxmox.get(f"nodes/{node}/qemu"):
                vms.append(virtman["vmid"])

            for cont in proxmox.get(f"nodes/{node}/lxc"):
                containers.append(cont["vmid"])

The error in question is on the outermost for loop and is

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'ProxmoxResource' object is not iterable

I'm using Proxmox 6.3-6 and Python 3.9

Using proxmox.nodes.get() insted works correctly, but I would like to use proxmox.get("nodes")

Am I doing something wrong?

is there anyway to whit 1 method , start or stop lxc and qemu?

Hello i have this 2 methods

proxmox.nodes(env("PROX_NODE")).lxc(vmid).status.post(action)

and

proxmox.nodes(env("PROX_NODE")).qemu(vmid).status.post(action)

is there anyway i can do 2 methods in one?

like

def method(vmid,type)

proxmox.nodes(env("PROX_NODE")).$type(vmid).status.post(action)

or somethin

Uploading isos with api key not possible

I am not sure if this is an issue of proxmoxer or the API itself, but when i try to upload an iso with the following code:

from proxmoxer import ProxmoxAPI

def upload_iso(proxmox_api, iso_path, node: str, storage: str):
    local_storage = proxmox_api.nodes(node).storage(storage)
    iso_file = open(iso_path, 'rb')
    local_storage.upload.create(content='iso', filename=iso_file)

token_value = "xxx"
proxmox_api = ProxmoxAPI("xx.xx.xx.xx:xx", user="token_user@pve",
                                       token_name="token_name", token_value=token_value, verify_ssl=False)
upload_iso(proxmox_api, "/tmp/test.iso", "proxmox", "local")

I get the Exception:

Traceback (most recent call last):
  File "/home/user/proxmox/bug.py", line 23, in <module>
    upload_iso(proxmox, "/tmp/test.iso", "proxmox", "local")
  File  "/home/user/proxmox/bug.py", line 7, in upload_iso
    local_storage.upload.create(content='iso', filename=iso_file)
  File "/usr/lib/python3.9/site-packages/proxmoxer/core.py", line 117, in create
    return self.post(*args, **data)
  File "/usr/lib/python3.9/site-packages/proxmoxer/core.py", line 108, in post
    return self(args)._request("POST", data=data)
  File "/usr/lib/python3.9/site-packages/proxmoxer/core.py", line 90, in _request
    raise ResourceException("{0} {1}: {2} - {3}".format(
proxmoxer.core.ResourceException: 501 Not Implemented: for data too large - b''

When i pass upload_iso an ProxmoxAPI instance, which was created using a "normal" user, uploading the iso works just fine.
The iso itself is only a few Kbytes big and the permissions of the api token are the same as the permissions from the user.
Doing other actions, for example listing the content of a storage, are also no problem with the API Key.

When using backend openssh agent.exec.post(command="ls") works, "ls -l" says TypeError: cannot use a string pattern on a bytes-like object

Hi,

When connecting to a server with openssh backend I can exec a command "ls" via the agent successfully:

proxmox.nodes("r640c").qemu("149").agent.exec.post(command="ls")
{'pid': 28016}
proxmox.nodes("r640c").qemu("149").agent("exec-status").get(pid=28016)
{'exitcode': 0, 'exited': 1, 'out-data': '...n'}

But when I try "ls -l" I get TypeError: cannot use a string pattern on a bytes-like object :

proxmox.nodes("r640c").qemu("149").agent.exec.post(command="ls -l")
Traceback (most recent call last):
File "", line 1, in
File "/home/lguerby/.local/lib/python3.7/site-packages/proxmoxer/core.py", line 126, in post
return self(args)._request("POST", data=data)
File "/home/lguerby/.local/lib/python3.7/site-packages/proxmoxer/core.py", line 100, in _request
resp = self._store["session"].request(method, url, data=data or None, params=params)
File "/home/lguerby/.local/lib/python3.7/site-packages/proxmoxer/backends/base_ssh.py", line 60, in request
500)
File "/home/lguerby/.local/lib/python3.7/site-packages/proxmoxer/backends/base_ssh.py", line 59, in
(int(s.split()[0]) for s in stderr.splitlines() if match(s)),
File "/home/lguerby/.local/lib/python3.7/site-packages/proxmoxer/backends/base_ssh.py", line 55, in match
def match(s): return re.match(r'\d\d\d [a-zA-Z]', s)
File "/usr/lib/python3.7/re.py", line 173, in match
return _compile(pattern, flags).match(string)
TypeError: cannot use a string pattern on a bytes-like object

When I use the https backend both "ls" and "ls -l" work. I suspect an issue with space handling/quoting or may be I missed something for post command=.

Thanks for proxmoxer!

Python3 export pve-cluster info 400 Bad Request

I wrote a python script to export the pve cluster cluster information, but this script can be exported before, but now it can’t be executed, please help me take a look?I did not find any exceptions in this sentence, because this script is in another version with the same pve It can be executed under the cluster. Please help, thanks.

python3 list-pool.py


Traceback (most recent call last):
  File "list-pool-prd.py", line 58, in 
    conf = proxmox.nodes(node['node']).qemu(vm['vmid']).config.get()
  File "/usr/local/lib/python3.5/dist-packages/proxmoxer/core.py", line 123, in get
    return self(args)._request("GET", params=params)
  File "/usr/local/lib/python3.5/dist-packages/proxmoxer/core.py", line 110, in _request
    (self._store["serializer"].loads(resp) or {}).get('errors')
proxmoxer.core.ResourceException: 400 Bad Request: Result verification failed

image


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from proxmoxer import ProxmoxAPI
import re
import xlsxwriter
import pandas as pd

workbook = xlsxwriter.Workbook('pve.xlsx')
worksheet = workbook.add_worksheet(u'pve')
head_format = workbook.add_format()
head_format.set_border(1)
head_format.set_bg_color('silver')
head_format.set_bold()
headings = ('NODE','VMID','VMNAME','POOL','STATUS','IP','DESCRIPTION')
worksheet.write_row(0, 0, headings, head_format)
row = 1
rowdata = []

proxmox = ProxmoxAPI('127.0.0.1', user='root@pam', password='XXX', verify_ssl=False)

pooldict = {}
for pool in proxmox.pools.get():
  p = proxmox.pools(pool['poolid']).get()
  memberlist = p.get("members")
  for item in memberlist:
    id = item.get("id")
    if id.startswith("lxc"):
      pooldict[id[4:]] = pool['poolid']
    if id.startswith("qemu"):
      pooldict[id[5:]] = pool['poolid']

patt = re.compile(r'ip=.*/\d+')
for node in proxmox.nodes.get():
  for vm in proxmox.nodes(node['node']).lxc.get():
    conf = proxmox.nodes(node['node']).lxc(vm['vmid']).config.get()
    des = conf.get("description")
    des = des.strip().replace('\n', ' ').replace('\r', ' ') if des is not None else "/"
    ip = "/"
    net = conf.get("net0")
    if net is not None:
      m = re.search(patt, net)
      ip = m.group(0)[3:] if m is not None else "/"
    rowdata.clear()
    rowdata.append(node['node'])
    rowdata.append(vm['vmid'])
    rowdata.append(vm['name'])
    if vm['vmid'] in pooldict.keys():
      rowdata.append(pooldict[vm['vmid']])
    else:
      rowdata.append("/")
    rowdata.append(vm['status'])
    rowdata.append(ip)
    rowdata.append(des)
    worksheet.write_row(row, 0, rowdata)
    row += 1
  for vm in proxmox.nodes(node['node']).qemu.get():
    conf = proxmox.nodes(node['node']).qemu(vm['vmid']).config.get()
    des = conf.get("description")
    des = des.strip().replace('\n', ' ').replace('\r', ' ') if des is not None else "/"
    ip = "/"
    net = conf.get("net0")
    if net is not None:
      m = re.search(patt, net)
      ip = m.group(0)[3:] if m is not None else "/"
    rowdata.clear()
    rowdata.append(node['node'])
    rowdata.append(vm['vmid'])
    rowdata.append(vm['name'])
    if vm['vmid'] in pooldict.keys():
      rowdata.append(pooldict[vm['vmid']])
    else:
      rowdata.append("/")
    rowdata.append(vm['status'])
    rowdata.append(ip)
    rowdata.append(des)
    worksheet.write_row(row, 0, rowdata)
    row += 1
workbook.close()
#
df = pd.DataFrame(pd.read_excel('./pve.xlsx'))
df = df.set_index(['NODE','VMID'])
df = df.sort_index()
df.to_excel(r'./pve.xlsx')
#df.to_excel('./pve_sorted.xlsx')

Proxmoxer Logo Design Contest

I would love to have an official logo for Promoxer. It doesn't have to be super complex, but it should not just be a copy of the Proxmox logo.

Submission Rules

  • reply in this issue with a submission for the Proxmoxer logo
  • Vector images (SVG) are preferred to bitmap (PNG, JPG, etc), but is not a strict requirement
    • If you create a vector image, submitting a bitmap is fine, just note that there is a vector master copy
  • add the πŸ‘ reaction to your image (vote for yourself)
  • Only post images you created or explicitly have permission to submit
  • All images submitted will be considered to fall under the license of this repo

Voting Rules

  • Click the πŸ‘ under the image you like the best
  • Please only vote for one image
  • You may change your vote by removing your vote from one image and adding it to another.

Picking a Winner

Voting will close 2022-04-30 (end of April). Votes on images will be used to gauge public opinion, but the project maintainers have the right to veto the vote if required. The creator of the winning image will be contacted to collect the source image files. The winner will be credited with the creation of the logo in the changelog and in other locations as the maintainers see fit.


Thank you for all your submissions, and may the best logo win!

Unable to update ipsets

Hi,

I'm trying to use the library to check, add or update ipsets, but, as the IP addresses contains . it is not possible.

DOC: https://pve.proxmox.com/pve-docs/api-viewer/index.html#/cluster/firewall/ipset/{name}/{cidr}

So I have to create a call like:

from proxmoxer import ProxmoxAPI
proxmox = ProxmoxAPI(PROXMOX_HOST, user=USER_NAME, token_name=TOKEN_NAME, token_value=TOKEN_SECRET, verify_ssl=False)

CheckIP='1.2.3.4'


# Adding a IP into the blacklist IPset
proxmox.cluster.firewall.ipset.blacklist.post(cidr='1.2.3.4',comment='test asdf')

# Getting the IP from blacklist IPset
MyIP=proxmox.cluster.firewall.ipset.blacklist.get('1.2.3.4')

# MyIP = {'digest': 'randomstring',
# 'comment': 'test asdf',
# 'cidr': '1.2.3.4'}

# Updating the IP
# ????
# should be something like:

proxmox.cluster.firewall.ipset.blacklist.1.2.3.4.put(comment='new comment')
# but . is a special character in python, so it is not possible except the library changes another character to `.` on the API call.

Same problem for delete, which should be:

proxmox.cluster.firewall.ipset.blacklist.1.2.3.4.delete()

Having issues with Ansible role

I've write an Ansible role to add the ssh public key to a proxmox server.

After the execution of the playbook:

---
- proxmox:
    api_user: "{{ proxmox.api_user }}"
    api_password: "{{ proxmox.api_password }}"
    api_host: "{{ target }}"
    #pubkey: "{{ public_keys.victor_home }}"

I got the next error:

**"msg": "authorization on proxmox cluster failed with exception: invalid literal for float(): 6.1-8"**

Talking on proxmox forums aswell

I don't know how to read lxc config

Hello all,
want to extract the existing configuration of a PVE Node for documentation purposes.

I have no trouble to display some metadata of the lxc. But how do I get the config ?

In pvesh it looks like this:

pvesh get /nodes/xxx/lxc/200/config/

In python I do:

from proxmoxer import ProxmoxAPI

proxmox = ProxmoxAPI('xxx.de', user=yyy',
                 password='yyyyyy', verify_ssl=False)

for node in proxmox.nodes.get():
    for lxc in proxmox.nodes(node['node']).lxc.get():
        print (lxc)

the dictionary lxc does not contain a 'config' and I did not manage to extract this information in any way i tried.

How shall this be done ?

Thanks for reading !

Norbert

proxmoxer agent exec-status and "out-data"

Hello

How can i type "out-data" to see output of command ?

code :

def agent_get_swap(targetnode,vmid):
  command = 'blkid -o value -L swap'
  agent = []
  agent = proxmox.nodes(targetnode).qemu(vmid).agent.exec.post(command=command)
  pid = agent['pid']
  swap = proxmox.nodes(targetnode).qemu(vmid).agent("exec-status").get(pid=pid)
  return swap

test = agent_get_swap(local-15,101)
print (test)

it only print {'exited': 0} without "out-data" which I need (it should be /dev/sdb)

I can read that in exec-status out-data is optional so I thing I need to turn it on somehow.
https://pve.proxmox.com/pve-docs/api-viewer/index.html#/nodes/{node}/qemu/{vmid}/agent/exec-status

501 Not Implemented

I just finished setting up my proxmox server and had wanted to try this out. After copying the example in the readme (the PVE one) I ran it and was greeted with this error:

Traceback (most recent call last):
  File "/run/media/marvel/data/Coding/python_in_proxmox/main.py", line 9, in <module>
    for vm in proxmox.nodes(node['node']).openvz.get():
  File "/home/marvel/.local/lib/python3.9/site-packages/proxmoxer/core.py", line 105, in get
    return self(args)._request("GET", params=params)
  File "/home/marvel/.local/lib/python3.9/site-packages/proxmoxer/core.py", line 90, in _request
    raise ResourceException("{0} {1}: {2} - {3}".format(
proxmoxer.core.ResourceException: 501 Not Implemented: Method 'GET /nodes/lab/openvz' not implemented - b'{"data":null}'

I am running this on arch linux with python 3.9.

Thanks in advance

Qemu listing empty

pvesh returns a list of vms under qemu:

pvesh get /nodes/<node>/qemu
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬
β”‚ status  β”‚ vmid β”‚ cpus β”‚ lock β”‚    maxdisk β”‚    maxmem β”‚ name            β”‚   pid β”‚ qmpstatus β”‚
β•žβ•β•β•β•β•β•β•β•β•β•ͺ══════β•ͺ══════β•ͺ══════β•ͺ════════════β•ͺ═══════════β•ͺ═════════════════β•ͺ═══════β•ͺ═══════════β•ͺ
β”‚ running β”‚ 1100 β”‚    1 β”‚      β”‚  10.00 GiB β”‚  1.00 GiB β”‚ vmname          β”‚  1321 β”‚           β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Ό
...

With proxmoxer the list is empty:

>>> proxmox.nodes.get('<node>')
[{u'name': u'ceph'}, {u'name': u'disks'}, {u'name': u'apt'}, {u'name': u'version'}, {u'name': u'syslog'}, {u'name': u'journal'}, {u'name': u'status'}, {u'name': u'wakeonlan'}, {u'name': u'subscription'}, {u'name': u'report'}, {u'name': u'tasks'}, {u'name': u'rrd'}, {u'name': u'rrddata'}, {u'name': u'replication'}, {u'name': u'vncshell'}, {u'name': u'termproxy'}, {u'name': u'spiceshell'}, {u'name': u'time'}, {u'name': u'dns'}, {u'name': u'services'}, {u'name': u'scan'}, {u'name': u'storage'}, {u'name': u'qemu'}, {u'name': u'lxc'}, {u'name': u'vzdump'}, {u'name': u'network'}, {u'name': u'aplinfo'}, {u'name': u'startall'}, {u'name': u'stopall'}, {u'name': u'netstat'}, {u'name': u'firewall'}, {u'name': u'certificates'}, {u'name': u'config'}, {u'name': u'hosts'}]

>>> proxmox.nodes.get('<node>','qemu')
[]

Version:

>>> proxmox.version.get()
{u'release': u'6.2', u'version': u'6.2-4', ... }

Remark <node> should be replaced with your node name

What privileges necessary?

I'm looking to lock down access to my Proxmox server and am using Ansible to create VMs/LXCs. Currently I'm using an API token and with the PVEAdmin role but I'm wondering if I can reduce that still further. From playing around a bit it looks like I need a cross between the PVEDatastoreAdmin and PVEVMAdmin roles (https://pve.proxmox.com/wiki/User_Management#pveum_permission_management). Just trying to get a sense of what privileges are specifically required. This may not be the right place to ask (may need to go to ansible) so you can tell me to go there and I won't be offended :-)

Can't clone template

I am trying to clone a template with the following code:


 proxmox_node = proxmox.nodes(NODE)

 proxmox_node.qemu(123).status.start.post()  # it works

 next_id = max([int(vm['vmid']) for vm in proxmox_node.qemu.get()]) + 1
 proxmox_node.qemu(142).clone.post(newid=next_id)  
 # fails: proxmoxer.core.ResourceException: 403 Forbidden: Permission check failed - b'{"data":null}'

What am I doing wrong? If I use the web interface to clone the template it works (obviously with the same user)

Wrong pve node name in config

This issue is based at my own "bug" report 'bout this intergration, here is the original topic: home-assistant/core#42637 (comment)

For reproduce:
For-example your node called is proxmox, just add integration config like this:

proxmoxve:
  - host: 192.168.0.9
    verify_ssl: false
    username: homeassistant
    password: password
    realm: pve
    nodes:
      - node: Proxmox <-- for example first letter is uppercase
        vms:
...

Next, u will see this answer in HA log 'bout the issue with this integration:

proxmoxve: Error on device update!
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/helpers/entity_platform.py", line 346, in _async_add_entity
    await entity.async_device_update(warning=False)
  File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 471, in async_device_update
    await self.hass.async_add_executor_job(self.update)  # type: ignore
  File "/usr/local/lib/python3.8/concurrent/futures/thread.py", line 57, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/usr/src/homeassistant/homeassistant/components/proxmoxve/binary_sensor.py", line 83, in update
    item = self.poll_item()
  File "/usr/src/homeassistant/homeassistant/components/proxmoxve/binary_sensor.py", line 94, in poll_item
    self._proxmox_client.get_api_client()
  File "/usr/local/lib/python3.8/site-packages/proxmoxer/core.py", line 105, in get
    return self(args)._request("GET", params=params)
  File "/usr/local/lib/python3.8/site-packages/proxmoxer/core.py", line 90, in _request
    raise ResourceException("{0} {1}: {2} - {3}".format(
proxmoxer.core.ResourceException: 596 Errors during TLS negotiation, request sending and header processing: tls_process_server_certificate: certificate verify failed - b''

Based on the response in Home Assistant logs completely is not clear what this integration needs. I think this needs to be fixed, and a check should be added with the answer that such a node was NOT FOUND. After such an answer, I hope users will not have any questions, which was not true.

But in fact, guys, I thought, maybe just correct the description of the integration, where to describe in more detail the importance of the coincidence of the node name from the hypervisor with the config in the Home Assistant?

Ok, thanks in advance! Best regards.

proxmoxer agent exec-status

Hello,

I am trying to check agent exec-status command but proxmoxer don't know anything after "-" so perhaps there is some other keyword to use ?

when I am trying to check on console with pvesh it is working
"pvesh get /nodes/local-11/qemu/10001/agent/exec-status --pid 1017"

my code:
targetnode=local-11
vmid=10001
pid=1017
proxmox.nodes(targetnode).qemu(vmid).agent.exec-status(pid=pid).get()

proxmoxer variables inside .post(variable=array) error

Hello,

I want to send post method via proxmoxer but I want to use variables "hdd3_type" instead of scsi2 (when I put scsi2=hdd3array it is working!) :

code :

def vm_hdd_add(targetnode,vm_modifyid,hdd3_type,hdd3array):
  hddadd = proxmox.nodes(targetnode).qemu(vm_modifyid).config.post(hdd3_type=hdd3array)
  return hddadd

hdd3_type = 'scsi2'
hdd3array = 'moosefs:3,format=qcow2,discard=on'
upid = vm_hdd_add(targetnode,vm_modifyid,hdd3_type,hdd3array)

return
parameter verification failed. - b'{"data":null,"errors":{"hdd3_type":"property is not defined in schema and the schema does not allow additional properties"}}'

I was checking also some other methods to omit this error but without success.
.post(hdd3_type+'='+hdd3array)

return
Not Implemented: Method 'POST /nodes/local-15/qemu/100/config/scsi2=moosefs:3,format=qcow2,discard=on' not implemented - b'{"data":null}'

Give the paramiko instance

Hi !

I suggest an other way to use paramiko.
I'm facing a problem where I need to use the API and run basic commandsin SSH to my proxmox cluster.

I use paramiko and proxmoxer.
Do you think if it possible to give the instance of paramiko in parameter of proxmoxer.
Or maybe in the other side, it's possible to get the instance of proxmoxer ?

Thanks for your work !

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.