Compare commits
1 Commits
Author | SHA1 | Date | |
---|---|---|---|
5fc7979d4c |
42
functions.py
42
functions.py
@ -1,4 +1,5 @@
|
||||
import logging
|
||||
import time
|
||||
|
||||
from proxmoxer import ProxmoxAPI
|
||||
|
||||
@ -55,12 +56,17 @@ def delete_vm(
|
||||
proxmox: ProxmoxAPI,
|
||||
node: str,
|
||||
vmid: int,
|
||||
) -> None:
|
||||
proxmox.nodes(node).qemu(vmid).delete(
|
||||
node=node,
|
||||
vmid=vmid,
|
||||
) -> str:
|
||||
upid: str = (
|
||||
proxmox.nodes(node)
|
||||
.qemu(vmid)
|
||||
.delete(
|
||||
node=node,
|
||||
vmid=vmid,
|
||||
)
|
||||
)
|
||||
logger.info("VM %s was deleted successfully!", vmid)
|
||||
return upid
|
||||
|
||||
|
||||
def clone_template(
|
||||
@ -107,17 +113,27 @@ def get_vm_ip(
|
||||
node: str,
|
||||
vmid: int,
|
||||
) -> str:
|
||||
res: dict = (
|
||||
proxmox.nodes(node).qemu(vmid).agent("network-get-interfaces").get()
|
||||
) # pyright: ignore
|
||||
done = False
|
||||
vm_ip_address = None
|
||||
for net in res["result"]:
|
||||
if net["name"] == "eth0" or net["name"] == "ens19":
|
||||
for ip in net["ip-addresses"]:
|
||||
if ip["ip-address-type"] == "ipv4":
|
||||
vm_ip_address = ip["ip-address"]
|
||||
while not done:
|
||||
try:
|
||||
res: dict = (
|
||||
proxmox.nodes(node).qemu(vmid).agent("network-get-interfaces").get()
|
||||
) # pyright: ignore
|
||||
for net in res["result"]:
|
||||
if net["name"] == "eth0" or net["name"] == "ens19":
|
||||
for ip in net["ip-addresses"]:
|
||||
if ip["ip-address-type"] == "ipv4":
|
||||
vm_ip_address = ip["ip-address"]
|
||||
done = True
|
||||
except KeyError:
|
||||
time.sleep(1)
|
||||
except Exception as e:
|
||||
raise RuntimeError(
|
||||
f"Could not get the ip address of VM {vmid} on node {node}"
|
||||
) from e
|
||||
|
||||
if vm_ip_address is None:
|
||||
raise ValueError(f"Could not get the ip address of VM {vmid} on node {node}")
|
||||
raise RuntimeError(f"Could not get the ip address of VM {vmid} on node {node}")
|
||||
|
||||
return vm_ip_address
|
||||
|
111
main.py
Normal file → Executable file
111
main.py
Normal file → Executable file
@ -1,15 +1,15 @@
|
||||
#!/usr/bin/python3
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import argparse
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
from time import sleep
|
||||
from typing import Callable
|
||||
import time
|
||||
|
||||
import urllib3
|
||||
import yaml
|
||||
from dotenv import load_dotenv
|
||||
from proxmoxer import ProxmoxAPI
|
||||
from proxmoxer import ProxmoxAPI, ResourceException
|
||||
from proxmoxer.tools import Tasks
|
||||
|
||||
from functions import clone_template, delete_vm, get_vm_ip
|
||||
|
||||
@ -28,15 +28,19 @@ PROXMOX_USER_FULL: str | None = os.environ.get("PROXMOX_USER_FULL")
|
||||
PROXMOX_PASSWORD: str | None = os.environ.get("PROXMOX_PASSWORD")
|
||||
|
||||
|
||||
def wait_status(
|
||||
funcs: list[Callable[[], dict[str, str]]], status: str, sleep_time: float = 60
|
||||
) -> None:
|
||||
statuses = [False] * len(funcs)
|
||||
while not all(statuses):
|
||||
logger.debug(statuses)
|
||||
sleep(sleep_time)
|
||||
for i in range(len(funcs)):
|
||||
statuses[i] = funcs[i]()["status"] == status
|
||||
def tasks_wait_completion(proxmox: ProxmoxAPI, upids: list[str]) -> None:
|
||||
for upid in upids:
|
||||
Tasks.blocking_status(proxmox, upid)
|
||||
|
||||
|
||||
def parse_args() -> argparse.Namespace:
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument(
|
||||
"branch",
|
||||
help="used to pick the appropriate VM template to clone",
|
||||
choices=["sisyphus", "c10f2", "p10"],
|
||||
)
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
def main() -> None:
|
||||
@ -45,6 +49,8 @@ def main() -> None:
|
||||
assert PROXMOX_USER_FULL is not None
|
||||
assert PROXMOX_PASSWORD is not None
|
||||
|
||||
args = parse_args()
|
||||
|
||||
proxmox = ProxmoxAPI(
|
||||
PROXMOX_HOST,
|
||||
user=PROXMOX_USER_FULL,
|
||||
@ -57,10 +63,7 @@ def main() -> None:
|
||||
# node = min(nodes, key=lambda node: node['disk'])['node']
|
||||
node: str = "pve05"
|
||||
|
||||
assert len(sys.argv) >= 2
|
||||
branch: str = sys.argv[1]
|
||||
|
||||
match branch:
|
||||
match args.branch:
|
||||
case "sisyphus":
|
||||
template_id: int = 374
|
||||
case "p10":
|
||||
@ -92,15 +95,24 @@ def main() -> None:
|
||||
|
||||
if delete != "0":
|
||||
logger.info("Stopping VMs %s...", vm_ids)
|
||||
proxmox.nodes(node).qemu(vm_ids["master"]).status.stop.post()
|
||||
proxmox.nodes(node).qemu(vm_ids["worker1"]).status.stop.post()
|
||||
proxmox.nodes(node).qemu(vm_ids["worker2"]).status.stop.post()
|
||||
sleep(15)
|
||||
tasks_wait_completion(
|
||||
proxmox,
|
||||
[
|
||||
proxmox.nodes(node).qemu(vm_ids["master"]).status.stop.post(),
|
||||
proxmox.nodes(node).qemu(vm_ids["worker1"]).status.stop.post(),
|
||||
proxmox.nodes(node).qemu(vm_ids["worker2"]).status.stop.post(),
|
||||
],
|
||||
)
|
||||
|
||||
logger.info("Deleting VMs %s...", vm_ids)
|
||||
delete_vm(proxmox, node, vm_ids["master"])
|
||||
delete_vm(proxmox, node, vm_ids["worker1"])
|
||||
delete_vm(proxmox, node, vm_ids["worker2"])
|
||||
sleep(15)
|
||||
tasks_wait_completion(
|
||||
proxmox,
|
||||
[
|
||||
delete_vm(proxmox, node, vm_ids["master"]),
|
||||
delete_vm(proxmox, node, vm_ids["worker1"]),
|
||||
delete_vm(proxmox, node, vm_ids["worker2"]),
|
||||
],
|
||||
)
|
||||
|
||||
vm_id_master, upid_master = clone_template(
|
||||
proxmox,
|
||||
@ -130,35 +142,42 @@ def main() -> None:
|
||||
assert vm_id_worker2 == vm_ids["worker2"]
|
||||
|
||||
logger.info("Waiting for cloning to complete...")
|
||||
wait_status(
|
||||
tasks_wait_completion(
|
||||
proxmox,
|
||||
[
|
||||
proxmox.nodes(node).tasks(upid_master).status.get,
|
||||
proxmox.nodes(node).tasks(upid_worker1).status.get,
|
||||
proxmox.nodes(node).tasks(upid_worker2).status.get,
|
||||
], # pyright: ignore
|
||||
"stopped",
|
||||
sleep_time=40,
|
||||
upid_master,
|
||||
upid_worker1,
|
||||
upid_worker2,
|
||||
],
|
||||
)
|
||||
|
||||
logger.info("Cloning completed!")
|
||||
|
||||
logger.info("Starting VMs...")
|
||||
proxmox.nodes(node).qemu(vm_ids["master"]).status.start.post()
|
||||
proxmox.nodes(node).qemu(vm_ids["worker1"]).status.start.post()
|
||||
proxmox.nodes(node).qemu(vm_ids["worker2"]).status.start.post()
|
||||
wait_status(
|
||||
tasks_wait_completion(
|
||||
proxmox,
|
||||
[
|
||||
proxmox.nodes(node).qemu(vm_ids["master"]).status.current.get,
|
||||
proxmox.nodes(node).qemu(vm_ids["worker1"]).status.current.get,
|
||||
proxmox.nodes(node).qemu(vm_ids["worker2"]).status.current.get,
|
||||
], # pyright: ignore
|
||||
"running",
|
||||
sleep_time=10,
|
||||
proxmox.nodes(node).qemu(vm_ids["master"]).status.start.post(),
|
||||
proxmox.nodes(node).qemu(vm_ids["worker1"]).status.start.post(),
|
||||
proxmox.nodes(node).qemu(vm_ids["worker2"]).status.start.post(),
|
||||
],
|
||||
)
|
||||
|
||||
sleep(40)
|
||||
logger.info("VMs are running!")
|
||||
|
||||
logger.info("Waiting for QEMU guest agent to start")
|
||||
done = False
|
||||
while not done:
|
||||
try:
|
||||
_ = proxmox.nodes(node).qemu(vm_ids["master"]).agent.ping.post()
|
||||
_ = proxmox.nodes(node).qemu(vm_ids["worker1"]).agent.ping.post()
|
||||
_ = proxmox.nodes(node).qemu(vm_ids["worker2"]).agent.ping.post()
|
||||
except ResourceException:
|
||||
time.sleep(1)
|
||||
except Exception as e:
|
||||
raise RuntimeError("Failed to ping QEMU agent") from e
|
||||
else:
|
||||
done = True
|
||||
logger.info("QEMU guest agent is running")
|
||||
|
||||
vm_ip_master: str = get_vm_ip(proxmox, node, vm_ids["master"])
|
||||
vm_ip_worker1: str = get_vm_ip(proxmox, node, vm_ids["worker1"])
|
||||
vm_ip_worker2: str = get_vm_ip(proxmox, node, vm_ids["worker2"])
|
||||
|
Loading…
x
Reference in New Issue
Block a user