Repository: sosreport/sos

Issue:
implement PROXMOX / PVE plugin
Hi team,

Running sos on a proxmox/pve host does not produce all expected logs (VM inventory, storage pools, SDN .. )

PVE is 100% api driven and gathering all those info is quite simple

I started to ask one of my dev guy to gather all commands (mostly with `pvesh`)

My question here is : how may we help you ?
- give you all the commands + directories to copy to sos output ?
- start from a plugin template and modify it ? ==> which one 
- start from scratch in python ?

Thx

PS : we will do the same with Proxmox Backup Server / PBS after 
PS2 : all my "recent" activity around sos is to help the opensource OGrEE Datacenter Digital Twin project which I started 4 years ago. (https://ogree.ditrit.io) (I've been using sos since years for linux hosts for that twin, with some other collect tools that run on other platforms (vmware,windows, ibm AIX... we could discuss about that elsewhere.

Hervé 


Discussion:
We're happy to write a plugin if you can provide the commands to run (including any commands that we should run based on the output of other commands), files/dirs to collect, what (if any) collections need to be scrubbed for sensitive data like passwords, and what should determine if the plugin gets automatically run or not (most common is name(s) of installed package(s)).

Alternatively, also happy to review any plugin you write and open a PR for. A good example plugin would probably be `block`, `podman`, or `python` (which also shows how to make a plugin perform differently on different distributions, if you need that).  There's also a [wiki entry](https://github.com/sosreport/sos/wiki/How-to-Write-a-Plugin) on writing a plugin.
Hi @TurboTurtle : here is the v1 of the plugin, written we one of my devs.  We kept 100% of your python philosophy and here is how I imagine it :
- PVE api has so many endpoints, most of them are "GET", some of them are "PUT"
- in most cases we do not necessarly want to spend hours waiting for our sosreport to complete, so I start in this version we the endpoints I consider "important"
- PVE natively propopse TEXT and JSON-PRETTY, so no need to code that transformation
- i will propose you a second version next week in which :
-- user will be able to generate endpoint files for each categoris (cluster/node/storage/...) 
-- files could be changed from the cmdline to add/remove some endpoints
-- a second run of sos using those files will finnally do the requested job

we tested that on 
- standalone PVE servers 
- 4 or 6 nodes clusters with SAN storage
- 6 nodes cluster with local CEPH storage
[proxmox.py.txt](https://github.com/sosreport/sos/files/14468839/proxmox.py.txt)

dev is https://github.com/sohzaz 

Resolving patch:
diff --git a/sos/report/plugins/proxmox.py b/sos/report/plugins/proxmox.py
new file mode 100644
--- /dev/null
+++ b/sos/report/plugins/proxmox.py
@@ -0,0 +1,101 @@
+# Copyright (C) 2024 ORNESS/Ditrit Drien Breton <drien.breton@orness.com>
+
+# This file is part of the sos project: https://github.com/sosreport/sos
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions of
+# version 2 of the GNU General Public License.
+#
+# See the LICENSE file in the source distribution for further information.
+import json
+
+from sos.report.plugins import Plugin, DebianPlugin, PluginOpt
+
+
+class Proxmox(Plugin, DebianPlugin):
+    """
+    This plugin will capture information about the system's
+    Proxmox Virtualization Environment.
+
+    It will collect information about the cluster, nodes, pools and
+    storage from the Proxmox API.
+    """
+    short_desc = 'Proxmox cluster information'
+
+    plugin_name = 'proxmox'
+    packages = ('proxmox-ve',)
+
+    option_list = [
+        PluginOpt('output_formats',
+                  desc='List of output formats to use '
+                       'for the commands separated by ":".',
+                  default='text',
+                  ),
+    ]
+
+    def setup(self):
+        output_formats = self.get_option('output_formats').split(':')
+
+        commands = [
+            'cluster/resources',
+            'cluster/config/nodes',
+            'cluster/options',
+            'nodes/:id/status',
+            'nodes/:id/storage',
+            'nodes/:id/network',
+            'pools',
+            'storage',
+            'storage/:sid',
+            'cluster/ceph/status',
+            'cluster/ceph/metadata',
+            'cluster/ceph/flags',
+        ]
+
+        cmd_paths = []
+
+        for command in commands:
+            cmd_paths.extend(self.build_cmd_paths(command))
+
+        self.add_cmd_output([
+            f"pvesh get {cmd} {'--noborder' if format == 'text' else ''} "
+            f"--output-format {format}"
+            for cmd in cmd_paths
+            for format in output_formats
+        ])
+
+    def build_cmd_paths(self, base_path):
+        """
+        Build command paths,
+        replacing dynamic attributes with data from the API
+
+        :param base_path: The base path to build from
+        :type base_path: str
+
+        :return: A list of paths
+        """
+        parts = base_path.split('/')
+        paths = []
+
+        id_index = next((i for i, part in enumerate(parts)
+                         if part.startswith(':')), None)
+
+        if id_index is not None:
+            path = "/".join(parts[:id_index])
+            trailing_path = "/".join(parts[id_index + 1:])
+
+            results = self.exec_cmd(f'pvesh ls {path} --output-format json')
+
+            if results["status"] == 0:
+                children = json.loads(results["output"])
+                for child in children:
+                    paths.extend(
+                        self.build_cmd_paths(
+                            f"{path}/{child['name']}/{trailing_path}"
+                        )
+                    )
+
+        else:
+            paths.append('/'.join(parts))
+        return paths
+
+# vim: set et ts=4 sw=4 :


Test patch: