Proxmox API

Hallo Leute,

habe einen Server mit Proxmox drauf.
Proxmox bietet eine API Schnittstelle.

Es wird mit curl ein Ticket erstellt der nur 2 Stunden Gültig ist. Mit dem Ticket können die Daten Abgefragt werden.

Ist die Abfrage mit IPS realisierbar?

Gruß

Klar. Schau dir einfach mal Beispiele zu curl oder file_get_contents an.

Oder schau mal hier: GitHub - Saleh7/ProxmoxVE_PHP_API: ProxmoxVE PHP API

paresy

Hallo Leute,

habe etwas Zeit mich wieder mit dem Thema zu beschäftigen. Leider komme ich kein Schritt weiter.
Kann mir jemand Helfen?

Ich muss ein Token erstellen. Proxmox API
Ich verstehe aber nicht wie.

curl -k -d "username=root@pam&password=yourpassword" https://10.0.0.1:8006/api2/json/access/ticket

Gruß

habe geschafft ein Token & ticket auszulesen.

<?php

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://192.168.178.250:8006/api2/json/access/ticket');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, "username=root@pam&password=PASSWORD");
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

$headers = array();
$headers[] = 'Content-Type: application/x-www-form-urlencoded';
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$result = curl_exec($ch);
if (curl_errno($ch)) {
   echo 'Error:' . curl_error($ch);
}
curl_close($ch);
echo 'result=' . $result . PHP_EOL;

Ergebniss:

„CSRFPreventionToken“:„4EEC61E2:lwk7od06fa1+DcPUwBTXCcndyAY“
„ticket“:„PVE:root@pam:4EEC61E2::rsKoApxDTLYPn6H3NNT6iP2mv…“

Wie komme ich jetzt an die Daten?
In der Doku ist es ein curl Beispiel:

curl -k -b "PVEAuthCookie=PVE:root@pam:4EEC61E2::rsKoApxDTLYPn6H3NNT6iP2mv..." https://10.0.0.1:8006/api2/json/

Würde mich über Hilfe freuen.

Gruß

OK habe geschafft

<?php

$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, 'https://192.168.178.250:8006/api2/json//cluster/resources');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_COOKIE, "PVEAuthCookie=PVE:root@pam:617BA9B4::MbXeTNFVb6n5......");
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

$result = curl_exec($ch);
if (curl_errno($ch)) {
    echo 'Error:' . curl_error($ch);
}
curl_close($ch);


$json = json_decode($result, true);
print_r($json = json_decode($result));

Gruß

Hallo Leute,

überlege dafür ein Modul zu erstellen (wenn ich es schaffe :grimacing:).
Besteht überhaupt bedarf?

Gruß

Habe zweckst übung angefangen ein Modul zu erstellen.
Habe aber ein verständniss Problem bezüglich Daten.

Plan ist:

ClientSocket „ProxmoxIO“ für Token und Ticket.

Bekomme mein Token und Ticket auch ausgelesen.

Instanz für Nodes „ProxmoxNode“
proxmox3

Wie bekomme ich die Daten von „ProxmoxIO“ zum „ProxmoxNode“?
Alle Instanzen müssen ja auf den Token und Ticket zugreifen.

Es werden im „ProxmoxIO“ einmal die Daten geholt die dann 2 Stunden Gültig sind.
Kann ich mit den Instanzen den Socket Updaten wenn der Toket abgelaufen ist?

Gruß

Das ist ja eher eine grundsätzliche Verständnisfrage zum SDK.
Da wäre es eventuell besser ein eigenes Thema im passenden Bereich aufzumachen.
Dort gibt es auch schon diverse Themen dazu.
Zum Beispiel:

Erster Tipp:
Benutze auf der Symcon Webseite im Entwicklerbereich den Modul Generator und fülle dort den Bereich Datenfluss für deinen Device Instanzen aus.
Dann hast du gleich fertige Funktionen im Code.
Zusätzlich sind die Symcon DemoModule auf GitHub sehr hilfreich, da sie immer ein spezielles Thema behandeln.

Um den Punkt mit den Token und Ticket aufzugreifen, diese Daten sollten den IO nie verlassen.
Deine DeviceInstanz (ProxmoxNode) sendet die Anfrage an den IO, der macht den WebRequest und liefert das Ergebnis zurück an das Device.
Den ungültigen Token sollte der IO selbstständig erkennen und erneuern (eventuell per Timer).
Michael

