diff options
| author | Christian Breunig <christian@breunig.cc> | 2026-07-22 21:34:02 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-07-22 21:34:02 +0200 |
| commit | bf2b506e45b574b18cf8be5dfd2c8e33ac999732 (patch) | |
| tree | 00ff79613a63b369109039e91aac0fdb8ea88ba3 /src | |
| parent | 9a02328fd8f68f24a66c9cb559219541508f5f9d (diff) | |
| parent | b12a8c5aef72c0adaca197c98f5dfa9cbb8a73d2 (diff) | |
| download | vyos-1x-bf2b506e45b574b18cf8be5dfd2c8e33ac999732.tar.gz vyos-1x-bf2b506e45b574b18cf8be5dfd2c8e33ac999732.zip | |
Merge pull request #5344 from alexandr-san4ez/T9021-rolling
image: T9021: Save bash history during image upgrade
Diffstat (limited to 'src')
| -rwxr-xr-x | src/op_mode/image_installer.py | 109 |
1 files changed, 93 insertions, 16 deletions
diff --git a/src/op_mode/image_installer.py b/src/op_mode/image_installer.py index ea5aed088..4e7a70893 100755 --- a/src/op_mode/image_installer.py +++ b/src/op_mode/image_installer.py @@ -812,6 +812,18 @@ def copy_ssh_known_hosts() -> bool: return known_hosts_files and ask_yes_no(msg, default=True) +def copy_bash_history() -> bool: + """Ask user to copy bash history + + Returns: + bool: user's decision + """ + + history_files = get_bash_history_files() + msg = 'Would you like to copy bash history?' + return bool(history_files) and ask_yes_no(msg, default=False) + + def console_hint() -> str: pid = getppid() if 'SUDO_USER' in environ else getpid() try: @@ -1116,36 +1128,62 @@ def install_image() -> None: exit(1) -def get_known_hosts_files(for_root=True, for_users=True) -> list: - """Collect all existing `known_hosts` files for root and/or users under /home""" +def _get_users_relative_paths( + relative_paths: list, for_root=True, for_users=True +) -> list: + """ + Retrieve a list of file paths based on given relative paths, optionally + including files from the root directory and user home directories. + """ files = [] if for_root: - base_files = ('/root/.ssh/known_hosts', '/etc/ssh/ssh_known_hosts') - for file_path in base_files: - root_known_hosts = Path(file_path) - if root_known_hosts.exists(): - files.append(root_known_hosts) + for relative_path in relative_paths: + file_path = Path('/root') / relative_path + if file_path.exists(): + files.append(file_path) if for_users: # for each non-system user for user in get_local_users(): home_dir = Path(get_user_home_dir(user)) if home_dir.exists(): - known_hosts = home_dir / '.ssh' / 'known_hosts' - if known_hosts.exists(): - files.append(known_hosts) + for relative_path in relative_paths: + file_path = home_dir / relative_path + if file_path.exists(): + files.append(file_path) + + return [file_path.absolute() for file_path in files] + + +def get_known_hosts_files(for_root=True, for_users=True) -> list: + """Collect all existing `known_hosts` files for root and/or users under /home""" + + files = _get_users_relative_paths( + ['.ssh/known_hosts'], + for_root=for_root, + for_users=for_users, + ) + + if for_root: + # Add also additional global 'ssh_known_hosts' file + root_known_hosts = Path('/etc/ssh/ssh_known_hosts') + if root_known_hosts.exists(): + files.append(root_known_hosts) return files +def _mkdir_and_copy_file(source_path: Path, target_path: Path): + """Create the target directory if it doesn't exist and copy a file from source to target""" + + target_path.parent.mkdir(parents=True, exist_ok=True) + copy(source_path, target_path) + + def migrate_known_hosts(target_dir: str): """Copy `known_hosts` for root and all users to the new image directory""" - def _mkdir_and_copy_file(known_hosts_file, target_known_hosts): - target_known_hosts.parent.mkdir(parents=True, exist_ok=True) - copy(known_hosts_file, target_known_hosts) - # Copy root only files using default path known_hosts_files = get_known_hosts_files(for_root=True, for_users=False) for known_hosts_file in known_hosts_files: @@ -1165,6 +1203,36 @@ def migrate_known_hosts(target_dir: str): _mkdir_and_copy_file(known_hosts_file, target_known_hosts) +def get_bash_history_files(for_root=True, for_users=True) -> list: + """Collect all existing `.bash_history` files for root and/or users under /home""" + + return _get_users_relative_paths( + ['.bash_history'], + for_root=for_root, + for_users=for_users, + ) + + +def migrate_bash_history(target_dir: str): + """Copy `.bash_history` for root and all users to the new image directory""" + + # Copy root's history using its default path + history_files = get_bash_history_files(for_root=True, for_users=False) + for history_file in history_files: + target_history = Path(f'{target_dir}{history_file}') + _mkdir_and_copy_file(history_file, target_history) + + # Preserve non-root users' bash history the same way known_hosts + # is backed up: under /var/.users_backups/{user}, since regular + # user home directories are not otherwise migrated. + history_files = get_bash_history_files(for_root=False, for_users=True) + for history_file in history_files: + username = history_file.parent.name + base_dir = Path(f'{target_dir}/var/.users_backups/{username}') + target_history = base_dir / '.bash_history' + _mkdir_and_copy_file(history_file, target_history) + + @compat.grub_cfg_update def add_image(image_path: str, vrf: str = None, username: str = '', password: str = '', no_prompt: bool = False, force: bool = False) -> None: @@ -1290,19 +1358,28 @@ def add_image(image_path: str, vrf: str = None, username: str = '', chmod_2775(target_config_dir) Path(f'{target_config_dir}/.vyatta_config').touch() - target_ssh_dir: str = f'{root_dir}/boot/{image_name}/rw/etc/ssh/' + # Default persistence directory + target_persist_dir: str = f'{root_dir}/boot/{image_name}/rw' + if no_prompt or copy_ssh_host_keys(): print('Copying SSH host keys') + target_ssh_dir: str = f'{target_persist_dir}/etc/ssh/' Path(target_ssh_dir).mkdir(parents=True) host_keys: list[str] = glob('/etc/ssh/ssh_host*') for host_key in host_keys: copy(host_key, target_ssh_dir) - target_ssh_known_hosts_dir: str = f'{root_dir}/boot/{image_name}/rw' if no_prompt or copy_ssh_known_hosts(): print('Copying SSH known_hosts files') + target_ssh_known_hosts_dir: str = target_persist_dir migrate_known_hosts(target_ssh_known_hosts_dir) + # By default we should disable auto-copy under '--no-prompt' mode + if no_prompt is False and copy_bash_history(): + print('Copying bash history') + target_history_dir: str = target_persist_dir + migrate_bash_history(target_history_dir) + # copy system image and kernel files print('Copying system image files') for file in Path(f'{DIR_ISO_MOUNT}/live').iterdir(): |
