
    VhW                         d dl mZmZmZ eZdZdZd dlZd dl	Z	d dl
Z
d dlmZ d dlmZ d dlmZ d dlmZ d d	lmZmZ d d
lmZ d dlmZmZ  G d de      Zy)    )absolute_importdivisionprint_functiona  
author:
- Ansible Networking Team (@ansible-network)
name: ios
short_description: Use ios cliconf to run command on Cisco IOS platform
description:
- This ios plugin provides low level abstraction apis for sending and receiving CLI
  commands from Cisco IOS network devices.
version_added: 1.0.0
options:
  commit_confirm_immediate:
    type: boolean
    default: false
    description:
    - Enable or disable commit confirm mode.
    - Confirms the configuration pushed after a custom/ default timeout.(default 1 minute).
    - For custom timeout configuration set commit_confirm_timeout value.
    - On commit_confirm_immediate default value for commit_confirm_timeout is considered 1 minute
      when variable in not explicitly declared.
    env:
    - name: ANSIBLE_IOS_COMMIT_CONFIRM_IMMEDIATE
    vars:
    - name: ansible_ios_commit_confirm_immediate
  commit_confirm_timeout:
    type: int
    description:
    - Commits the configuration on a trial basis for the time
      specified in minutes.
    - Using commit_confirm_timeout without specifying commit_confirm_immediate would
      need an explicit C(configure confirm) using the ios_command module
      to confirm/commit the changes made.
    - Refer to example for a use case demonstration.
    env:
    - name: ANSIBLE_IOS_COMMIT_CONFIRM_TIMEOUT
    vars:
    - name: ansible_ios_commit_confirm_timeout
  config_commands:
    description:
    - Specifies a list of commands that can make configuration changes
      to the target device.
    - When `ansible_network_single_user_mode` is enabled, if a command sent
      to the device is present in this list, the existing cache is invalidated.
    version_added: 2.0.0
    type: list
    elements: str
    default: []
    vars:
    - name: ansible_ios_config_commands
a  
# NOTE - IOS waits for a `configure confirm` when the configure terminal
# command executed is `configure terminal revert timer <timeout>` within the timeout
# period for the configuration to commit successfully, else a rollback
# happens.

# Use commit confirm with timeout and confirm the commit explicitly

- name: Example commit confirmed
  vars:
    ansible_ios_commit_confirm_timeout: 1
  tasks:
    - name: "Commit confirmed with timeout"
      cisco.ios.ios_hostname:
        state: merged
        config:
          hostname: R1

    - name: "Confirm the Commit"
      cisco.ios.ios_command:
        commands:
          - configure confirm

# Commands fired
# - configure terminal revert timer 1 (cliconf specific)
# - hostname R1 (from hostname resource module)
# - configure confirm (from ios_command module)

# Use commit confirm with timeout and confirm the commit via cliconf

- name: Example commit confirmed
  vars:
    ansible_ios_commit_confirm_immediate: True
    ansible_ios_commit_confirm_timeout: 3
  tasks:
    - name: "Commit confirmed with timeout"
      cisco.ios.ios_hostname:
        state: merged
        config:
          hostname: R1

# Commands fired
# - configure terminal revert timer 3 (cliconf specific)
# - hostname R1 (from hostname resource module)
# - configure confirm (cliconf specific)

# Use commit confirm via cliconf using default timeout

- name: Example commit confirmed
  vars:
    ansible_ios_commit_confirm_immediate: True
  tasks:
    - name: "Commit confirmed with timeout"
      cisco.ios.ios_hostname:
        state: merged
        config:
          hostname: R1

# Commands fired
# - configure terminal revert timer 1 (cliconf specific with default timeout)
# - hostname R1 (from hostname resource module)
# - configure confirm (cliconf specific)

