#!/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)