Hallo Michael,

kannst du mir sagen wo bzw welchen Beispiel ich bei SymconTest gucken soll? Es sind viele Beispiele.

Gruß

IOSplitter und IOTest sind zwei Module welche Daten austauschen.
Wobei gerade der Datenaustausch doch sehr wenig Beachtung bei den TestModulen hat.
Ergänzend sei noch die Dokumentation hierzu zu empfehlen:
https://www.symcon.de/service/dokumentation/entwicklerbereich/sdk-tools/sdk-php/datenfluss/
Michael

Also muss ich ein Splitter erstellen und die Daten vom ClientSocket im Splitter zwischenspeichern?
Und die Instanzen bekommen die Daten vom Splitter?

Jein :slight_smile:
Kommt auf die Umsetzung an.
Du kannst natürlich den Symcon eigenen WWWReader als IO benutzen, dann macht dein Splitter das Token handling.

Oder du machst es so weiter wie du jetzt schon angefangen hast und baust deinen eigenen IO welcher die CURL Abfragen inkl. Token selber baut.
Ich würde zu letzteren tendieren, da ich glaube dass der Symcon WWWReader keine Cookies unterstützt.
Michael

Habe eineiges Probiert und gelesen. Es klappt nicht.

Instanz:

<?php

declare(strict_types=1);
	class SymconProxmoxNode extends IPSModule
	{
		public function Create()
		{
			//Never delete this line!
			parent::Create();
			$this->RegisterPropertyString('Node', '');
			$this->RegisterPropertyInteger('UpdateInterval', 60);
			$this->RegisterTimer('Update', $this->ReadPropertyInteger('UpdateInterval') * 1000, 'PVENODE_Update($_IPS[\'TARGET\']);');
       
			$this->RequireParent('{03F746E8-3F0F-C53E-8F1A-BF9A4DAFAC76}');
		}

		public function Destroy()
		{
			//Never delete this line!
			parent::Destroy();
		}

		public function ApplyChanges()
		{
			$this->SetTimerInterval('Update', $this->ReadPropertyInteger('UpdateInterval') * 1000);
			//Never delete this line!
			parent::ApplyChanges();
		}

		public function Send()
		{
			$this->SendDataToParent(json_encode(['DataID' => '{A8F28772-131A-351B-DEC1-BA2995EAE4C3}']));
			
		}

		public function ReceiveData($JSONString)
		{
			$data = json_decode($JSONString);
			IPS_LogMessage('Device RECV', utf8_decode($data->Buffer));
		}
	}

IO Socket:

<?php

declare(strict_types=1);
	class SymconProxmoxIO extends IPSModule
	{
		public function Create()
		{
			$this->RegisterPropertyString('Url', '');
			$this->RegisterPropertyInteger('Port', 8006);
            $this->RegisterPropertyString('Username', '');
            $this->RegisterPropertyString('Password', '');
            
			$this->RegisterPropertyBoolean('Active', false);
			//Never delete this line!
			parent::Create();
		}

		public function Destroy()
		{
			//Never delete this line!
			parent::Destroy();
		}

		public function ApplyChanges()
		{
			//Never delete this line!
			parent::ApplyChanges();
		}

		public function ForwardData($JSONString)
		{
			$data = json_decode($JSONString);
			IPS_LogMessage('IO FRWD', utf8_decode($data->Buffer));
		}

		public function Send(string $Text)
		{
			$this->SendDataToChildren(json_encode(['DataID' => '{F32EAE78-97AA-E390-804A-8600121F361A}', 'Buffer' => $Text]));
		}
		public function Token()
		{
			$url = $this->ReadPropertyString('Url');
			$port = $this->ReadPropertyInteger('Port');
			$username = urlencode($this->ReadPropertyString('Username'));
            $password = urlencode($this->ReadPropertyString('Password'));

			$curl = curl_init();

            curl_setopt_array($curl, array(
					CURLOPT_URL => 'https://'.$url.':'.$port.'/api2/json/access/ticket',
					CURLOPT_RETURNTRANSFER => 1,
					CURLOPT_POST => 1,
					CURLOPT_POSTFIELDS => 'username='.$username.'@pam&password='.$password,
					CURLOPT_SSL_VERIFYPEER => false,
				));

			$result = curl_exec($curl);
			$httpcode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
			if (curl_error($curl)) {
    			echo 'Error:' . curl_error($curl);
			}

			$this->SendDebug('Token()', 'Response:' . $result, 0);
			
			curl_close($curl);

			if ($httpcode != 200){
				$token = 'Fehler';
				$this->SendDebug('Token()', 'Denied permission', 0);
			}
			if ($httpcode == 200){
				$json = json_decode($result, true);
				$token = ($json['data']['CSRFPreventionToken']);
			}
            
			


			return $token;
		}
	}