N)AnsibleConnectionFailure)to_text)Mapping)	iteritems)NetworkConfigdumps)to_list)CliconfBaseenable_modec                        e Zd Z fdZedd       Zedd       Z	 	 	 	 	 	 ddZed        Zedd       Z	ddZ
	 	 	 	 	 	 	 ddZd	 Zd
 Zd Zd Z fdZddZddZd Zd Zd Zd Z xZS )Cliconfc                 :    i | _         t        t        |   |i | y N)_device_infosuperr   __init__)selfargskwargs	__class__s      a/home/dcms/DCMS/lib/python3.12/site-packages/ansible_collections/cisco/ios/plugins/cliconf/ios.pyr   zCliconf.__init__   s    gt%t6v6    c                     |dvrt        d|z        |rt        d|z        |sg }|dk(  rd}nd}|dj                  t        |            z  }|j                         }| j	                  |      S )N)runningstartupz/fetching configuration from %s is not supportedz1'format' value %s is not supported for get_configr   zshow running-config zshow startup-config  )
ValueErrorjoinr   stripsend_command)r   sourceflagsformatcmds        r   
get_configzCliconf.get_config   s    //NQWWXXPSYYZZEY(C(Csxx''iik  %%r   c                 N    |st        d      d| | d}| j                  |      S )Nz)'file_name' value is required for restorezconfigure replace z forcer    r#   )r   filenamepathr'   s       r   restorezCliconf.restore   s4    HII"4&
&9  %%r   c           	      n   i }| j                         }| j                         }	||d   rt        d      ||	d   vr#t        d|ddj                  |	d               ||	d   vr#t        d|ddj                  |	d               t	        d	
      }
| j                  |      \  }}|
j                  |       |r=|dk7  r8| j                  |      \  }}t	        d	||      }|
j                  ||||      }n|
j                  }i }|rt        |d      nd|d<   | j                  ||      }|r|ni |d<   |S )aR	  
        Generate diff between candidate and running configuration. If the
        remote host supports onbox diff capabilities ie. supports_onbox_diff in that case
        candidate and running configurations are not required to be passed as argument.
        In case if onbox diff capability is not supported candidate argument is mandatory
        and running argument is optional.
        :param candidate: The configuration which is expected to be present on remote host.
        :param running: The base configuration which is used to generate diff.
        :param diff_match: Instructs how to match the candidate configuration with current device configuration
                      Valid values are 'line', 'strict', 'exact', 'none'.
                      'line' - commands are matched line by line
                      'strict' - command lines are matched with respect to position
                      'exact' - command lines must be an equal match
                      'none' - will not compare the candidate configuration with the running configuration
        :param diff_ignore_lines: Use this argument to specify one or more lines that should be
                                  ignored during the diff.  This is used for lines in the configuration
                                  that are automatically updated by the system.  This argument takes
                                  a list of regular expressions or exact line matches.
        :param path: The ordered set of parents that uniquely identify the section or hierarchy
                     the commands should be checked against.  If the parents argument
                     is omitted, the commands are checked against the set of top
                    level or global commands.
        :param diff_replace: Instructs on the way to perform the configuration on the device.
                        If the replace argument is set to I(line) then the modified lines are
                        pushed to the device in configuration mode.  If the replace argument is
                        set to I(block) then the entire command block is pushed to the device in
                        configuration mode if any line is not correct.
        :return: Configuration diff in  json format.
               {
                   'config_diff': '',
                   'banner_diff': {}
               }
        supports_generate_diffz4candidate configuration is required to generate diff
diff_matchz'match' value z in invalid, valid values are z, diff_replacez'replace' value    )indentnone)r3   contentsignore_lines)r,   matchreplacecommands config_diffbanner_diff)get_device_operationsget_option_valuesr    r!   r
   _extract_bannersload
