def dracut_bind_mounts(root_path,): """Function to do bind mounts needed before running dracut""" log = logging.getLogger(Defaults.get_migration_log_name()) BIND_DIRS = ['/dev', '/proc', '/sys'] for bind_dir in BIND_DIRS: try: log.info( 'Running mount --bind {0} {1}'.format(bind_dir, root_path + bind_dir) ) Command.run( [ 'mount', '--bind', bind_dir, root_path + bind_dir ] ) except Exception as issue: log.error( 'Unable to mount: {0}'.format(issue) ) raise DistMigrationCommandException( 'Unable to mount: {0}'.format( issue ) ) from issue
def run_dracut(root_path): """Function run dracut""" log = logging.getLogger(Defaults.get_migration_log_name()) try: log.info( 'Running chroot {0} dracut --no-kernel --no-host-only --no-hostonly-cmdline' '--regenerate-all --logfile /tmp/host_independent_initrd.log -f'.format(root_path) ) Command.run( [ 'chroot', root_path, 'dracut', '--no-kernel', '--no-host-only', '--no-hostonly-cmdline', '--regenerate-all', '--logfile', '/tmp/host_independent_initrd.log', '-f' ] ) Command.run( [ 'chroot', root_path, 'cat', '/tmp/host_independent_initrd.log', '>> /var/log/distro_migration.log' ] ) Command.run( [ 'chroot', root_path, 'rm', '/tmp/host_independent_initrd.log' ] ) except Exception as issue: log.error( 'Unable to create new initrd with dracut: {0}'.format(issue) ) raise DistMigrationCommandException( 'Failed to create new initrd: {0}'.format( issue ) ) from issue
def main(): """ DistMigration run zypper based migration Call zypper migration plugin and migrate the system. The output of the call is logged on the system to migrate """ root_path = Defaults.get_system_root_path() try: log.info('Running migrate service') migration_config = MigrationConfig() if migration_config.is_zypper_migration_plugin_requested(): bash_command = ' '.join([ 'zypper', 'migration', '--non-interactive', '--gpg-auto-import-keys', '--no-selfupdate', '--auto-agree-with-licenses', '--allow-vendor-change', '--strict-errors-dist-migration', '--replacefiles', '--product', migration_config.get_migration_product(), '--root', root_path, '&>>', Defaults.get_migration_log_file() ]) Command.run(['bash', '-c', bash_command]) else: bash_command = ' '.join([ 'zypper', '--non-interactive', '--gpg-auto-import-keys', '--root', root_path, 'dup', '--auto-agree-with-licenses', '--allow-vendor-change', '--replacefiles', '&>>', Defaults.get_migration_log_file() ]) zypper_call = Command.run(['bash', '-c', bash_command], raise_on_error=False) if zypper_has_failed(zypper_call.returncode): raise DistMigrationCommandException( '{0} failed with: {1}: {2}'.format(bash_command, zypper_call.output, zypper_call.error)) except Exception as issue: etc_issue_path = os.sep.join([root_path, 'etc/issue']) log_path_migrated_system = os.sep + os.path.relpath( Defaults.get_migration_log_file(), root_path) with open(etc_issue_path, 'w') as issue_file: issue_file.write( 'Migration has failed, for further details see {0}'.format( log_path_migrated_system)) log.error('migrate service failed with {0}'.format(issue)) raise DistMigrationZypperException( 'Migration failed with {0}'.format(issue))
def test_run_failure(self, mock_popen, mock_which): mock_which.return_value = 'command' mock_popen.side_effect = DistMigrationCommandException('Run failure') with raises(DistMigrationCommandException): Command.run(['command', 'args'])
def run(command, custom_env=None, raise_on_error=True): """ Execute a program and block the caller. The return value is a hash containing the stdout, stderr and return code information. Unless raise_on_error is set to false an exception is thrown if the command exits with an error code not equal to zero Example: .. code:: python result = Command.run(['ls', '-l']) :param list command: command and arguments :param list custom_env: custom os.environ :param bool raise_on_error: control error behaviour :return: Contains call results in command type .. code:: python command(output='string', error='string', returncode=int) :rtype: namedtuple """ from .path import Path command_type = namedtuple('command', ['output', 'error', 'returncode']) environment = os.environ if custom_env: environment = custom_env if not Path.which( command[0], custom_env=environment, access_mode=os.X_OK): message = 'Command "%s" not found in the environment' % command[0] if not raise_on_error: return command_type(output=None, error=None, returncode=-1) else: log.error(message) raise DistMigrationCommandNotFoundException(message) try: log.info('Calling: {0}'.format(command)) process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=environment) except Exception as issue: raise DistMigrationCommandException('{0}: {1}: {2}'.format( command[0], type(issue).__name__, issue)) output, error = process.communicate() if process.returncode != 0 and not error: error = bytes(b'(no output on stderr)') if process.returncode != 0 and not output: output = bytes(b'(no output on stdout)') if process.returncode != 0 and raise_on_error: log.error('EXEC: Failed with stderr: {0}, stdout: {1}'.format( error.decode(), output.decode())) raise DistMigrationCommandException( '{0}: stderr: {1}, stdout: {2}'.format(command[0], error.decode(), output.decode())) return command_type(output=output.decode(), error=error.decode(), returncode=process.returncode)