def test_vm_create_and_is_running(self, config, test_vm): # initial cleanup destroy_vm(test_vm.vm_name) assert test_vm.is_running is False logging.info("testing vm create with pause=False") test_vm.create(pause=False) assert get_vm_state(test_vm.vm_name) != "p" assert test_vm.is_running is True logging.info("testing vm create for a created VM") with pytest.raises(Exception): test_vm.create(pause=True) # second run destroy_vm(test_vm.vm_name) logging.info("testing vm create with pause=True") test_vm.create(pause=True) assert get_vm_state(test_vm.vm_name) == "p" # destroy the vm destroy_vm(test_vm.vm_name) logging.info("testing vm create with non-existant file") with pytest.raises(Exception): new_vm = VirtualMachine(None, 0, "test-hvm64-example", "/tmp/unexitant-file") new_vm.create() logging.info("testing vm create with empty file") with tempfile.NamedTemporaryFile() as tempf: with pytest.raises(Exception): new_vm = VirtualMachine(None, 0, "test-hvm64-example", tempf.name) new_vm.create() # check if vm is shutdown with pytest.raises(Exception): get_vm_state(test_vm.name)
def install( vcpus, memory, storage_backend, disk_size, iso_path, zfs_tank_name, lvm_volume_group, unattended_xml, ): if not check_root(): return if storage_backend == "lvm" and lvm_volume_group is None: raise Exception("lvm storage backend requires --lvm-volume-group") if storage_backend == "zfs" and zfs_tank_name is None: raise Exception("zfs storage backend requires --zfs-tank-name") if not sanity_check(): logging.error("Sanity check failed.") return stop_all_drakruns() logging.info("Performing installation...") if vcpus < 1: logging.error("Your VM must have at least 1 vCPU.") return if memory < 512: logging.error("Your VM must have at least 512 MB RAM.") return if memory < 1536: logging.warning( "Using less than 1.5 GB RAM per VM is not recommended for any supported system." ) if unattended_xml: logging.info("Baking unattended.iso for automated installation") with tempfile.TemporaryDirectory() as tmpdir: tmp_xml_path = os.path.join(tmpdir, "autounattend.xml") with open(tmp_xml_path, "wb") as fw: with open(unattended_xml, "rb") as fr: fw.write(fr.read()) try: subprocess.check_output( [ "genisoimage", "-o", os.path.join(VOLUME_DIR, "unattended.iso"), "-J", "-r", tmp_xml_path, ], stderr=subprocess.STDOUT, ) except subprocess.CalledProcessError: logging.exception("Failed to generate unattended.iso.") sha256_hash = hashlib.sha256() logging.info("Calculating hash of iso") iso_file_size = os.stat(iso_path).st_size block_size = 128 * 1024 with tqdm(total=iso_file_size, unit_scale=True) as pbar: with open(iso_path, "rb") as f: for byte_block in iter(lambda: f.read(block_size), b""): pbar.update(block_size) sha256_hash.update(byte_block) iso_sha256 = sha256_hash.hexdigest() install_info = InstallInfo( vcpus=vcpus, memory=memory, storage_backend=storage_backend, disk_size=disk_size, iso_path=os.path.abspath(iso_path), zfs_tank_name=zfs_tank_name, lvm_volume_group=lvm_volume_group, enable_unattended=unattended_xml is not None, iso_sha256=iso_sha256, ) install_info.save() backend = get_storage_backend(install_info) vm0 = VirtualMachine(backend, 0) vm0.destroy() generate_vm_conf(install_info, 0) backend.initialize_vm0_volume(disk_size) try: subprocess.check_output("brctl show", shell=True) except subprocess.CalledProcessError: logging.exception( "Failed to execute brctl show. Make sure you have bridge-utils installed." ) return net_enable = conf["drakrun"].getboolean("net_enable", fallback=False) out_interface = conf["drakrun"].get("out_interface", "") dns_server = conf["drakrun"].get("dns_server", "") setup_vm_network( vm_id=0, net_enable=net_enable, out_interface=out_interface, dns_server=dns_server, ) if net_enable: start_dnsmasq(vm_id=0, dns_server=dns_server, background=True) cfg_path = os.path.join(VM_CONFIG_DIR, "vm-0.cfg") vm0.create() logging.info("-" * 80) logging.info("Initial VM setup is complete and the vm-0 was launched.") logging.info( "Please now VNC to the port 5900 on this machine to perform Windows installation." ) logging.info( "After you have installed Windows and booted it to the desktop, please execute:" ) logging.info("# draksetup postinstall") with open(cfg_path, "r") as f: data = f.read() m = re.search(r"vncpasswd[ ]*=(.*)", data) if m: passwd = m.group(1).strip() if passwd[0] == '"' and passwd[-1] == '"': passwd = passwd[1:-1] logging.info("Your configured VNC password is:") logging.info(passwd) logging.info( "Please note that on some machines, system installer may boot for up to 10 minutes" ) logging.info( "and may look unresponsive during the process. Please be patient.") logging.info("-" * 80)
def perform_xtf(): logging.info("Testing your Xen installation...") module_dir = os.path.dirname(os.path.realpath(__file__)) cfg_path = os.path.join(module_dir, "tools", "test-hvm64-example.cfg") firmware_path = os.path.join(module_dir, "tools", "test-hvm64-example") with open(cfg_path, "r") as f: test_cfg = (f.read().replace("{{ FIRMWARE_PATH }}", firmware_path).encode("utf-8")) with tempfile.NamedTemporaryFile() as tmpf: tmpf.write(test_cfg) tmpf.flush() test_hvm64 = VirtualMachine(None, None, "test-hvm64-example", tmpf.name) logging.info("Checking if the test domain already exists...") test_hvm64.destroy() logging.info("Creating new test domain...") test_hvm64.create(pause=True, timeout=30) module_dir = os.path.dirname(os.path.realpath(__file__)) test_altp2m_tool = os.path.join(module_dir, "tools", "test-altp2m") logging.info("Testing altp2m feature...") try: subprocess.run( [test_altp2m_tool, "test-hvm64-example"], stderr=subprocess.STDOUT, check=True, ) except subprocess.CalledProcessError as e: output = e.output.decode("utf-8", "replace") logging.error( f"Failed to enable altp2m on domain. Your hardware might not support Extended Page Tables. Logs:\n{output}" ) test_hvm64.destroy() return False logging.info("Performing simple XTF test...") p = subprocess.Popen( ["xl", "console", "test-hvm64-example"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, ) test_hvm64.unpause(timeout=30) stdout_b, _ = p.communicate(timeout=10) stdout_text = stdout_b.decode("utf-8") stdout = [line.strip() for line in stdout_text.split("\n")] for line in stdout: if line == "Test result: SUCCESS": logging.info( "All tests passed. Your Xen installation seems to work properly." ) return True logging.error( f"Preflight check with Xen Test Framework doesn't pass. Your hardware might not support VT-x. Logs: \n{stdout_text}" ) return False