1- """Module for using a Cisco ASA device over SSH.
2- """
1+ """Module for using a Cisco ASA device over SSH."""
32
43import os
54import re
@@ -41,6 +40,16 @@ class ASADevice(BaseDevice):
4140 active_redundancy_states = {None , "active" }
4241
4342 def __init__ (self , host : str , username : str , password : str , secret = "" , port = 22 , ** kwargs ):
43+ """
44+ Pyntc Device constructor for Cisco ASA.
45+
46+ Args:
47+ host (str): The address of the network device.
48+ username (str): The username to authenticate to the device.
49+ password (str): The password to authenticate to the device.
50+ secret (str, optional): The password to escalate privlege on the device. Defaults to "".
51+ port (int, optional): Port used to establish connection. Defaults to 22.
52+ """
4453 super ().__init__ (host , username , password , device_type = "cisco_asa_ssh" )
4554
4655 self .native : Optional [CiscoAsaSSH ] = None
@@ -93,7 +102,7 @@ def _file_copy_instance(
93102 return fc
94103
95104 def _get_file_system (self ):
96- """Determines the default file system or directory for device.
105+ """Determine the default file system or directory for device.
97106
98107 Returns:
99108 str: The name of the default file system or directory for the device.
@@ -301,11 +310,23 @@ def _wait_for_peer_reboot(self, acceptable_states: Iterable[str], timeout: int =
301310 raise RebootTimeoutError (hostname = f"{ self .host } -peer" , wait_time = timeout )
302311
303312 def backup_running_config (self , filename ):
313+ """
314+ Backups running config.
315+
316+ Args:
317+ filename (str): Name of backup file.
318+ """
304319 with open (filename , "w" ) as f :
305320 f .write (self .running_config )
306321
307322 @property
308323 def boot_options (self ):
324+ """
325+ Determine boot image.
326+
327+ Returns:
328+ dict: Key: 'sys' Value: Current boot image.
329+ """
309330 show_boot_out = self .show ("show boot | i BOOT variable" )
310331 # Improve regex to get only the first boot $var in the sequence!
311332 boot_path_regex = r"Current BOOT variable = (\S+):\/(\S+)"
@@ -319,19 +340,41 @@ def boot_options(self):
319340 return dict (sys = boot_image )
320341
321342 def checkpoint (self , checkpoint_file ):
343+ """
344+ Create a checkpoint file of the current config.
345+
346+ Args:
347+ checkpoint_file (str): Saves a checkpoint file with the name provided to the function.
348+ """
322349 self .save (filename = checkpoint_file )
323350
324351 def close (self ):
352+ """Disconnect from device."""
325353 if self ._connected :
326354 self .native .disconnect ()
327355 self ._connected = False
328356
329357 def config (self , command ):
358+ """
359+ Send single command to device.
360+
361+ Args:
362+ command (str): command to be sent to device.
363+ """
330364 self ._enter_config ()
331365 self ._send_command (command )
332366 self .native .exit_config_mode ()
333367
334368 def config_list (self , commands ):
369+ """
370+ Send list of commands to device.
371+
372+ Args:
373+ commands (list): list of commands to be set to device.
374+
375+ Raises:
376+ CommandListError: Message stating which command failed and the response from the device.
377+ """
335378 self ._enter_config ()
336379 entered_commands = []
337380 for command in commands :
@@ -345,7 +388,7 @@ def config_list(self, commands):
345388 @property
346389 def connected_interface (self ) -> str :
347390 """
348- The interface that is assigned an IP Address of ``self.ip_address``.
391+ Interface that is assigned an IP Address of ``self.ip_address``.
349392
350393 Returns:
351394 str: The name of the interfaces associated to ``self.ip_address``.
@@ -415,7 +458,7 @@ def enable_scp(self) -> None:
415458
416459 @property
417460 def facts (self ):
418- """Implement this once facts' re-factor is done. """
461+ """Implement this once facts re-factor is done."""
419462 return {}
420463
421464 def file_copy (
@@ -462,6 +505,25 @@ def file_copy(
462505
463506 # TODO: Make this an internal method since exposing file_copy should be sufficient
464507 def file_copy_remote_exists (self , src , dest = None , file_system = None ):
508+ """
509+ Copy ``src`` file to device.
510+
511+ Args:
512+ src (str): The path to the file to be copied to the device.
513+ dest (str, optional): The name to use for storing the file on the device.
514+ Defaults to use the name of the ``src`` file..
515+ file_system (str, optional): The directory name to store files on the device.
516+ Defaults to discover the default directory of the device.
517+
518+ Returns:
519+ bool: True if the file exists on the device and the md5 hashes match. Otherwise, false.
520+
521+ Example:
522+ >>> status = file_copy_remote_exists("path/to/asa-image.bin")
523+ >>> print(status)
524+ True
525+ >>>
526+ """
465527 self .enable ()
466528 if file_system is None :
467529 file_system = self ._get_file_system ()
@@ -472,6 +534,18 @@ def file_copy_remote_exists(self, src, dest=None, file_system=None):
472534 return False
473535
474536 def install_os (self , image_name , ** vendor_specifics ):
537+ """
538+ Install OS on device.
539+
540+ Args:
541+ image_name (str): Name of the image to be installed.
542+
543+ Raises:
544+ OSInstallError: Message stating the end device could not boot into the new image.
545+
546+ Returns:
547+ bool: True if new image is installed correctly. False if device is already running image_name.
548+ """
475549 timeout = vendor_specifics .get ("timeout" , 3600 )
476550 if not self ._image_booted (image_name ):
477551 self .set_boot_options (image_name , ** vendor_specifics )
@@ -487,7 +561,7 @@ def install_os(self, image_name, **vendor_specifics):
487561 @property
488562 def ip_address (self ) -> Union [IPv4Address , IPv6Address ]:
489563 """
490- The IP Address used to establish the connection to the device.
564+ IP Address used to establish the connection to the device.
491565
492566 Returns:
493567 IPv4Address/IPv6Address: The IP address used by the paramiko connection.
@@ -515,7 +589,7 @@ def ip_address(self) -> Union[IPv4Address, IPv6Address]:
515589 @property
516590 def ipv4_addresses (self ) -> Dict [str , List [IPv4Address ]]:
517591 """
518- The IPv4 addresses of the device's interfaces.
592+ IPv4 addresses of the device's interfaces.
519593
520594 Returns:
521595 dict: The ipv4 addresses mapped to their interfaces.
@@ -531,7 +605,7 @@ def ipv4_addresses(self) -> Dict[str, List[IPv4Address]]:
531605 @property
532606 def ipv6_addresses (self ) -> Dict [str , List [IPv6Address ]]:
533607 """
534- The IPv6 addresses of the device's interfaces.
608+ IPv6 addresses of the device's interfaces.
535609
536610 Returns:
537611 dict: The ipv6 addresses mapped to their interfaces.
@@ -547,7 +621,7 @@ def ipv6_addresses(self) -> Dict[str, List[IPv6Address]]:
547621 @property
548622 def ip_protocol (self ) -> str :
549623 """
550- The IP Protocol of the IP Addressed used by the underlying paramiko connection.
624+ IP Protocol of the IP Addressed used by the underlying paramiko connection.
551625
552626 Returns:
553627 str: "ipv4" for IPv4 Addresses and "ipv6" for IPv6 Addresses.
@@ -584,6 +658,7 @@ def is_active(self):
584658 return self .redundancy_state in self .active_redundancy_states
585659
586660 def open (self ):
661+ """Attempt to find device prompt. If not found, create Connecthandler object to device."""
587662 if self ._connected :
588663 try :
589664 self .native .find_prompt ()
@@ -605,6 +680,12 @@ def open(self):
605680
606681 @property
607682 def peer_device (self ) -> "ASADevice" :
683+ """
684+ Create instance of ASADevice for peer device.
685+
686+ Returns:
687+ :class`~devices.ASADevice`: Cisco ASA device instance.
688+ """
608689 if self ._peer_device is None :
609690 self ._peer_device = self .__class__ (
610691 str (self .peer_ip_address ), self .username , self .password , self .secret , self .port , ** self .kwargs
@@ -617,7 +698,7 @@ def peer_device(self) -> "ASADevice":
617698 @property
618699 def peer_ip_address (self ) -> Union [IPv4Address , IPv6Address ]:
619700 """
620- The IP Address associated with ``self.ip_address`` on the peer device.
701+ IP Address associated with ``self.ip_address`` on the peer device.
621702
622703 Returns:
623704 IPv4Address/IPv6Address: The IP address used by the paramiko connection.
@@ -644,7 +725,7 @@ def peer_ip_address(self) -> Union[IPv4Address, IPv6Address]:
644725 @property
645726 def peer_ipv4_addresses (self ) -> Dict [str , List [IPv4Address ]]:
646727 """
647- The IPv4 addresses of the peer device's interfaces.
728+ IPv4 addresses of the peer device's interfaces.
648729
649730 Returns:
650731 dict: The ipv4 addresses mapped to their interfaces.
@@ -660,7 +741,7 @@ def peer_ipv4_addresses(self) -> Dict[str, List[IPv4Address]]:
660741 @property
661742 def peer_ipv6_addresses (self ) -> Dict [str , List [IPv6Address ]]:
662743 """
663- The IPv6 addresses of the peer device's interfaces.
744+ IPv6 addresses of the peer device's interfaces.
664745
665746 Returns:
666747 dict: The ipv6 addresses mapped to their interfaces.
@@ -789,7 +870,7 @@ def reboot_standby(self, acceptable_states: Optional[Iterable[str]] = None, time
789870 @property
790871 def redundancy_mode (self ):
791872 """
792- The operating redundancy mode of the device.
873+ Operating redundancy mode of the device.
793874
794875 Returns:
795876 str: The redundancy mode the device is operating in.
@@ -852,13 +933,37 @@ def redundancy_state(self):
852933 return redundancy_state .lower ()
853934
854935 def rollback (self , rollback_to ):
936+ """
937+ Rollback the device configuration.
938+
939+ Args:
940+ rollback_to (str): Name of checkpoint file to rollback to
941+
942+ Raises:
943+ NotImplementedError: Function not implemented yet.
944+ """
855945 raise NotImplementedError
856946
857947 @property
858948 def running_config (self ):
949+ """
950+ Get current running config on device.
951+
952+ Returns:
953+ str: Running configuration on device.
954+ """
859955 return self .show ("show running-config" )
860956
861957 def save (self , filename = "startup-config" ):
958+ """
959+ Save changes to startup config.
960+
961+ Args:
962+ filename (str, optional): Name of startup configuration file. Defaults to "startup-config".
963+
964+ Returns:
965+ bool: True if configuration saved succesfully.
966+ """
862967 command = "copy running-config %s" % filename
863968 # Changed to send_command_timing to not require a direct prompt return.
864969 self .native .send_command_timing (command )
@@ -871,6 +976,16 @@ def save(self, filename="startup-config"):
871976 return True
872977
873978 def set_boot_options (self , image_name , ** vendor_specifics ):
979+ """
980+ Set new image as boot option on device.
981+
982+ Args:
983+ image_name (str): AName of image.
984+
985+ Raises:
986+ NTCFileNotFoundError: File not found on device.
987+ CommandError: Unable to issue command on device.
988+ """
874989 current_boot = self .show ("show running-config | inc ^boot system " )
875990 file_system = vendor_specifics .get ("file_system" )
876991 if file_system is None :
@@ -898,10 +1013,32 @@ def set_boot_options(self, image_name, **vendor_specifics):
8981013 )
8991014
9001015 def show (self , command , expect_string = None ):
1016+ """
1017+ Send command to device.
1018+
1019+ Args:
1020+ command (str): Command to be ran on device.
1021+ expect_string (str, optional): Expected response from running command on device. Defaults to None.
1022+
1023+ Returns:
1024+ str: Output from running command on device.
1025+ """
9011026 self .enable ()
9021027 return self ._send_command (command , expect_string = expect_string )
9031028
9041029 def show_list (self , commands ):
1030+ """
1031+ Send list of commands to device.
1032+
1033+ Args:
1034+ commands (list): Commands to be sent to device.
1035+
1036+ Raises:
1037+ CommandListError: Failure running command on device.
1038+
1039+ Returns:
1040+ list: Output from each command sent.
1041+ """
9051042 self .enable ()
9061043
9071044 responses = []
@@ -917,8 +1054,15 @@ def show_list(self, commands):
9171054
9181055 @property
9191056 def startup_config (self ):
1057+ """
1058+ Show startup config.
1059+
1060+ :return: Output of command 'show startup-config'.
1061+ """
9201062 return self .show ("show startup-config" )
9211063
9221064
9231065class RebootSignal (NTCError ):
1066+ """Not implemented."""
1067+
9241068 pass
0 commit comments