def burn_kano_os(path, disk, size, return_queue, report_progress_ui): cmd = 'gzip -dc {} | dd of={} bs=4M'.format(path, disk) process = subprocess.Popen(cmd, shell=True, stderr=subprocess.PIPE) failed = False unparsed_line = '' # as long as Popen is running, read it's stderr line by line # each time a USR1 signal is sent to dd, it outputs 3 lines # and we are only interested in the last one i.e. 'x bytes written in y seconds' for line in iter(process.stderr.readline, ''): if 'bytes' in line: try: parts = line.split() written_bytes = float(parts[0]) progress = int(written_bytes / size * 100) speed = float(parts[7]) eta = calculate_eta(written_bytes, size, speed * BYTES_IN_MEGABYTE) report_progress_ui( progress, 'speed {0:.2f} MB/s eta {1:s} completed {2:d}%'.format( speed, eta, progress)) except: unparsed_line = line # watch out for an error output from dd if 'error' in line.lower() or 'invalid' in line.lower(): debugger('[ERROR] ' + line) failed = True # make sure the progress bar is filled and show an appropriate message # if we failed, the UI will immediately show the error screen report_progress_ui(100, 'burning finished successfully') # making sure we log anything nasty that has happened if unparsed_line: debugger('[ERROR] Failed parsing the line: ' + unparsed_line) if failed: debugger('[ERROR] Burning Kano image failed') return_queue.put(False) else: debugger('Burning successfully finished') return_queue.put(True)
def burn_kano_os(path, disk, size, return_queue, report_progress_ui): cmd = 'gzip -dc {} | dd of={} bs=4M'.format(path, disk) process = subprocess.Popen(cmd, shell=True, env=cmd_env, stderr=subprocess.PIPE) failed = False unparsed_line = '' # as long as Popen is running, read it's stderr line by line # each time a USR1 signal is sent to dd, it outputs 3 lines # and we are only interested in the last one i.e. 'x bytes written in y seconds' for line in iter(process.stderr.readline, ''): if 'bytes' in line: try: parts = line.split() written_bytes = float(parts[0]) progress = int(written_bytes / size * 100) speed = float(parts[7]) eta = calculate_eta(written_bytes, size, speed * BYTES_IN_MEGABYTE) report_progress_ui(progress, 'speed {0:.2f} MB/s eta {1:s} completed {2:d}%' .format(speed, eta, progress)) except: unparsed_line = line # watch out for an error output from dd if 'error' in line.lower() or 'invalid' in line.lower(): debugger('[ERROR] ' + line) failed = True # make sure the progress bar is filled and show an appropriate message # if we failed, the UI will immediately show the error screen report_progress_ui(100, 'burning finished successfully') # making sure we log anything nasty that has happened if unparsed_line: debugger('[ERROR] Failed parsing the line: ' + unparsed_line) if failed: debugger('[ERROR] Burning Kano image failed') return_queue.put(False) else: debugger('Burning successfully finished') return_queue.put(True)
def burn_worker(stderr, size, report_progress_ui): global burn_success failed = False unparsed_line = '' # initialise UI timed reporting previous_timestamp = time.time() # as long as Popen is running, read it's stderr line by line # dd uses a carriage return when printing it's progress, but using # universal_newlines converts all line endings into \n for line in iter(stderr.readline, ''): line = line.strip() # looking for dd's progress in the output e.g. '1,234M \n' # and making sure we report to UI at fixed time intervals, not like dd elapsed_seconds = time.time() - previous_timestamp try: if line and line[-1] == 'M' and elapsed_seconds > 0.3: total_written_mb = float(line.strip('M').replace(',', '')) # calculate stats to be reported to UI progress = int(total_written_mb / (size / BYTES_IN_MEGABYTE) * 100) speed = calculate_speed(total_written_mb, elapsed_seconds) eta = calculate_eta(total_written_mb, size / BYTES_IN_MEGABYTE, speed) report_progress_ui( progress, 'speed {0:.2f} MB/s eta {1:s} completed {2:d}%'.format( speed, eta, progress)) # update the time at which we last reported with the current time previous_timestamp = time.time() except: unparsed_line = line # watch out for an error output from dd if 'error' in line.lower() or 'invalid' in line.lower(): debugger('[ERROR] ' + line) failed = True # make sure the progress bar is filled and show an appropriate message # if we failed, the UI will immediately show the error screen report_progress_ui(100, 'burning finished successfully') # making sure we log anything nasty that has happened if unparsed_line: debugger('[ERROR] Failed parsing the line: ' + unparsed_line) if failed: debugger('[ERROR] Burning Kano image failed') burn_success = False else: debugger('Burning successfully finished') burn_success = True
def burn_kano_os(path, disk, size, return_queue, report_progress_ui): failed = False unparsed_line = '' try: gzip_cmd = "gzip -dc '{}'".format(path) dd_cmd = "dd 'of={}' bs=4m".format(disk) gzip_process = subprocess.Popen(gzip_cmd, env=cmd_env, stderr=subprocess.PIPE, stdout=subprocess.PIPE, shell=True) dd_process = subprocess.Popen(dd_cmd, env=cmd_env, stderr=subprocess.PIPE, stdin=gzip_process.stdout, stdout=subprocess.PIPE, shell=True) gzip_process.stdout.close() gzip_err_output = Queue.Queue() def gzip_read(gzip_file, return_queue): lines = gzip_file.readlines() return_queue.put(lines) gzip_thread = threading.Thread(target=gzip_read, args=(gzip_process.stderr, gzip_err_output)) gzip_thread.start() # as long as Popen is running, read it's stderr line by line # each time an INFO signal is sent to dd, it outputs 3 lines # and we are only interested in the last one i.e. 'x bytes written in y seconds' for line in iter(dd_process.stderr.readline, ''): if 'bytes' in line: try: parts = line.split() written_bytes = float(parts[0]) progress = int(written_bytes / size * 100) speed = float(parts[6][1:]) / BYTES_IN_MEGABYTE eta = calculate_eta(written_bytes, size, int(parts[6][1:])) report_progress_ui(progress, 'speed {0:.2f} MB/s eta {1:s} completed {2:d}%' .format(speed, eta, progress)) except: unparsed_line = line # watch out for an error output from dd if 'error' in line.lower() or 'invalid' in line.lower(): debugger('[ERROR] ' + line) failed = True # dd has closed its stdout, so everything should have finished. # But check anyway. dd_process.poll() if dd_process.returncode is None: dd_process.kill() dd_process.wait() gzip_process.poll() if gzip_process.returncode is None: gzip_process.kill() gzip_process.wait() if dd_process.returncode != 0: debugger('[ERROR] dd returned error code {}' .format(dd_process.returncode)) failed = True if gzip_process.returncode != 0: debugger('[ERROR] gzip returned error code {}' .format(gzip_process.returncode)) failed = True gzip_thread.join(100) gzip_stderr = gzip_err_output.get() debugger("gzip output: " + str(gzip_stderr)) # make sure the progress bar is filled and show an appropriate message # if we failed, the UI will immediately show the error screen report_progress_ui(100, 'burning finished successfully') except Exception as e: debugger(str(e)) failed = True # making sure we log anything nasty that has happened if unparsed_line: debugger('[ERROR] Failed parsing the line: ' + unparsed_line) if failed: debugger('[ERROR] Burning Kano image failed') return_queue.put(False) else: debugger('Burning successfully finished') return_queue.put(True)
def burn_kano_os(path, disk, size, return_queue, report_progress_ui): failed = False unparsed_line = '' try: gzip_cmd = "gzip -dc '{}'".format(path) dd_cmd = "dd 'of={}' bs=4m".format(disk) gzip_process = subprocess.Popen(gzip_cmd, env=cmd_env, stderr=subprocess.PIPE, stdout=subprocess.PIPE, shell=True) dd_process = subprocess.Popen(dd_cmd, env=cmd_env, stderr=subprocess.PIPE, stdin=gzip_process.stdout, stdout=subprocess.PIPE, shell=True) gzip_process.stdout.close() gzip_err_output = Queue.Queue() def gzip_read(gzip_file, return_queue): lines = gzip_file.readlines() return_queue.put(lines) gzip_thread = threading.Thread(target=gzip_read, args=(gzip_process.stderr, gzip_err_output)) gzip_thread.start() # as long as Popen is running, read it's stderr line by line # each time an INFO signal is sent to dd, it outputs 3 lines # and we are only interested in the last one i.e. 'x bytes written in y seconds' for line in iter(dd_process.stderr.readline, ''): if 'bytes' in line: try: parts = line.split() written_bytes = float(parts[0]) progress = int(written_bytes / size * 100) speed = float(parts[6][1:]) / BYTES_IN_MEGABYTE eta = calculate_eta(written_bytes, size, int(parts[6][1:])) report_progress_ui( progress, 'speed {0:.2f} MB/s eta {1:s} completed {2:d}%'. format(speed, eta, progress)) except: unparsed_line = line # watch out for an error output from dd if 'error' in line.lower() or 'invalid' in line.lower(): debugger('[ERROR] ' + line) failed = True # dd has closed its stdout, so everything should have finished. # But check anyway. dd_process.poll() if dd_process.returncode is None: dd_process.kill() dd_process.wait() gzip_process.poll() if gzip_process.returncode is None: gzip_process.kill() gzip_process.wait() if dd_process.returncode != 0: debugger('[ERROR] dd returned error code {}'.format( dd_process.returncode)) failed = True if gzip_process.returncode != 0: debugger('[ERROR] gzip returned error code {}'.format( gzip_process.returncode)) failed = True gzip_thread.join(100) gzip_stderr = gzip_err_output.get() debugger("gzip output: " + str(gzip_stderr)) # make sure the progress bar is filled and show an appropriate message # if we failed, the UI will immediately show the error screen report_progress_ui(100, 'burning finished successfully') except Exception as e: debugger(str(e)) failed = True # making sure we log anything nasty that has happened if unparsed_line: debugger('[ERROR] Failed parsing the line: ' + unparsed_line) if failed: debugger('[ERROR] Burning Kano image failed') return_queue.put(False) else: debugger('Burning successfully finished') return_queue.put(True)
def burn_kano_os(os_path, disk, size, report_progress_ui): cmd = '"{}\\7za.exe" e -so "{}" | "{}\\dd.exe" of="{}" bs=4M --progress'.format(_7zip_path, os_path, _dd_path, disk) # all handles (in, out, err) need to be set due to PyInstaller bundling process = subprocess.Popen(cmd, shell=True, universal_newlines=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) failed = False unparsed_line = '' # initialise UI timed reporting previous_timestamp = time.time() # as long as Popen is running, read it's stderr line by line # dd uses a carriage return when printing it's progress, but using # universal_newlines converts all line endings into \n for line in iter(process.stderr.readline, ''): line = line.strip() # looking for dd's progress in the output e.g. '1,234M \n' # and making sure we report to UI at fixed time intervals, not like dd elapsed_seconds = time.time() - previous_timestamp try: if line and line[-1] == 'M' and elapsed_seconds > 0.3: total_written_mb = float(line.strip('M').replace(',', '')) # calculate stats to be reported to UI progress = int(total_written_mb / (size / BYTES_IN_MEGABYTE) * 100) speed = calculate_speed(total_written_mb, elapsed_seconds) eta = calculate_eta(total_written_mb, size / BYTES_IN_MEGABYTE, speed) report_progress_ui(progress, 'speed {0:.2f} MB/s eta {1:s} completed {2:d}%' .format(speed, eta, progress)) # update the time at which we last reported with the current time previous_timestamp = time.time() except: unparsed_line = line # watch out for an error output from dd if 'error' in line.lower() or 'invalid' in line.lower(): debugger('[ERROR] ' + line) failed = True # make sure the progress bar is filled and show an appropriate message # if we failed, the UI will immediately show the error screen report_progress_ui(100, 'burning finished successfully') # making sure we log anything nasty that has happened if unparsed_line: debugger('[ERROR] Failed parsing the line: ' + unparsed_line) if failed: debugger('[ERROR] Burning Kano image failed') return False else: debugger('Burning successfully finished') return True