Files
cloud-monitor/oci-arm-monitor.py
T
2026-02-15 00:33:42 +08:00

85 lines
3.0 KiB
Python

#!/usr/bin/env python3
import oci
import time
import smtplib
import sys
from email.mime.text import MIMEText
import os
from dotenv import load_dotenv
load_dotenv(os.path.join(os.path.dirname(__file__), ".env"))
COMPARTMENT_ID = os.environ["COMPARTMENT_ID"]
AVAILABILITY_DOMAIN = os.environ["AVAILABILITY_DOMAIN"]
SUBNET_ID = os.environ["SUBNET_ID"]
IMAGE_ID = os.environ["IMAGE_ID"]
SSH_KEY = os.environ["SSH_KEY"]
DISPLAY_NAME = os.environ.get("DISPLAY_NAME", "free-arm-instance")
SHAPE = "VM.Standard.A1.Flex"
OCPUS = 4
MEMORY_GB = 24
INTERVAL = 60
WEEKLY_REPORT_INTERVAL = 7 * 24 * 3600
EMAIL_TO = os.environ["EMAIL_TO"]
EMAIL_FROM = os.environ["EMAIL_FROM"]
EMAIL_APP_PASSWORD = os.environ["EMAIL_APP_PASSWORD"]
def send_email(subject, body):
msg = MIMEText(body)
msg["Subject"] = subject
msg["From"] = EMAIL_FROM
msg["To"] = EMAIL_TO
with smtplib.SMTP_SSL("smtp.gmail.com", 465) as s:
s.login(EMAIL_FROM, EMAIL_APP_PASSWORD)
s.send_message(msg)
config = oci.config.from_file()
compute = oci.core.ComputeClient(config)
print("Starting ARM instance monitor...", flush=True)
start_time = time.time()
last_report = start_time
attempts = 0
while True:
try:
resp = compute.launch_instance(
oci.core.models.LaunchInstanceDetails(
compartment_id=COMPARTMENT_ID,
availability_domain=AVAILABILITY_DOMAIN,
shape=SHAPE,
shape_config=oci.core.models.LaunchInstanceShapeConfigDetails(ocpus=OCPUS, memory_in_gbs=MEMORY_GB),
image_id=IMAGE_ID,
subnet_id=SUBNET_ID,
display_name=DISPLAY_NAME,
metadata={"ssh_authorized_keys": SSH_KEY},
)
)
instance_id = resp.data.id
msg = f"ARM instance created!\nID: {instance_id}"
print(msg, flush=True)
send_email("OCI ARM Instance Created!", msg)
sys.exit(0)
except oci.exceptions.ServiceError as e:
if "capacity" in str(e.message).lower() or "host" in str(e.message).lower():
attempts += 1
print(f"{time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime(time.time() + 8*3600))} No capacity. Retrying in {INTERVAL}s...", flush=True)
else:
print(f"Unexpected error: {e.message}", flush=True)
send_email("OCI ARM Monitor Error", str(e.message))
sys.exit(1)
now = time.time()
if now - last_report >= WEEKLY_REPORT_INTERVAL:
uptime_days = int((now - start_time) / 86400)
send_email(
"OCI ARM Monitor - Weekly Report",
f"Status: Still running, no capacity available.\n"
f"Uptime: {uptime_days} days\n"
f"Attempts since last report: {attempts}\n"
f"Shape: {SHAPE} ({OCPUS} OCPUs, {MEMORY_GB}GB RAM)",
)
print(f"{time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime(now + 8*3600))} Weekly report sent.", flush=True)
last_report = now
attempts = 0
time.sleep(INTERVAL)