differenceitemsr   _diff_banners)r   	candidater   r0   diff_ignore_linesr,   r1   diffdevice_operationsoption_valuescandidate_objwant_srcwant_bannershave_srchave_bannersrunning_objconfigdiffobjsbannerss                     r   get_diffzCliconf.get_diff   su   T  668..0!23K!LSTT]<88tyy|)DEG 
 }^<<=+H!IK  &Q/!%!6!6y!A,8$zV+%)%:%:7%C"Hl'q8RcdK*55 $	 6 N +00NLCQeNJ?WY]$$\<@)0gb]r   c                     | j                  d      s| j                  d      r| j                  d      r| j                  d      nd}| j                  j                  d      }| j                  d      }| j                  d      }||dz  kD  rt        d      t	        j
                  d	|      rt        d
      t	        j
                  d|      st        d      | j                  d|        y| j                  d       y)zu
        Enter global configuration mode based on the
        status of commit_confirm
        :return: None
        commit_confirm_timeoutcommit_confirm_immediater2   persistent_command_timeoutzshow archivez"show archive config rollback timer<   z`ansible_command_timeout can't be greater than commit_confirm_timeout Please adjust and try againzArchive.*not.enabledzocommit_confirm_immediate option set, but archiving not enabled on device. Please set up archiving and try againz%%No Rollback Confirmed Change pendingzqExisting rollback change already pending. Please resolve by issuing 'configure confirm' or 'configure revert now'z configure terminal revert timer zconfigure terminalN)
get_option_connectionr#   r    research)r   commit_timeoutrU   archive_staterollback_states        r   	configurezCliconf.configure  s    ??34Hb8c ??#;<  89  *.)9)9)D)DEa)b& --n=M!../STN)NR,?? 2 
 yy0-@ <  99E~V 0   @@PQR23r   c                    i }| j                         }| j                  |||||       g }g }| j                  d      }	|r| j                          t	        |      D ]\  }
t        |
t              sd|
i}
|
d   }|dk7  s"|d   dk7  s+|j                   | j                  d
i |
       |j                  |       ^ | j                  d       |	r| j                  d       nt        d      ||d<   ||d	<   |S )NrT   commandendr   !zconfigure confirmzcheck mode is not supportedrequestresponse )
r=   check_edit_config_capabilityrW   r^   r   
isinstancer   appendr#   r    )r   rD   commitr8   commentresp
operationsresultsrequestscommit_confirmliner'   s               r   edit_configzCliconf.edit_config?  s   //1
))*iRYZ)CDNN	* )!$0%t,D9o%<CFcMNN#44#4#4#<t#<=OOC() e$!!"56 :;;"Y"Zr   c                    i }| j                         }| j                  |||||       g }g }|rd}	| j                  d       t        j                  d       |	|j                  d      dz   z  }	|j                  d      }
|D ]  }|	d|z   dz   z  }	 |	|
dz   z  }	|	dd	}|j                   | j                  di |       |j                  |	       t        j                  d       | j                  d
d       t        j                  d       |j                  | j                  d             |j                  d       ||d<   ||d<   |S )z
        ios_config:
          lines: "{{ macro_lines }}"
          parents: "macro name {{ macro_name }}"
          after: '@'
          match: line
          replace: block
        r:   config terminal皙?r   
r   Tr`   sendonlyra   rx   rc   rd   re   )r=   rf   r#   timesleeppoprh   )r   rD   ri   r8   rj   rk   rl   rm   rn   r9   multiline_delimiterrp   objs                r   
edit_macrozCliconf.edit_macro_  sJ    //1
))*iRYZH/0JJsO	a(4//H"+--"3! .C$J--.+d22H&D9CNN,4,,3s34OOH%JJsOed3JJsONN4,,T23OOD!"Y"Zr   c                 j    |st        d      |rt        d|z        | j                  ||||||      S )Nz(must provide value of command to executez*'output' value %s is not supported for get)r`   promptanswerrx   newline	check_allr*   )r   r`   r   r   rx   r   outputr   s           r   getzCliconf.get  sQ     GHHIFRSS   ! 
 	
r   c                 T    d}	 | j                  d       |S # t        $ r d}Y |S w xY w)NL2z	show vlanr`   L3)r   	Exception)r   device_types     r   check_device_typezCliconf.check_device_type  s>    	HH[H)   	K	s    ''c                    | j                   s_i }d|d<   | j                  dd       | j                  d      }t        |d	      j	                         }t        j                  d
|      }|r#|j                  d      j	                  d      |d<   ddg}|D ]S  }t        j                  ||t
        j                        }|s+|j                  d      j                  d      }|d   |d<    n t        j                  d|t
        j                        }|r|j                  d      |d<   t        j                  d|      }|r|j                  d      |d<   | j                         |d<   || _         | j                   S )Nios
