Skip to content

Instantly share code, notes, and snippets.

@gpetrousov
Last active April 7, 2025 19:42
Show Gist options
  • Save gpetrousov/6fb2d5835e96c9133c0533190d780a79 to your computer and use it in GitHub Desktop.
Save gpetrousov/6fb2d5835e96c9133c0533190d780a79 to your computer and use it in GitHub Desktop.
experimetal
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!!")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment