def rexec(self, command, **kwargs): """Remote execute a command on the windows VM The following optional flags are allowed: * fatal: If True, a FatalError is thrown if the command fails * debug: If True, WinEXE is executed in the highest debug level * uninstall: If True, the winexesvc.exe service will be uninstalled after the execution of the command. """ fatal = kwargs['fatal'] if 'fatal' in kwargs else True debug = kwargs['debug'] if 'debug' in kwargs else False uninstall = kwargs['uninstall'] if 'uninstall' in kwargs else False winexe = WinEXE(self.admin.name, 'localhost', password=self.password) winexe.no_pass() if debug: winexe.debug(9) if uninstall: winexe.uninstall() try: (stdout, stderr, rc) = winexe.run(command) except WinexeTimeout: raise FatalError("Command: `%s' timeout out." % command) if rc != 0 and fatal: log = tempfile.NamedTemporaryFile(delete=False) try: log.file.write("STDOUT:\n%s\n" % stdout) log.file.write("STDERR:\n%s\n" % stderr) finally: fname = log.name log.close() raise FatalError("Command: `%s' failed (rc=%d). See: %s" % (command, rc, fname)) return (stdout, stderr, rc)
def do_sysprep(self): """Prepare system for image creation.""" self.out.info('Preparing system for image creation:') # Check if winexe is installed if not WinEXE.is_installed(): raise FatalError( "Winexe not found! In order to be able to customize a Windows " "image you need to have Winexe installed.") if self.sysprepped: raise FatalError( "Microsoft's System Preparation Tool has ran on the media. " "Further image customization is not possible.") if len(self.virtio_state['viostor']) == 0: raise FatalError( "The media has no VirtIO SCSI controller driver installed. " "Further image customization is not possible.") if len(self.virtio_state['netkvm']) == 0: raise FatalError( "The media has no VirtIO Ethernet Adapter driver installed. " "Further image customization is not possible.") timeout = self.sysprep_params['boot_timeout'].value shutdown_timeout = self.sysprep_params['shutdown_timeout'].value self.out.info("Preparing media for boot ...", False) with self.mount(readonly=False, silent=True): if not self.registry.reset_account(self.vm.admin.rid): self._add_cleanup('sysprep', self.registry.reset_account, self.vm.admin.rid, False) old = self.registry.update_uac(0) if old != 0: self._add_cleanup('sysprep', self.registry.update_uac, old) old = self.registry.update_uac_remote_setting(1) if old != 1: self._add_cleanup('sysprep', self.registry.update_uac_remote_setting, old) def if_not_sysprepped(task, *args): """Only perform this if the image is not sysprepped""" if not self.sysprepped: task(*args) # The next 2 registry values get completely removed by Microsoft # Sysprep. They should not be reverted if Sysprep gets executed. old = self.registry.update_noautoupdate(1) if old != 1: self._add_cleanup('sysprep', if_not_sysprepped, self.registry.update_noautoupdate, old) old = self.registry.update_auoptions(1) if old != 1: self._add_cleanup('sysprep', if_not_sysprepped, self.registry.update_auoptions, old) # disable the firewalls self._add_cleanup('sysprep', self.registry.update_firewalls, *self.registry.update_firewalls(0, 0, 0)) v_val = self.registry.reset_passwd(self.vm.admin.rid) self._add_boot_scripts() # Delete the pagefile. It will be recreated when the system boots try: pagefile = "%s/pagefile.sys" % self.systemroot self.image.g.rm_rf(self.image.g.case_sensitive_path(pagefile)) except RuntimeError: pass self.out.success('done') self.image.disable_guestfs() booted = False try: self.out.info("Starting windows VM ...", False) self.vm.start() try: self.out.success("started (console on VNC display: %d)" % self.vm.display) self.out.info("Waiting for OS to boot ...", False) if not self.vm.wait_on_serial(timeout): raise FatalError("Windows VM booting timed out!") self.out.success('done') booted = True # Since the password is reset when logging in, sleep a little # bit before checking the connectivity, to avoid race # conditions time.sleep(5) self.out.info("Checking connectivity to the VM ...", False) self._check_connectivity() # self.out.success('done') # self.out.info("Disabling automatic logon ...", False) self._disable_autologon() self.out.success('done') self._exec_sysprep_tasks() self.out.info("Waiting for windows to shut down ...", False) (_, stderr, rc) = self.vm.wait(shutdown_timeout) if rc != 0 or "terminating on signal" in stderr: raise FatalError("Windows VM died unexpectedly!\n\n" "(rc=%d)\n%s" % (rc, stderr)) self.out.success("done") finally: # if the VM is not already dead here, a Fatal Error will have # already been raised. There is no reason to make the command # fatal. self.vm.stop(shutdown_timeout if booted else 1, fatal=False) finally: self.image.enable_guestfs() self.out.info("Reverting media boot preparations ...", False) with self.mount(readonly=False, silent=True, fatal=False): if not self.ismounted: self.out.warn("The boot changes cannot be reverted. " "The snapshot may be in a corrupted state.") else: if not self.sysprepped: # Reset the old password self.registry.reset_passwd(self.vm.admin.rid, v_val) self._cleanup('sysprep') self.out.success("done") self.image.shrink(silent=True)