network_osz)#ra   )config_contextexit_commandzshow versionr   surrogate_or_stricterrorszVersion (\S+)r2   ,network_os_versionz^[Cc]isco (.+) \(revisionz"^[Cc]isco (\S+).+bytes of .*memoryr   r   network_os_modelz^(.+) uptimenetwork_os_hostnamezimage file is "(.+)"network_os_imagenetwork_os_type)r   _update_cli_prompt_contextr   r   r"   rY   rZ   groupMsplitr   )r   device_inforeplydatar7   model_search_strsitemversions           r   get_device_infozCliconf.get_device_info  sf     K(-K%++4e+THH^H4E5)>?EEGDII.5E49KKN4H4H4M01 -5! * 		$bdd3#kk!n2237G6=ajK 23 IIotRTT:E5:[[^12II5t<E27++a../-1-C-C-EK)* +D   r   c                     ddddddddddddS )NTF)supports_diff_replacesupports_commitsupports_rollbacksupports_defaultssupports_onbox_diffsupports_commit_commentsupports_multiline_delimitersupports_diff_matchsupports_diff_ignore_linesr/   supports_replacere   r   s    r   r=   zCliconf.get_device_operations  s-    %)$!&!%#(',,0#'*.&* %
 	
r   c                     dgg dddgg dS )Ntext)rp   strictexactr4   rp   block)r&   r0   r1   r   re   r   s    r   r>   zCliconf.get_option_values  s    h=#W-	
 	
r   c                     t         t        |          }|dxx   g dz  cc<   | j                         |d<   |j	                  | j                                t        j                  |      S )Nrpc)edit_bannerrQ   run_commandsget_defaults_flagrG   )r   r   get_capabilitiesr=   updater>   jsonr   )r   resultr   s     r   r   zCliconf.get_capabilities  sY    w68uYY&*&@&@&B"#d,,./zz&!!r   c           	         i }t        j                  |      }g }g }|rt        |      D ]  \  }}	|d|z  z  }| j                  dd       ||	|fD ]9  }
|
dd}|j	                   | j                  di |       |j	                  |
       ; | j                  dd       t        j                  d       |j	                  | j                  d             |j	                  d        ||d	<   ||d
<   |S )ab  
        Edit banner on remote device
        :param banners: Banners to be loaded in json format
        :param multiline_delimiter: Line delimiter for banner
        :param commit: Boolean value that indicates if the device candidate
               configuration should be  pushed in the running configuration or discarded.
        :param diff: Boolean flag to indicate if configuration that is applied on remote host should
                     generated and returned in response or not
        :return: Returns response of executing the configuration command received
             from remote host
        z %srs   Try   rw   ra   rt   ru   rc   rd   re   )r   loadsr	   r#   rh   rz   r{   )r   rD   r}   ri   rk   banners_objrm   rn   keyvaluer'   r~   s               r   r   zCliconf.edit_banner  s    jj+'4 &
Uu222!!"3d!C(;< )C&)t<CNN#44#4#4#;s#;<OOC()
 !!%$!7