Kann mir jamend bitte sagen wo ich was ausführen muss damit ich die Daten von IO Socket bekomme?

Kann ich dir nicht sagen, weil ein Modul aus mehr als nur PHP Code besteht. Ohne module.json wo das prefix steht, weiß keiner wie der PHP Befehl lautet.
Hier wäre das FT_CallString und bei dir dann ???_Token.

Michael

ProxmoxIO hat PVEIO ProxmoxNode hat PVENODE als Präfix.
Für Tests wird im Moment beim drücken des Buttons in der IO Instanz die Funktion „Token“ ausgeführt. Ich bekomme mein Token als Return und im Debug alles.
Was muss ich noch ausführen damit die Daten beim Node landen?
Später kommt noch die Instanz „ProxmoxVM“, da brauche ich auch die Daten.

Gruß

Wie gesagt, warum soll ProxmoxNode den Token bekommen? Sinnvoller ist es wenn ProxmoxNode eine Anfrage an den IO sendet (z.B. sende Payload xyz).
Das geht im ProxmoxNode mit SendDataToParent.
Und im ProxmoxIO kommt der Datensatz dann bei ForwardData an und was du dort mit return zurückgibst, kommt als Rückgabewert von SendDataToParent im ProxmoxNode zurück.
So hast du auch eine 1 zu 1 Kommunikation.

Wenn du spontan Daten vom IO an die Childs (ProxmoxNode, ProxmoxVM usw…) senden willst, kannst du das im ProxmoxIO über SendDataToChildren machen; aber dann bekommen alle Childs die Daten (= je ein belegter PHP-Slot pro Child-Instanz). Ist also eine 1:n Kommunikation.
Beides kann Sinn machen, ist immer die Frage was/wie die API die Daten liefert.
Hast du z.B. eine Anfrage an Proxmox wo eh immer alle Daten für alle Instanzen enthalten sind, macht das zweite schon Sinn. Musst du aber eh pro Instanz (ProxmoxNode, ProxmoxVM usw…) eine eigene Anfrage an Proxmox senden, ist es sinnvoller die Childs initiieren die Abfrage über den ProxmoxIO.

Michael

in beiden modul.php sind die Funktionen vorhanden. Ich weiss aber nicht was genau ich machen soll.
Habe etliche Beispiele angeschaut und Probiert. Komme einfach nicht weiter.
Muss ich die ForwardData & SendDataToParent Funktionen aufrufen?

Habe im Node Instanz ein Button der die Abfrage machen soll (nur zum Testen) geht aber nichts.
Kann mit jemand ein Code Schnippsel geben? Wäre echt Super.

Gruß

Hallo Sewo,

einfacher wäre es, wenn Du zeigst was Du bisher hast, dann kann man genauer weiterhelfen.

Zur Frage:
Aus Deinem Node machst Du :

$return = $this->Send_to_Parent("Do Something");
$this->SendDebug(__FUNCTION__,  $return , 0);

protected function Send_to_Parent($Buffer)
{
	$return = $this->SendDataToParent(json_encode([
		'DataID' => "{79827379-F36E-4ADA-8A95-5F8D1DC92FA9}", // UUID anpassen!
		'Buffer' => utf8_encode($Buffer),
	]));
	return $return;
}

Das landet im „Gateway“ hier:

public function ForwardData($JSONString)
{
	$data = json_decode($JSONString,true);
	$returndata = "";
	switch ($data)
	{
		case 'Do Something':
// do what you want
			$returndata = 'Done';
			break;
    }
return $returndata;
}

Damit landet „Done“ bei Dir zurück im „Node“ und wird dort im Debug ausgegeben.

Wichtig sind die UUID. Wie Michael schon sagte, erstelle Dir eine entsprechende Vorlage mit dem Modulgenerator, dann ist es eigentlich nicht so kompliziert.

Attain

Hallo Attain,

habe mein Gebastel Hochgeladen.

Danke für die Hilfe.
Gruß