diff options
author | John Estabrook <jestabro@vyos.io> | 2023-11-28 08:33:30 -0600 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-11-28 08:33:30 -0600 |
commit | 6d9feb9df38bfcad7c68c2cbbdba7868a715ccef (patch) | |
tree | 1da0672cfcdc943c0cddf2627a3d31184296a77d | |
parent | 5f575360b0c996187e7f05cccc5caff6a658544d (diff) | |
parent | 2ccb567bba6dba69a1523daf9096ba39a18b35d1 (diff) | |
download | vyos-1x-6d9feb9df38bfcad7c68c2cbbdba7868a715ccef.tar.gz vyos-1x-6d9feb9df38bfcad7c68c2cbbdba7868a715ccef.zip |
Merge pull request #2550 from jestabro/non-interactive-add-delete-image
image-tools: T5751: allow non-interactive add/delete image
-rw-r--r-- | op-mode-definitions/system-image.xml.in | 14 | ||||
-rw-r--r-- | python/vyos/configsession.py | 6 | ||||
-rw-r--r-- | python/vyos/remote.py | 4 | ||||
-rwxr-xr-x | src/op_mode/image_installer.py | 30 | ||||
-rwxr-xr-x | src/op_mode/image_manager.py | 17 |
5 files changed, 43 insertions, 28 deletions
diff --git a/op-mode-definitions/system-image.xml.in b/op-mode-definitions/system-image.xml.in index 463b985d6..c131087be 100644 --- a/op-mode-definitions/system-image.xml.in +++ b/op-mode-definitions/system-image.xml.in @@ -17,7 +17,7 @@ <list>/path/to/vyos-image.iso "http://example.com/vyos-image.iso"</list> </completionHelp> </properties> - <command>sudo ${vyos_op_scripts_dir}/image_installer.py --action add --image_path "${4}"</command> + <command>sudo ${vyos_op_scripts_dir}/image_installer.py --action add --image-path "${4}"</command> <children> <tagNode name="vrf"> <properties> @@ -26,7 +26,7 @@ <path>vrf name</path> </completionHelp> </properties> - <command>sudo ${vyos_op_scripts_dir}/image_installer.py --action add --image_path "${4}" --vrf "${6}"</command> + <command>sudo ${vyos_op_scripts_dir}/image_installer.py --action add --image-path "${4}" --vrf "${6}"</command> <children> <tagNode name="username"> <properties> @@ -37,7 +37,7 @@ <properties> <help>Password to use with authentication</help> </properties> - <command>sudo ${vyos_op_scripts_dir}/image_installer.py --action add --image_path "${4}" --vrf "${6}" --username "${8}" --password "${10}"</command> + <command>sudo ${vyos_op_scripts_dir}/image_installer.py --action add --image-path "${4}" --vrf "${6}" --username "${8}" --password "${10}"</command> </tagNode> </children> </tagNode> @@ -52,7 +52,7 @@ <properties> <help>Password to use with authentication</help> </properties> - <command>sudo ${vyos_op_scripts_dir}/image_installer.py --action add --image_path "${4}" --username "${6}" --password "${8}"</command> + <command>sudo ${vyos_op_scripts_dir}/image_installer.py --action add --image-path "${4}" --username "${6}" --password "${8}"</command> </tagNode> </children> </tagNode> @@ -90,7 +90,7 @@ <script>sudo ${vyos_op_scripts_dir}/image_manager.py --action list</script> </completionHelp> </properties> - <command>sudo ${vyos_op_scripts_dir}/image_manager.py --action set --image_name "${5}"</command> + <command>sudo ${vyos_op_scripts_dir}/image_manager.py --action set --image-name "${5}"</command> </tagNode> </children> </node> @@ -134,7 +134,7 @@ <script>sudo ${vyos_op_scripts_dir}/image_manager.py --action list</script> </completionHelp> </properties> - <command>sudo ${vyos_op_scripts_dir}/image_manager.py --action delete --image_name "${4}"</command> + <command>sudo ${vyos_op_scripts_dir}/image_manager.py --action delete --image-name "${4}"</command> </tagNode> </children> </node> @@ -162,7 +162,7 @@ <properties> <help>A new name for an image</help> </properties> - <command>sudo ${vyos_op_scripts_dir}/image_manager.py --action rename --image_name "${4}" --image_new_name "${6}"</command> + <command>sudo ${vyos_op_scripts_dir}/image_manager.py --action rename --image-name "${4}" --image-new-name "${6}"</command> </tagNode> </children> </tagNode> diff --git a/python/vyos/configsession.py b/python/vyos/configsession.py index 9802ebae4..90842b749 100644 --- a/python/vyos/configsession.py +++ b/python/vyos/configsession.py @@ -30,8 +30,10 @@ SHOW_CONFIG = ['/bin/cli-shell-api', 'showConfig'] LOAD_CONFIG = ['/bin/cli-shell-api', 'loadFile'] MIGRATE_LOAD_CONFIG = ['/usr/libexec/vyos/vyos-load-config.py'] SAVE_CONFIG = ['/usr/libexec/vyos/vyos-save-config.py'] -INSTALL_IMAGE = ['/opt/vyatta/sbin/install-image', '--url'] -REMOVE_IMAGE = ['/opt/vyatta/bin/vyatta-boot-image.pl', '--del'] +INSTALL_IMAGE = ['/usr/libexec/vyos/op_mode/image_installer.py', + '--action', 'add', '--no-prompt', '--image-path'] +REMOVE_IMAGE = ['/usr/libexec/vyos/op_mode/image_manager.py', + '--action', 'delete', '--no-prompt', '--image-name'] GENERATE = ['/opt/vyatta/bin/vyatta-op-cmd-wrapper', 'generate'] SHOW = ['/opt/vyatta/bin/vyatta-op-cmd-wrapper', 'show'] RESET = ['/opt/vyatta/bin/vyatta-op-cmd-wrapper', 'reset'] diff --git a/python/vyos/remote.py b/python/vyos/remote.py index 8928cce67..fec44b571 100644 --- a/python/vyos/remote.py +++ b/python/vyos/remote.py @@ -437,11 +437,13 @@ def urlc(urlstring, *args, **kwargs): raise ValueError(f'Unsupported URL scheme: "{scheme}"') def download(local_path, urlstring, progressbar=False, check_space=False, - source_host='', source_port=0, timeout=10.0): + source_host='', source_port=0, timeout=10.0, raise_error=False): try: progressbar = progressbar and is_interactive() urlc(urlstring, progressbar, check_space, source_host, source_port, timeout).download(local_path) except Exception as err: + if raise_error: + raise print_error(f'Unable to download "{urlstring}": {err}') except KeyboardInterrupt: print_error('\nDownload aborted by user.') diff --git a/src/op_mode/image_installer.py b/src/op_mode/image_installer.py index aa4cf301b..df5d897b7 100755 --- a/src/op_mode/image_installer.py +++ b/src/op_mode/image_installer.py @@ -376,7 +376,7 @@ def validate_signature(file_path: str, sign_type: str) -> None: print('Signature is valid') -def image_fetch(image_path: str) -> Path: +def image_fetch(image_path: str, no_prompt: bool = False) -> Path: """Fetch an ISO image Args: @@ -389,13 +389,14 @@ def image_fetch(image_path: str) -> Path: # check a type of path if urlparse(image_path).scheme: # download an image - download(ISO_DOWNLOAD_PATH, image_path, True, True) + download(ISO_DOWNLOAD_PATH, image_path, True, True, + raise_error=True) # download a signature sign_file = (False, '') for sign_type in ['minisig', 'asc']: try: download(f'{ISO_DOWNLOAD_PATH}.{sign_type}', - f'{image_path}.{sign_type}') + f'{image_path}.{sign_type}', raise_error=True) sign_file = (True, sign_type) break except Exception: @@ -404,7 +405,8 @@ def image_fetch(image_path: str) -> Path: if sign_file[0]: validate_signature(ISO_DOWNLOAD_PATH, sign_file[1]) else: - if not ask_yes_no(MSG_WARN_ISO_SIGN_UNAVAL, default=False): + if (not no_prompt and + not ask_yes_no(MSG_WARN_ISO_SIGN_UNAVAL, default=False)): cleanup() exit(MSG_INFO_INSTALL_EXIT) @@ -629,7 +631,7 @@ def install_image() -> None: @compat.grub_cfg_update -def add_image(image_path: str) -> None: +def add_image(image_path: str, no_prompt: bool = False) -> None: """Add a new image Args: @@ -639,7 +641,7 @@ def add_image(image_path: str) -> None: exit(MSG_ERR_LIVE) # fetch an image - iso_path: Path = image_fetch(image_path) + iso_path: Path = image_fetch(image_path, no_prompt) try: # mount an ISO Path(DIR_ISO_MOUNT).mkdir(mode=0o755, parents=True) @@ -668,8 +670,12 @@ def add_image(image_path: str) -> None: raise compat.DowngradingImageTools( f'Adding image would downgrade image tools to v.{cfg_ver}; disallowed') - image_name: str = ask_input(MSG_INPUT_IMAGE_NAME, version_name) - set_as_default: bool = ask_yes_no(MSG_INPUT_IMAGE_DEFAULT, default=True) + if not no_prompt: + image_name: str = ask_input(MSG_INPUT_IMAGE_NAME, version_name) + set_as_default: bool = ask_yes_no(MSG_INPUT_IMAGE_DEFAULT, default=True) + else: + image_name: str = version_name + set_as_default: bool = True # find target directory root_dir: str = disk.find_persistence() @@ -678,7 +684,7 @@ def add_image(image_path: str) -> None: # create all the rest in a single step target_config_dir: str = f'{root_dir}/boot/{image_name}/rw/opt/vyatta/etc/config/' # copy config - if migrate_config(): + if no_prompt or migrate_config(): print('Copying configuration directory') # copytree preserves perms but not ownership: Path(target_config_dir).mkdir(parents=True) @@ -727,8 +733,10 @@ def parse_arguments() -> Namespace: choices=['install', 'add'], required=True, help='action to perform with an image') + parser.add_argument('--no-prompt', action='store_true', + help='perform action non-interactively') parser.add_argument( - '--image_path', + '--image-path', help='a path (HTTP or local file) to an image that needs to be installed' ) # parser.add_argument('--image_new_name', help='a new name for image') @@ -746,7 +754,7 @@ if __name__ == '__main__': if args.action == 'install': install_image() if args.action == 'add': - add_image(args.image_path) + add_image(args.image_path, args.no_prompt) exit() diff --git a/src/op_mode/image_manager.py b/src/op_mode/image_manager.py index e4b2f4833..e75485f9f 100755 --- a/src/op_mode/image_manager.py +++ b/src/op_mode/image_manager.py @@ -36,7 +36,7 @@ MSG_DELETE_IMAGE_DEFAULT: str = 'Default image cannot be deleted; set another im @compat.grub_cfg_update def delete_image(image_name: Optional[str] = None, - prompt: bool = True) -> None: + no_prompt: bool = False) -> None: """Remove installed image files and boot entry Args: @@ -44,7 +44,7 @@ def delete_image(image_name: Optional[str] = None, """ available_images: list[str] = grub.version_list() if image_name is None: - if not prompt: + if no_prompt: exit('An image name is required for delete action') else: image_name = select_entry(available_images, @@ -60,8 +60,9 @@ def delete_image(image_name: Optional[str] = None, if not persistence_storage: exit('Persistence storage cannot be found') - if not ask_yes_no(f'Do you really want to delete the image {image_name}?', - default=False): + if (not no_prompt and + not ask_yes_no(f'Do you really want to delete the image {image_name}?', + default=False)): exit() # remove files and menu entry @@ -171,11 +172,13 @@ def parse_arguments() -> Namespace: choices=['delete', 'set', 'rename', 'list'], required=True, help='action to perform with an image') + parser.add_argument('--no-prompt', action='store_true', + help='perform action non-interactively') parser.add_argument( - '--image_name', + '--image-name', help= 'a name of an image to add, delete, install, rename, or set as default') - parser.add_argument('--image_new_name', help='a new name for image') + parser.add_argument('--image-new-name', help='a new name for image') args: Namespace = parser.parse_args() # Validate arguments if args.action == 'rename' and (not args.image_name or @@ -189,7 +192,7 @@ if __name__ == '__main__': try: args: Namespace = parse_arguments() if args.action == 'delete': - delete_image(args.image_name) + delete_image(args.image_name, args.no_prompt) if args.action == 'set': set_image(args.image_name) if args.action == 'rename': |