def snapshot_import(name, bucket, full, zpool): local_install = InstallInfo.try_load() if local_install is not None: click.confirm( "Detected local snapshot. It will be REMOVED. Continue?", abort=True ) mc = get_minio_client(conf) if not mc.bucket_exists(bucket): logging.error("Bucket %s doesn't exist", bucket) return ensure_dirs() try: if full: logging.warning( "Importing full snapshot. This may not work if hardware is different" ) do_import_full(mc, name, bucket, zpool) else: do_import_minimal(mc, name, bucket, zpool) # This could probably use some refactoring # We're duplicating quite a lot of code from install function install_info = InstallInfo.load() generate_vm_conf(install_info, 0) backend = get_storage_backend(install_info) backend.rollback_vm_storage(0) net_enable = int(conf["drakrun"].get("net_enable", "0")) 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") try: subprocess.run(["xl" "create", cfg_path], check=True) except subprocess.CalledProcessError: logging.exception("Failed to launch VM vm-0") return logging.info("Minimal snapshots require postinstall to work correctly") logging.info( "Please VNC to the port 5900 to ensure the OS booted correctly" ) logging.info("After that, execute this command to finish the setup") logging.info("# draksetup postinstall") except NoSuchKey: logging.error("Import failed. Missing files in bucket.")
def create_missing_profiles(): """ Creates usermode profiles by restoring vm-1 and extracting the DLLs. Assumes that injector is configured properly, i.e. kernel and runtime profiles exist and that vm-1 is free to use. """ # Prepare injector with open(os.path.join(PROFILE_DIR, "runtime.json"), "r") as runtime_f: runtime_info = RuntimeInfo.load(runtime_f) kernel_profile = os.path.join(PROFILE_DIR, "kernel.json") injector = Injector("vm-1", runtime_info, kernel_profile) # restore vm-1 out_interface = conf["drakrun"].get("out_interface", "") dns_server = conf["drakrun"].get("dns_server", "") install_info = InstallInfo.load() backend = get_storage_backend(install_info) generate_vm_conf(install_info, 1) setup_vm_network(vm_id=1, net_enable=False, out_interface=out_interface, dns_server=dns_server) vm = VirtualMachine(backend, 1) vm.restore() # Ensure that all declared usermode profiles exist # This is important when upgrade defines new entries in dll_file_list and compulsory_dll_file_list for profile in compulsory_dll_file_list: if not profiles_exist(profile.dest): create_rekall_profile(injector, profile, True) for profile in dll_file_list: if not profiles_exist(profile.dest): try: create_rekall_profile(injector, profile) except Exception: log.exception( "Unexpected exception from create_rekall_profile!") build_os_info(APISCOUT_PROFILE_DIR, vmi_win_guid(vm.vm_name), backend) dll_basename_list = [dll.dest for dll in dll_file_list] static_apiscout_profile = build_static_apiscout_profile( APISCOUT_PROFILE_DIR, dll_basename_list) with open( Path(APISCOUT_PROFILE_DIR) / "static_apiscout_profile.json", "w") as f: json.dump(static_apiscout_profile, f) vm.destroy() delete_vm_network(vm_id=1, net_enable=False, out_interface=out_interface, dns_server=dns_server)
def init_drakrun(self): generate_vm_conf(self.install_info, self.instance_id) if not self.backend.minio.bucket_exists("drakrun"): self.backend.minio.make_bucket(bucket_name="drakrun") out_interface = self.config.config["drakrun"].get("out_interface", "") dns_server = self.config.config["drakrun"].get("dns_server", "") setup_vm_network(self.instance_id, self.net_enable, out_interface, dns_server)
def init_drakrun(self): generate_vm_conf(self.install_info, self.instance_id) if not self.backend.minio.bucket_exists('drakrun'): self.backend.minio.make_bucket(bucket_name='drakrun') out_interface = self.config.config['drakrun'].get('out_interface', '') dns_server = self.config.config['drakrun'].get('dns_server', '') setup_vm_network(self.instance_id, self.net_enable, out_interface, dns_server)
def init_drakrun(self): generate_vm_conf(self.install_info, self.instance_id) if not self.backend.minio.bucket_exists("drakrun"): self.backend.minio.make_bucket(bucket_name="drakrun") out_interface = self.config.config["drakrun"].get("out_interface", "") dns_server = self.config.config["drakrun"].get("dns_server", "") setup_vm_network(self.instance_id, self.net_enable, out_interface, dns_server) self.log.info("Calculating snapshot hash...") self.snapshot_sha256 = file_sha256(os.path.join(VOLUME_DIR, "snapshot.sav"))
def create_missing_profiles(): """ Creates usermode profiles by restoring vm-1 and extracting the DLLs. Assumes that injector is configured properly, i.e. kernel and runtime profiles exist and that vm-1 is free to use. """ # Prepare injector with open(os.path.join(PROFILE_DIR, "runtime.json"), "r") as runtime_f: runtime_info = RuntimeInfo.load(runtime_f) kernel_profile = os.path.join(PROFILE_DIR, "kernel.json") injector = Injector("vm-1", runtime_info, kernel_profile) # restore vm-1 out_interface = conf["drakrun"].get("out_interface", "") dns_server = conf["drakrun"].get("dns_server", "") install_info = InstallInfo.load() backend = get_storage_backend(install_info) generate_vm_conf(install_info, 1) setup_vm_network(vm_id=1, net_enable=False, out_interface=out_interface, dns_server=dns_server) vm = VirtualMachine(backend, 1) vm.restore() # Ensure that all declared usermode profiles exist # This is important when upgrade defines new entries in dll_file_list and compulsory_dll_file_list for profile in compulsory_dll_file_list: if not profile_exists(profile): create_rekall_profile(injector, profile, True) for profile in dll_file_list: if not profile_exists(profile): try: create_rekall_profile(injector, profile) except Exception: # silence per-dll errors pass vm.destroy() delete_vm_network(vm_id=1, net_enable=False, out_interface=out_interface, dns_server=dns_server)
def __init__(self, vm_id: int, dns: str): install_info = InstallInfo.load() backend = get_storage_backend(install_info) generate_vm_conf(install_info, vm_id) self.vm = VirtualMachine(backend, vm_id) with open(Path(PROFILE_DIR) / "runtime.json", 'r') as f: self.runtime_info = RuntimeInfo.load(f) self.desktop = WinPath(r"%USERPROFILE%") / "Desktop" self.kernel_profile = Path(PROFILE_DIR) / "kernel.json" self.injector = Injector( self.vm.vm_name, self.runtime_info, self.kernel_profile, ) setup_vm_network(vm_id, True, find_default_interface(), dns)
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() try: subprocess.check_output('xl uptime vm-0', shell=True, stderr=subprocess.STDOUT) except subprocess.CalledProcessError: pass else: logging.info('Detected that vm-0 is already running, stopping it.') subprocess.run('xl destroy vm-0', shell=True, check=True) generate_vm_conf(install_info, 0) backend = get_storage_backend(install_info) 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") try: subprocess.run('xl create {}'.format(shlex.quote(cfg_path)), shell=True, check=True) except subprocess.CalledProcessError: logging.exception("Failed to launch VM vm-0") return 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 install(storage_backend, disk_size, iso_path, zfs_tank_name, unattended_xml): logging.info("Ensuring that drakrun@* services are stopped...") subprocess.check_output('systemctl stop \'drakrun@*\'', shell=True, stderr=subprocess.STDOUT) logging.info("Performing installation...") 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() with open(iso_path, "rb") as f: for byte_block in iter(lambda: f.read(4096), b""): sha256_hash.update(byte_block) iso_sha256 = sha256_hash.hexdigest() install_info = InstallInfo(storage_backend=storage_backend, disk_size=disk_size, iso_path=os.path.abspath(iso_path), zfs_tank_name=zfs_tank_name, enable_unattended=unattended_xml is not None, iso_sha256=iso_sha256) install_info.save() logging.info("Checking xen-detect...") proc = subprocess.run('xen-detect -N', shell=True) if proc.returncode != 1: logging.error( 'It looks like the system is not running on Xen. Please reboot your machine into Xen hypervisor.' ) return logging.info("Testing if xl tool is sane...") try: subprocess.check_output('xl info', shell=True, stderr=subprocess.STDOUT) except subprocess.CalledProcessError: logging.exception("Failed to test xl command.") return try: subprocess.check_output('xl uptime vm-0', shell=True, stderr=subprocess.STDOUT) except subprocess.CalledProcessError: pass else: logging.info('Detected that vm-0 is already running, stopping it.') subprocess.run('xl destroy vm-0', shell=True, check=True) generate_vm_conf(install_info, 0) backend = get_storage_backend(install_info) 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 = int(conf['drakrun'].get('net_enable', '0')) 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") try: subprocess.run('xl create {}'.format(shlex.quote(cfg_path)), shell=True, check=True) except subprocess.CalledProcessError: logging.exception("Failed to launch VM vm-0") return 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)