Last active
April 7, 2025 19:42
Revisions
-
gpetrousov renamed this gist
Apr 7, 2025 . 1 changed file with 0 additions and 0 deletions.There are no files selected for viewing
File renamed without changes. -
gpetrousov revised this gist
Mar 24, 2025 . 1 changed file with 43 additions and 68 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,110 +1,85 @@ import requests requests.packages.urllib3.disable_warnings() # Node1 data node1_hostname = "10.1.1.135" node1_username = "root@pam" node1_password = "toortoor" node1_api_url = f"https://{node1_hostname}:8006/api2/json" # Node2 data node2_hostname = "10.1.1.136" node2_username = "root@pam" node2_password = "toortoor" node2_api_url = f"https://{node2_hostname}:8006/api2/json" # 0. Create ticket node1_auth_data = { 'username': node1_username, 'password': node1_password } auth_response = requests.post(f'{node1_api_url}/access/ticket', json=node1_auth_data, verify=False) auth_response.raise_for_status() node1_ticket = auth_response.json()['data']['ticket'] csrf_token = auth_response.json()['data']['CSRFPreventionToken'] # 1. Create the cluster on node1 node1_headers = { 'CSRFPreventionToken': csrf_token, 'Content-Type': 'application/x-www-form-urlencoded', } node1_cookies = {'PVEAuthCookie': node1_ticket} cluster_data = { 'clustername': "Experimetal", 'link0': node1_hostname, } create_response = requests.post(f'{node1_api_url}/cluster/config/', headers=node1_headers, cookies=node1_cookies, data=cluster_data, verify=False) # Check if cluster exists # status_response = requests.get(f'{node1_api_url}/cluster/config/nodes/', headers=node1_headers, cookies=node1_cookies, verify=False) # print(status_response.json()) if create_response.reason == "cluster config '/etc/pve/corosync.conf' already exists": print("Cluster exists") else: print(create_response.json()) # 2. Get join information from node1 print("Getting node1 cluster join info") join_info_response = requests.get(f"{node1_api_url}/cluster/config/join", headers=node1_headers, cookies=node1_cookies, verify=False) join_info_response.raise_for_status() join_fingerprint = join_info_response.json()["data"]["nodelist"][0]["pve_fp"] # 2.5 Craft request to join existing cluster node2_auth_data = { "username": node2_username, "password": node2_password } auth_response_node2 = requests.post(f"{node2_api_url}/access/ticket", json=node2_auth_data, verify=False) auth_response_node2.raise_for_status() node2_ticket = auth_response_node2.json()["data"]["ticket"] csrf_token_node2 = auth_response_node2.json()["data"]["CSRFPreventionToken"] node2_headers = { 'CSRFPreventionToken': csrf_token_node2, 'Content-Type': 'application/x-www-form-urlencoded', } node2_data = { "fingerprint": join_fingerprint, "hostname": node1_hostname, "password": node1_password, "link0": node2_hostname } node2_cookies = {'PVEAuthCookie': node2_ticket} # 3. Add node2 to the cluster print("Attempting to join") join_response = requests.post(f"{node2_api_url}/cluster/config/join", headers=node2_headers, data=node2_data, cookies=node2_cookies, verify=False) join_response.raise_for_status() print(join_response.json()) print("Join done!!") -
gpetrousov created this gist
Mar 24, 2025 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,110 @@ import requests import json # Disable SSL nags requests.packages.urllib3.disable_warnings() def get_proxmox_ticket(username, password, api_url): """Retrieves a Proxmox API ticket and cookie.""" auth_data = { 'username': username, 'password': password } auth_response = requests.post(f'{api_url}/access/ticket', json=auth_data, verify=False) auth_response.raise_for_status() ticket = auth_response.json()['data']['ticket'] csrf_token = auth_response.json()['data']['CSRFPreventionToken'] # cookie = auth_response.cookies['PVEAuthCookie'] return ticket, csrf_token def create_proxmox_cluster(hostname, username, password, api_url): """Creates a Proxmox cluster.""" ticket, csrf_token = get_proxmox_ticket(username, password, api_url) headers = { 'CSRFPreventionToken': csrf_token, 'Content-Type': 'application/x-www-form-urlencoded', } cookies = {'PVEAuthCookie': ticket} data = { 'clustername': "Experimental", 'link0': hostname, } create_response = requests.post(f'{api_url}/cluster/config/', headers=headers, cookies=cookies, data=data, verify=False) # Check if cluster exists if create_response.reason == "cluster config '/etc/pve/corosync.conf' already exists": return "Cluster exists" else: return create_response.json() node1_hostname = "<IP of node 1>" node1_username = "root@pam" node1_password = "<SSH password>" node1_api_url = f"https://{node1_hostname}:8006/api2/json" node2_hostname = "IP of node 2" node2_username = "root@pam" node2_password = "<SSH password>" node2_api_url = f"https://{node2_hostname}:8006/api2/json" # 1. Create the cluster on node1 create_result = create_proxmox_cluster(node1_hostname, node1_username, node1_password, node1_api_url) print(f"Cluster creation result: {json.dumps(create_result, indent=2)}") # 2. Get join information from node1 auth_data_node1 = { "username": node1_username, "password": node1_password } auth_response_node1 = requests.post(f"{node1_api_url}/access/ticket", json=auth_data_node1, verify=False) auth_response_node1.raise_for_status() ticket_node1 = auth_response_node1.json()["data"]["ticket"] csrf_token_node1 = auth_response_node1.json()["data"]["CSRFPreventionToken"] headers_node1 = { 'CSRFPreventionToken': csrf_token_node1, 'Content-Type': 'application/x-www-form-urlencoded', } cookies_nodes1 = {'PVEAuthCookie': ticket_node1} print("Getting node1 cluster join info") join_info_response = requests.get(f"{node1_api_url}/cluster/config/join", headers=headers_node1, cookies=cookies_nodes1, verify=False) join_info_response.raise_for_status() join_fingerprint = join_info_response.json()["data"]["nodelist"][0]["pve_fp"] # 2.5 Craft request to join existing cluster auth_data_node2 = { "username": node2_username, "password": node2_password } auth_response_node2 = requests.post(f"{node2_api_url}/access/ticket", json=auth_data_node2, verify=False) auth_response_node2.raise_for_status() ticket_node2 = auth_response_node2.json()["data"]["ticket"] csrf_token_node2 = auth_response_node2.json()["data"]["CSRFPreventionToken"] headers_node2 = { 'CSRFPreventionToken': csrf_token_node2, 'Content-Type': 'application/x-www-form-urlencoded', } data_node2 = { "fingerprint": join_fingerprint, "hostname": node1_hostname, "password": node1_password, "link0": node2_hostname } cookies_nodes2 = {'PVEAuthCookie': ticket_node2} # 3. Add node2 to the cluster print("Attempting to join") join_response = requests.post(f"{node2_api_url}/cluster/config/join", headers=headers_node2, data=data_node2, cookies=cookies_nodes2, verify=False) join_response.raise_for_status() print(join_response.json()) print("Join done!!")