3t0067%& #Y"Zr   c           	      f   |t        d      t               }t        |      D ]\  }t        |t              sd|i}|j                  dd       }|rt        d|z        	  | j                  di |}|j                  |       ^ |S # t        $ r#}|r t        |dt        |            }Y d }~<d }~ww xY w)Nz'commands' value is requiredr`   r   z3'output' value %s is not supported for run_commandserrre   )r    listr   rg   r   r|   r#   r   getattrr   rh   )r   r9   check_rc	responsesr'   r   outes           r   r   zCliconf.run_commands  s    ;<<F	8$ 	"Cc7+ #&WWXt,F !VY_!_``4'd''.#. S!	""  , 4a
34s   B	B0B++B0c                 
   | j                  d      }t        |d      }t               }|j                         D ]C  }|j	                         s|j                  |j	                         j                         d          E d|v ryy)z
        The method identifies the filter that should be used to fetch running-configuration
        with defaults.
        :return: valid default filter
        zshow running-config ?surrogate_then_replacer   r   allfull)r   r   set
splitlinesr"   addr   )r   r   r9   rp   s       r   r   zCliconf.get_defaults_flag#  sv     hh./c":;5NN$ 	6Dzz|TZZ\//1!45	6 Hr   c                 ~   | j                   j                  r| j                   j                         }|#t        d| j                   j                  z        t        j                  dt        |d      j                               r8| j                   j                  dd       | j                   j                  d	       yyy)
zT
        Make sure we are in the operational cli mode
        :return: None
        NzGcli prompt is not identified from the last received response window: %s)messagezconfig.*\)#r   r   vvvvz$wrong context, sending end to devicera   )rX   	connected
get_promptr   _last_recv_windowrY   rZ   r   r"   queue_messager#   )r   r   s     r   set_cli_prompt_contextzCliconf.set_cli_prompt_context6  s    
 %%""--/C{.+-1-=-=-O-OP 
 yy=U)V)\)\)^_  ..v7]^  --e4 ` &r   c                    i }t        j                  d|t         j                        }|D ]V  }d|z  }t        j                  ||t         j                        }|s0d|z  }|j                  d      j                         ||<   X |D ]Y  }d|z  }t        j                  ||t         j                        }|s0|j                  t        |j                  d            d      }[ t        j                  dd|      }||fS )Nz^banner (\w+)zbanner %s \^C(.+?)(?=\^C)z	banner %sr2   r:   zbanner \w+ \^C\^Cz!! banner removed)
rY   findallr   rZ   Sr   r"   r8   strsub)r   configrP   banner_cmdsr'   regexr7   r   s           r   r?   zCliconf._extract_bannersH  s    jj!16244@ 	6C036EIIeVRTT2E!C'${{1~335	6  	AC036EIIeVRTT2EEKKN(;R@		A ,.A6Jwr   c                 d    i }t        |      D ]  \  }}||j                  |      k7  s|||<   ! |S r   )r	   r   )r   wanthaverD   r   r   s         r   rC   zCliconf._diff_banners[  s?    	#D/ 	'JC%!&	#	' r   )r   NN)Nr:   )NNrp   NNrp   )NTNN)NNNFTNF)N@T)NT)__name__
__module____qualname__r   r   r(   r-   rQ   r^   rq   r   r   r   r   r=   r>   r   r   r   r   r   r?   rC   __classcell__)r   s   @r   r   r      s    7 & && & & Tl (4 (4T  >%R 
0"!H

"!F0&5$&r   r   )
__future__r   r   r   type__metaclass__DOCUMENTATIONEXAMPLESr   rY   rz   ansible.errorsr   ansible.module_utils._textr   /ansible.module_utils.common._collections_compatr   ansible.module_utils.sixr	   Pansible_collections.ansible.netcommon.plugins.module_utils.network.common.configr
   r   Oansible_collections.ansible.netcommon.plugins.module_utils.network.common.utilsr   Gansible_collections.ansible.netcommon.plugins.plugin_utils.cliconf_baser   r   r   re   r   r   <module>r      sZ   & A @ 0d?B  	  3 . C . dBk Br   