@sonic_installer.command('install')
@click.option('-y', '--yes', is_flag=True, callback=abort_if_false, expose_value=False, prompt='New image will be installed, continue?')
@click.option('-f', '--force', is_flag=True, help='Force installation of an image of a type which differs from that of the current running image')
@click.option('--skip_migration', is_flag=True, help='Do not migrate current configuration to the newly installed image')
@click.option('--skip-package-migration', is_flag=True, help='Do not migrate current packages to the newly installed image')
@click.option('--skip-setup-swap', is_flag=True, help='Skip setup temporary SWAP memory used for installation')
@click.option('--swap-mem-size', default=1024, type=int, show_default='1024 MiB', help='SWAP memory space size', callback=validate_positive_int, cls=clicommon.MutuallyExclusiveOption, mutually_exclusive=['skip_setup_swap'])
@click.option('--total-mem-threshold', default=2048, type=int, show_default='2048 MiB', help='If system total memory is lower than threshold, setup SWAP memory', cls=clicommon.MutuallyExclusiveOption, mutually_exclusive=['skip_setup_swap'], callback=validate_positive_int)
@click.option('--available-mem-threshold', default=1200, type=int, show_default='1200 MiB', help='If system available memory is lower than threhold, setup SWAP memory', cls=clicommon.MutuallyExclusiveOption, mutually_exclusive=['skip_setup_swap'], callback=validate_positive_int)
@click.argument('url')
def install(url, force, skip_migration=False, skip_package_migration=False, skip_setup_swap=False, swap_mem_size=None, total_mem_threshold=None, available_mem_threshold=None):
    ' Install image from local binary or URL'
    bootloader = get_bootloader()
    if (url.startswith('http://') or url.startswith('https://')):
        echo_and_log('Downloading image...')
        validate_url_or_abort(url)
        try:
            urlretrieve(url, bootloader.DEFAULT_IMAGE_PATH, reporthook)
            click.echo('')
        except Exception as e:
            echo_and_log('Download error', e)
            raise click.Abort()
        image_path = bootloader.DEFAULT_IMAGE_PATH
    else:
        image_path = os.path.join('./', url)
    binary_image_version = bootloader.get_binary_image_version(image_path)
    if (not binary_image_version):
        echo_and_log('Image file does not exist or is not a valid SONiC image file', LOG_ERR)
        raise click.Abort()
    if (binary_image_version in bootloader.get_installed_images()):
        echo_and_log('Image {} is already installed. Setting it as default...'.format(binary_image_version))
        if (not bootloader.set_default_image(binary_image_version)):
            echo_and_log('Error: Failed to set image as default', LOG_ERR)
            raise click.Abort()
    else:
        if ((not bootloader.verify_binary_image(image_path)) and (not force)):
            echo_and_log((("Image file '{}' is of a different type than running image.\n".format(url) + 'If you are sure you want to install this image, use -f|--force.\n') + 'Aborting...'), LOG_ERR)
            raise click.Abort()
        echo_and_log('Installing image {} and setting it as default...'.format(binary_image_version))
        with SWAPAllocator((not skip_setup_swap), swap_mem_size, total_mem_threshold, available_mem_threshold):
            bootloader.install_image(image_path)
        if skip_migration:
            echo_and_log('Skipping configuration migration as requested in the command option.')
        else:
            run_command('config-setup backup')
        update_sonic_environment(bootloader, binary_image_version)
        if ((not bootloader.supports_package_migration(binary_image_version)) and (not skip_package_migration)):
            echo_and_log('Warning: SONiC package migration is not supported for this bootloader/image', fg='yellow')
            skip_package_migration = True
        if (not skip_package_migration):
            migrate_sonic_packages(bootloader, binary_image_version)
    run_command('sync;sync;sync')
    run_command('sleep 3')
    echo_and_log('Done')
Install image from local binary or URL
@sonic_installer.command('install')
@click.option('-y', '--yes', is_flag=True, callback=abort_if_false, expose_value=False, prompt='New image will be installed, continue?')
@click.option('-f', '--force', is_flag=True, help='Force installation of an image of a type which differs from that of the current running image')
@click.option('--skip_migration', is_flag=True, help='Do not migrate current configuration to the newly installed image')
@click.option('--skip-package-migration', is_flag=True, help='Do not migrate current packages to the newly installed image')
@click.option('--skip-setup-swap', is_flag=True, help='Skip setup temporary SWAP memory used for installation')
@click.option('--swap-mem-size', default=1024, type=int, show_default='1024 MiB', help='SWAP memory space size', callback=validate_positive_int, cls=clicommon.MutuallyExclusiveOption, mutually_exclusive=['skip_setup_swap'])
@click.option('--total-mem-threshold', default=2048, type=int, show_default='2048 MiB', help='If system total memory is lower than threshold, setup SWAP memory', cls=clicommon.MutuallyExclusiveOption, mutually_exclusive=['skip_setup_swap'], callback=validate_positive_int)
@click.option('--available-mem-threshold', default=1200, type=int, show_default='1200 MiB', help='If system available memory is lower than threhold, setup SWAP memory', cls=clicommon.MutuallyExclusiveOption, mutually_exclusive=['skip_setup_swap'], callback=validate_positive_int)
@click.argument('url')
def install(url, force, skip_migration=False, skip_package_migration=False, skip_setup_swap=False, swap_mem_size=None, total_mem_threshold=None, available_mem_threshold=None):
    ' '
    bootloader = get_bootloader()
    if (url.startswith('http://') or url.startswith('https://')):
        echo_and_log('Downloading image...')
        validate_url_or_abort(url)
        try:
            urlretrieve(url, bootloader.DEFAULT_IMAGE_PATH, reporthook)
            click.echo()
        except Exception as e:
            echo_and_log('Download error', e)
            raise click.Abort()
        image_path = bootloader.DEFAULT_IMAGE_PATH
    else:
        image_path = os.path.join('./', url)
    binary_image_version = bootloader.get_binary_image_version(image_path)
    if (not binary_image_version):
        echo_and_log('Image file does not exist or is not a valid SONiC image file', LOG_ERR)
        raise click.Abort()
    if (binary_image_version in bootloader.get_installed_images()):
        echo_and_log('Image {} is already installed. Setting it as default...'.format(binary_image_version))
        if (not bootloader.set_default_image(binary_image_version)):
            echo_and_log('Error: Failed to set image as default', LOG_ERR)
            raise click.Abort()
    else:
        if ((not bootloader.verify_binary_image(image_path)) and (not force)):
            echo_and_log((("Image file '{}' is of a different type than running image.\n".format(url) + 'If you are sure you want to install this image, use -f|--force.\n') + 'Aborting...'), LOG_ERR)
            raise click.Abort()
        echo_and_log('Installing image {} and setting it as default...'.format(binary_image_version))
        with SWAPAllocator((not skip_setup_swap), swap_mem_size, total_mem_threshold, available_mem_threshold):
            bootloader.install_image(image_path)
        if skip_migration:
            echo_and_log('Skipping configuration migration as requested in the command option.')
        else:
            run_command('config-setup backup')
        update_sonic_environment(bootloader, binary_image_version)
        if ((not bootloader.supports_package_migration(binary_image_version)) and (not skip_package_migration)):
            echo_and_log('Warning: SONiC package migration is not supported for this bootloader/image', fg='yellow')
            skip_package_migration = True
        if (not skip_package_migration):
            migrate_sonic_packages(bootloader, binary_image_version)
    run_command('sync;sync;sync')
    run_command('sleep 3')
    echo_and_log('Done')