import os import platform import random import re import threading from filelock import FileLock import uuid import zipfile from time import sleep import shutil import psutil import subprocess import requests from tqdm import tqdm import docker import logging from desktop_env.providers.base import VMManager logger = logging.getLogger("desktopenv.providers.vmware.VMwareVMManager") logger.setLevel(logging.INFO) MAX_RETRY_TIMES = 10 RETRY_INTERVAL = 5 UBUNTU_X86_URL = "https://huggingface.co/datasets/xlangai/ubuntu_osworld/resolve/main/Ubuntu.qcow2" VMS_DIR = "./docker_vm_data" # Determine the platform and CPU architecture to decide the correct VM image to download # if platform.system() == 'Darwin': # macOS # # if os.uname().machine == 'arm64': # Apple Silicon # URL = UBUNTU_ARM_URL # # else: # # url = UBUNTU_X86_URL # elif platform.machine().lower() in ['amd64', 'x86_64']: # URL = UBUNTU_X86_URL # else: # raise Exception("Unsupported platform or architecture") URL = UBUNTU_X86_URL DOWNLOADED_FILE_NAME = URL.split('/')[-1] if platform.system() == 'Windows': docker_path = r"C:\Program Files\Docker\Docker" os.environ["PATH"] += os.pathsep + docker_path def _download_vm(vms_dir: str): # Download the virtual machine image logger.info("Downloading the virtual machine image...") downloaded_size = 0 URL = UBUNTU_X86_URL DOWNLOADED_FILE_NAME = URL.split('/')[-1] downloaded_file_name = DOWNLOADED_FILE_NAME os.makedirs(vms_dir, exist_ok=True) while True: downloaded_file_path = os.path.join(vms_dir, downloaded_file_name) headers = {} if os.path.exists(downloaded_file_path): downloaded_size = os.path.getsize(downloaded_file_path) headers["Range"] = f"bytes={downloaded_size}-" with requests.get(URL, headers=headers, stream=True) as response: if response.status_code == 416: # This means the range was not satisfiable, possibly the file was fully downloaded logger.info("Fully downloaded or the file size changed.") break response.raise_for_status() total_size = int(response.headers.get('content-length', 0)) with open(downloaded_file_path, "ab") as file, tqdm( desc="Progress", total=total_size, unit='iB', unit_scale=True, unit_divisor=1024, initial=downloaded_size, ascii=True ) as progress_bar: try: for data in response.iter_content(chunk_size=1024): size = file.write(data) progress_bar.update(size) except (requests.exceptions.RequestException, IOError) as e: logger.error(f"Download error: {e}") sleep(RETRY_INTERVAL) logger.error("Retrying...") else: logger.info("Download succeeds.") break # Download completed successfully class DockerVMManager(VMManager): def __init__(self, registry_path=""): pass def add_vm(self, vm_path): pass def check_and_clean(self): pass def delete_vm(self, vm_path): pass def initialize_registry(self): pass def list_free_vms(self): return os.path.join(VMS_DIR, DOWNLOADED_FILE_NAME) def occupy_vm(self, vm_path): pass def get_vm_path(self, os_type, region): if not os.path.exists(os.path.join(VMS_DIR, DOWNLOADED_FILE_NAME)): _download_vm(VMS_DIR) return os.path.join(VMS_DIR, DOWNLOADED_FILE_NAME)