33import os
44import re
55import time
6+ import warnings
67
78from netmiko import ConnectHandler , FileTransfer
89from netmiko .exceptions import ReadTimeout
@@ -319,6 +320,17 @@ def boot_options(self):
319320 log .debug ("Host %s: the boot options are {dict(sys=boot_image)}" , self .host )
320321 return {"sys" : boot_image }
321322
323+ @property
324+ def install_mode (self ):
325+ """Return whether the device is currently booted in install mode.
326+
327+ Returns:
328+ (bool): True when the current boot image equals
329+ :data:`INSTALL_MODE_FILE_NAME` (i.e., ``packages.conf``),
330+ False otherwise.
331+ """
332+ return self .boot_options .get ("sys" ) == INSTALL_MODE_FILE_NAME
333+
322334 def checkpoint (self , checkpoint_file ):
323335 """Create checkpoint file.
324336
@@ -877,13 +889,28 @@ def file_copy_remote_exists(self, src, dest=None, file_system=None):
877889 log .debug ("Host %s: File %s does not already exist on remote." , self .host , src )
878890 return False
879891
880- def install_os (self , image_name , reboot = True , install_mode = False , read_timeout = 2000 , ** vendor_specifics ):
892+ def _resolve_install_mode (self , install_mode ):
893+ """Return the effective install_mode flag, warning if the caller passed it explicitly."""
894+ if install_mode is None :
895+ return self .install_mode
896+ warnings .warn (
897+ "The install_mode argument to install_os is deprecated; install mode is now "
898+ "derived from the device's boot_options via the install_mode property." ,
899+ DeprecationWarning ,
900+ )
901+ return install_mode
902+
903+ def install_os (self , image_name , reboot = True , install_mode = None , read_timeout = 2000 , ** vendor_specifics ):
881904 """Installs the prescribed Network OS, which must be present before issuing this command.
882905
883906 Args:
884907 image_name (str): Name of the IOS image to boot into
885908 reboot (bool): Whether to reboot the device after setting the boot options. Defaults to true.
886- install_mode (bool, optional): Uses newer install method on devices. Defaults to False.
909+ install_mode (bool, optional): **Deprecated.** Whether to use the newer install-mode
910+ upgrade procedure. When omitted (the default), the value is derived from
911+ :attr:`install_mode`, which reads the device's current boot configuration.
912+ Passing the argument explicitly still works but emits a ``DeprecationWarning``
913+ and will be removed in a future release.
887914 read_timeout (int, optional): Netmiko timeout when waiting for device prompt. Default 2000.
888915 vendor_specifics (dict, optional): Vendor specific arguments to pass to the install command.
889916
@@ -893,14 +920,15 @@ def install_os(self, image_name, reboot=True, install_mode=False, read_timeout=2
893920 Returns:
894921 (bool): False if no install is needed, true if the install completes successfully
895922 """
923+ use_install_mode = self ._resolve_install_mode (install_mode )
896924 timeout = vendor_specifics .get ("timeout" , 3600 )
897925 if not self ._image_booted (image_name ):
898- if install_mode and not reboot :
926+ if use_install_mode and not reboot :
899927 raise ValueError (
900928 "IOS devices automatically reboot after installation when using install mode but the reboot argument was set to false."
901929 )
902930
903- if install_mode :
931+ if use_install_mode :
904932 # Change boot statement to be boot system <flash>:packages.conf
905933 self .set_boot_options (INSTALL_MODE_FILE_NAME , ** vendor_specifics )
906934
@@ -942,7 +970,7 @@ def install_os(self, image_name, reboot=True, install_mode=False, read_timeout=2
942970 self ._wait_for_device_reboot (timeout = timeout )
943971
944972 # Set FastCLI back to originally set when using install mode
945- if install_mode :
973+ if use_install_mode :
946974 image_name = INSTALL_MODE_FILE_NAME
947975 # Verify the OS level
948976 if not self ._image_booted (image_name ):
0 commit comments