
    VhA                        d Z ddlmZmZmZ eZddlZddl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Zd	d
eZdZ	 ddlmZ dZ	 ddlZdZdZ edddddddddd
      Z edPi ddddddddddd d!d"d#d$d%d&d'd(d)d*dd+dd,dd-d!d.d#d/d%d0d'd1d)Z  ed23      Z! ejD                  e#      Z$d4Z%d5Z&	 dd6l'm(Z( dZd7 Z)d8 Z*d9 Z+d: Z,d; Z-d< Z.d= Z/d> Z0d? Z1dQd@Z2dA Z3dB Z4dC Z5dRdDZ6dE Z7dF Z8dG Z9dH Z:dI Z;dSdJZ<dTdKZ=er G dL dMej|                        Z? G dN dOe@      ZAy# e$ r dZY w xY w# e$ rZdZeZY dZ[dZ[ww xY w# e$ r dZY w xY w# e$ r dZY w xY w)Uz
netapp.py
    )absolute_importdivisionprint_functionN)missing_required_lib)	to_native)__version__unknownz22.14.0z%s/)zapiTF   i  i@B i ʚ;l    J)l     I5 l     NZol     @=7M.cl      B3v^!< )
bytesbkbmbgbtbpbebzbybr   r   ki   mi   gi   @tl        pl           el            zl            yl               r   r   r   r   r   r   r   r   z/This module is expected to run as cluster admin)
no_cserverz/tmp/ontap_apis.logaw  With version 22.0.0 ONTAPI (ZAPI) has been deprecated. The final ONTAP version to support ZAPI is ONTAP 9.13.1.  ZAPI calls in these modules will continue to work for ONTAP versions that supports ZAPI.  You can update your playbook to use REST by adding use_rest: always to your playbook.  More information can be found at: https://github.com/ansible-collections/netapp.ontap)ElementFactoryc                      t         S N)HAS_NETAPP_LIB     l/home/dcms/DCMS/lib/python3.12/site-packages/ansible_collections/netapp/ontap/plugins/module_utils/netapp.pyhas_netapp_libr'   {   s    r%   c                  &    dt        t              z  S )NzBError: the python NetApp-Lib module is required.  Import error: %s)strIMPORT_EXCEPTIONr$   r%   r&   netapp_lib_is_requiredr+      s    ORUVfRgggr%   c                      t         S r"   )
HAS_SF_SDKr$   r%   r&   
has_sf_sdkr.      s    r%   c                  2   t        t        dd      t        dddg      t        dddgd      t        dd	d
      t        dd	d
      t        dd      t        dd      t        ddd
      t        dd      t        dd      t        ddd            S )NTr)   requiredtypeFuserr1   r2   aliasespassr1   r2   r5   no_logboolr1   r2   defaultintneverdictr1   r2   r8   )hostnameusernamepasswordhttpsvalidate_certs	http_portontapiuse_restfeature_flagscert_filepathkey_filepathr>   r$   r%   r&   na_ontap_zapi_only_specrL      s     t%0u56(Cu56(4PE>UFE2U/u5'BE7E65uUC r%   c                  J   t        t        dd      t        dddg      t        dddgd      t        dd	d
      t        dd	d
      t        dd      t        dd      t        ddd
      t        dd      t        dd      t        ddd      t        dd            S )NTr)   r0   Fr3   r4   r6   r7   r9   r:   r<   autor>   r?   )r@   rA   rB   rC   rD   rE   rF   rG   rH   rI   rJ   force_ontap_versionrK   r$   r%   r&   na_ontap_host_argument_specrP      s     t%0u56(Cu56(4PE>UFE2U/u5&AE7E65uUC %e< r%   c                  2   t        t        dd      t        dddg      t        dddgd      t        dd	d
      t        dd	d
      t        dd      t        ddd
      t        dd      t        dd      t        ddd      t        dd            S )NTr)   r0   Fr3   r4   r6   r7   r9   r:   r<   alwaysr>   r?   )r@   rA   rB   rC   rD   rE   rG   rH   rI   rJ   rO   rK   r$   r%   r&   na_ontap_rest_only_specrS      s     t%0u56(Cu56(4PE>UFE2u5(CE7E65uUC %e< r%   c                      t               } | j                  d       | j                         D ]  }d|v s|j                  d        | S )NrH   r;   )rP   popvalues)specvalues     r&    na_ontap_host_argument_spec_peerrY      sF    &(DHH_ !IIi ! Kr%   c                 j    t        | |      }t        |t              r|S | j                  d|z         y )Nz.Error: expected bool type for feature flag: %smsg)get_feature
isinstancer9   	fail_json)modulefeature_namefeatures      r&   has_featurerc      s4    &,/G'4 
ILXYr%   c                 &   t        di ddddddddddddd	dd
dddgdddddddg ddg ddddddd}| j                  d   #|| j                  d   v r| j                  d   |   S ||v r||   S | j                  d|z         y)zW if the user has configured the feature, use it
        otherwise, use our default
    strict_json_checkT
trace_apisFtrace_headerstrace_auth_argscheck_required_params_for_noneclassic_basic_authorizationdeprecation_warningsanitize_xmlsanitize_code_points   show_modifiedalways_wrap_zapiflexcache_delete_return_timeout   svm_allowable_protocols_rest)cifsfcpiscsinvmenfsndmps3svm_allowable_protocols_zapi)rt   ru   rv   rw   rx   ry   httpmax_files_change_thresholdr   )warn_or_fail_on_fabricpool_backend_changefailno_cserver_emsrH   Nz+Internal error: unexpected feature flag: %sr[   r$   )r>   paramsr_   )r`   ra   default_flagss      r&   r]   r]      s       	
 (, %* !   S   )* &[ &]  $%!" 39#$ %M* }}_%1lfmmTcFd6d}}_-l;;}$\**
FUVr%   c                    t         s| j                  d       || j                  }d\  }}dD cg c]  }|j                  |      r| }}|r)t	        |      dkD  rdnd}dj                  |      d	|d
}dD cg c]  }|j                  |      s| }}|r)t	        |      dkD  rdnd}dj                  |      d	|d}|r	|r|d|n|xs |}|r| j                  |       |j                  d      }	|j                  d      }
|j                  d      }	 t        j                  |	|
||      S c c}w c c}w # t        $ r}t        d|z        d }~ww xY w)Nz+the python SolidFire SDK module is requiredr[   NN)r@   rA   rB   r   areis,  z# required for ElementSW connection.)rI   rJ   z( not supported for ElementSW connection.  r@   rA   rB   )portz"Unable to create SF connection: %s)	r-   r_   r   getlenjoinr    create	Exception)r`   r   host_optionsr\   msg2optionmissing_optionsverbextra_optionsr@   rA   rB   excs                r&   create_sf_connectionr      sl   JK}}IC,Pq&XdXhXhioXpvqOqO,q0ud<@IIo<VX\]*Kh|O_O_`fOgVhMhM*Q.uDBF))MBZ\`a$'Dc4
 ckTC
S!
+H
+H
+HD$$XxMM! r i  D<sBCCDs/   D6D6<D;D;E   	E	EEc                     d }d }||||dnd}n.|dnd}n'||||d}nt        | d      rdnd}nd	}|||d
z  }|r| j                  |       |S )Nz1Error: cannot have a key file without a cert filezIError: ONTAP module requires username/password or SSL certificate file(s)single_certcert_keyzpError: cannot have both basic authentication (username/password) and certificate authentication (cert/key files)rj   
basic_authspeedy_basic_authz9Error: username and password have to be provided togetherz* and cannot be used with cert or key filesr[   )rc   r_   )r`   rA   rB   rI   rJ   errorauth_methods          r&   set_auth_methodr     s    EKH, LXLdHe  ,8+?-ZK		("6$(@FE +6f>[*\,buKK$(@AAEU#r%   c                 
    ddg}ddg}t         fd|D              }t         fd|D              }|r|r|j                  d       |r|}n|r|}ng }|D ]+  } j                  |      ||vs|j                  |    |<   - y	)
a&  if an option is not set, use primary value.
       but don't mix up basic and certificate authentication methods

       host_options is updated in place
       option values are read from module.params
       keys is a list of keys that need to be added/updated/left alone in host_options
    rA   rB   rI   rJ   c              3   D   K   | ]  }j                  |      d u  y wr"   r   .0xr   s     r&   	<genexpr>z8setup_host_options_from_module_params.<locals>.<genexpr>-  s!     N1|''*$6N    c              3   D   K   | ]  }j                  |      d u  y wr"   r   r   s     r&   r   z8setup_host_options_from_module_params.<locals>.<genexpr>.  s!     Ta,**1-T9Tr   zvError: host cannot have both basic authentication (username/password) and certificate authentication (cert/key files).r[   N)anyr_   r   r   )	r   r`   keyspassword_keyscertificate_keysuse_passworduse_certificateexclude_keyskeys	   `        r&   %setup_host_options_from_module_paramsr   #  s      ,M'8NNNLTCSTTO I 	 	J'	$ 3C (S-D &c 2L3r%   c                    |rU|d}d}|du rQt         j                  j                  dd      s1t        t        dd       r t        j
                  t        _        n|d}d}| j                  |       | j                  |       y )	Ni  HTTPSFPYTHONHTTPSVERIFY _create_unverified_contextP   HTTP)	osenvironr   getattrsslr   _create_default_https_contextset_transport_typeset_port)serverrC   r   rD   transport_types        r&   set_zapi_port_and_transportr   >  s    <D U"2::>>:Mr+RW^_b  eA  CG  XH030N0NC-<D
n-
OODr%   c                 @   | j                  t               || j                  }|j                  d      }|j                  d      }|j                  d      }|j                  d      }|j                  d      }|j                  d      }	|j                  d      }
|j                  d      }|j                  d	      }t	        | d
      }|r*t        j                  t        t
        j                  d       |t	        | d      z  }t        | ||||      }t        s| j                  t                      |dv r0t        || |||
||t        j                  j                   ||
      }d}	n3|dk(  s|rt        || |||
||      }nt        j                  ||||      }|r|j#                  |       |j                  d      dk(  r'|	rdnd}| j                  d| j$                  d|       t'        ||	||
       |j)                  d|xs d       |j+                  d       |S )Nr@   rA   rB   rI   rJ   rC   rD   rE   rF   rf   '%(asctime)s %(levelname)-8s %(message)sfilenamelevelformatrp   r[   )r   r   )	r`   rA   rB   rD   rI   rJ   styler   traceTr   )r`   rA   rB   rD   r   r   )rA   rB   r   rG   rR   r   z  Note: https is set to false.zUsing ZAPI for z, ignoring 'use_rest: always'.r   n   )majorminorFILER)warnZAPI_DEPRECATION_MESSAGEr   r   rc   loggingbasicConfigLOG_FILEDEBUGr   r#   r_   r+   OntapZAPICxr   NaServerSTYLE_CERTIFICATEset_vserver_namer   set_api_versionset_server_type)r`   vserver	wrap_zapir   r@   rA   rB   rI   rJ   rC   rD   r   versionr   r   r   notes                    r&   setup_na_ontap_zapir   O  s   
KK()}}
+H
+H
+H $$_5M##N3LW%E!%%&67NK(Dx(G-EXW]]KtuV%788I!&(Hm\ZK356 11XfxRZ,:-*6dmm>]>])4EC
 	+	+y XfxRZ,:[`b x(XUZ[7#
#x/r @6<<Y]^_t^D
7>c;
7#Mr%   c                     	 t        | t              rt        | d   t              ryt        | t              xr | j                  d      S # t        $ r Y .w xY w)z) return True if it is a connection issue r   T)URLErrorUnauthorized)r^   tupleConnectionError	NameErrorr)   
startswithmessages    r&   is_zapi_connection_errorr     sU    gu%*WQZ*Q gs#X(:(:;W(XX  s   #A	 		AAc                 N    t        | t              r| j                  d      rd| v S y)z+ return True if it is a write access error zInsufficient privileges:zdoes not have write accessF)r^   r)   r   r   s    r&   is_zapi_write_access_errorr     s*     '3G$6$67Q$R+w66r%   c                 .    t        | t              xr | dv S )z. return True if it is a missing vserver error )z&Vserver API missing vserver parameter.zSpecified vserver not found)r^   r)   r   s    r&   is_zapi_missing_vserver_errorr     s     gs#|3|(||r%   c                    t        j                  d      }t        j                  j                  di ddi}t        j                  d      }|j                  |       |j                  |       	 | j	                  |d      }|j                  d	      }|$|j                  d      }||j                  d
      S y# t         j
                  $ r!}t        |j                        rY d}~y|d}~ww xY w)z9 returns None if not run on the management or cluster IP zvserver-get-itervserver-infozvserver-typeadminqueryFenable_tunnelingNzattributes-listzvserver-name)r   )
r   	NaElementcreate_node_with_childrenadd_child_eleminvoke_successfully
NaApiErrorr   r   get_child_by_nameget_child_content)r   vserver_infoquery_detailsr   resultr   attribute_listvserver_lists           r&   get_cserver_zapir    s    >>"45LNN<<iP^`gOhiMNN7#E	'&	++L=B , D --.?@N!%77G#11.AA ??  $CKK0	s   /B: :C.C)'C))C.c                 L   	 t        | j                        }	 | j                  }|dk(  r%|j                  d      rd|v rddt        |       z  fS |dk(  r|j                  d	      rd
t        |       fS dt        |       fS # t        t        f$ r d}Y zw xY w# t        $ r d}Y ~w xY w)z return type of error r   r   i2  zUnable to find API:zdata vservermissing_vserver_api_errorz6Most likely running a cluster level API as vserver: %si2  zRPC: Couldn't make connection	rpc_errorother_error)r<   codeAttributeError
ValueErrorr   r   r   )r   err_codeerr_msgs      r&   classify_zapi_exceptionr    s    uzz?-- 5W//0EF>]dKd*,dgpqvgw,www5W//0OPIe,,,)E*** J' 
  s"   A> B >BBB#"B#c                     |st        |       S ddi}d}| j                  ||      \  }}||y |j                  d      }|,|D ]  }|d   dk(  s|d   c S  t        |      dk(  r|d   d   S y )	Nfieldsr2   zprivate/cli/vserverrecordsr   r   r   r   )r  r   r   )
connectionis_restr   apijsonr   vserversr   s           r&   get_cserverr    s    
++F
C..f-KD%|u(xx	"H 	*Gv')y))	* x=AA;y))r%   c                 n    t        |       }|||d<   |r||d<   |r||d<   |r|j                  |       |S )N)changedresponsemodifyactions)r>   update)r  r  r  r  extra_responsesr   s         r&   generate_resultr    sJ    '"F%z!x#yo&Mr%   c                        e Zd ZdZdej
                  j                  ej
                  j                  ej
                  j                  dddddddddf fd	Z	d Z
d Zd Z fdZd fd		Zdd
Z xZS )r   z override zapi NaServer class to:
        - enable SSL certificate authentication
        - ignore invalid XML characters in ONTAP output (when using CLI module)
        - add Authorization header when using basic authentication
        NFc           
         t         t        |   ||||||||       |
| _        || _        || _        |	| _        d | _        |dk(  r>|d|}t        j                  |j                               j                         | _        y y )N)server_typer   r   rA   rB   r   r   r   :)superr   __init__rI   rJ   rD   r`   base64_credsbase64	b64encodeencodedecode)selfr@   r  r   r   rA   rB   r   r   r`   rI   rJ   rD   r   auth	__class__s                  r&   r"  zOntapZAPICx.__init__  s     +t-hK=K49H7?dRW . Y "/D ,D"0D DK $D11"*H5$*$4$4T[[]$C$J$J$L! 2r%   c                    	 t        j                         }| j                  sd_        t         j                  |_        	 j                  | j                  | j                         t        j                  j                  j                        S # t        $ r}| j                  d|       Y d }~d }~ww xY w# t        $ r}| j                  d|       Y d }~rd }~ww xY w)Nz<SSL certificate authentication requires python 2.7 or later.F)keyfilez/Cannot load SSL certificate, check files exist.)context)r   create_default_contextr  _fail_with_exc_inforD   check_hostname	CERT_NONEverify_modeload_cert_chainrI   rJ   IOErrorr   urllibrequestHTTPSHandler)r(  r-  r   s      r&    _create_certificate_auth_handlerz,OntapZAPICx._create_certificate_auth_handler  s    n446 &&).&&)mm#a''(:(:DDUDU'V ;;&&33G3DD " n(()gilmmn  a(()Z\_``as.   B 'B8 	B5B00B58	CCCc                 b    |}|dt        |      z  z  }| j                  j                  |       y )Nz  More info: %sr[   )reprr`   r_   )r(  arg0r   r\   s       r&   r/  zOntapZAPICx._fail_with_exc_info  s0    C$tCy00CKK!!c!*r%   c                    |j                  dd      }|j                  dd      }t        | j                  d      D ]L  }t        dg      dk(  rt        |g      }nt	        d      dk(  rt	        |      }nd}|j                  |d      }N |S )Ns   
r%   s   
rm   rn         .)replacer]   r`   r   chr)r(  r  new_response
code_pointbytes        r&   rl   zOntapZAPICx.sanitize_xml  s    #++Is;L'//SAL)$++7MN @
!:( *.DVw&z?DD+33D$?@  r%   c                 f   	 t         t        |   |      S # t        j                  j
                  $ r}}t        | j                  d      r7	 t         t        |   | j                  |            cY d}~S # t        $ r Y nw xY w	 |xj                  d|z  z  c_
        |# t        $ r Y |w xY wd}~ww xY w)z  handling XML parsing exception rl   Nz.  Received: %s)r!  r   _parse_responser   etreeXMLSyntaxErrorrc   r`   rl   r   r\   )r(  r  r   r*  s      r&   rE  zOntapZAPICx._parse_response*  s    [$?II::,, t{{N;$[$GHYHYZbHcdd$ GG08;;G 	 ! 	s\    B0B+
!A1+B01	A=:B+<A==B+BB+	B($B+'B((B++B0c                     t         t        |   ||      \  }}|j                  dt        | j
                  j                  z         | j                  |j                  dd| j                  z         ||fS )z= intercept newly created request to add Authorization header r   X-Dot-Client-AppAuthorizationzBasic %s)r!  r   _create_request
add_headerCLIENT_APP_VERSIONr`   r   r#  )r(  
na_elementr   r6  netapp_elementr*  s        r&   rK  zOntapZAPICx._create_request=  sr    &+K&Nzl|&N&}#G^13EHYHY3YZ  ,""?JARAR4RSN**r%   c                    |rt        |t        j                        st        d      | j	                  ||      \  }}| j
                  r0t        j                  j                  d|j                  d             t        | d      r| j                  r| j                  r| j                          	 t        | d      r(| j                  j                  || j                        }n| j                  j                  |      }|j5                         }	| j7                  |	      }
| j
                  r0t        j                  j                  d|
j                  d             |
S # t        j                  j                   j"                  $ r/}t        j$                  |j&                  |j(                        d}~wt        j                  j                   j*                  $ ra}d	}t-        |      }	 t        |j(                  t.              rd
}|j0                  }n# t2        $ r Y nw xY wt        j$                  ||      d}~wt2        $ r$}t        j$                  dt-        |            d}~ww xY w)zInvoke the API on the server.z(NaElement must be supplied to invoke APIzRequest: %sT)pretty_opener_timeout)timeoutNz	URL errorzUnable to connectzUnexpected errorzResponse: %s)r^   r   r   r  rK  _traceLOGdebug	to_stringhasattrrR  _refresh_conn_build_openeropenrS  r5  r   	HTTPErrorr   r  reasonr   r:  ConnectionRefusedErrorargsr   read_get_result)r(  rN  r   r6  request_elementr  r   r\   r   response_xmlresponse_elements              r&   invoke_elemzOntapZAPICx.invoke_elemF  s   Z
DNN%K !KLL'+';';J<L(N$G_ {{}o.G.Gt.G.TU4+4<<))""$E4,#||00$--0PH#||009H" $==?L#//={{~/?/I/IQU/I/VW##- ;;$$.. <oochh

;;;;$$-- 
2!S	!#**.DE1 #  ooc511 Eoo&8$s)DDEsU   .AE 'I#*F--*I#H3%(HH3	HH3HH33I#?II#F)__name__
__module____qualname____doc__r   r   SERVER_TYPE_FILERTRANSPORT_TYPE_HTTPSTYLE_LOGIN_PASSWORDr"  r8  r/  rl   rE  rK  rf  __classcell__)r*  s   @r&   r   r     sm    	
 %)dmm6U6U$(MM$E$E===="U4#'d4!%	M(	E 	+
	  	&	+)	$r%   r   c                       e Zd ZdZd"dZd Zd#dZd$dZd%dZd%dZ	d	 Z
d&d
Zd&dZd Zd Zd'dZd(dZd&dZd&dZd&dZd(dZd Zd Zd Zd Zd Zd Zd&dZd)dZd&dZd Zd Zd*dZ d*d Z!d*d!Z"y)+OntapRestAPIz- wrapper to send requests to ONTAP REST APIs Nc                 T   ||j                   n|| _        || _        | j                  j                  d      | _        | j                  j                  d      | _        | j                  d   | _        | j                  d   j                         | _        | j                  j                  d      | _	        | j                  j                  d      | _
        | j                  d   | _        || _        | j                  d   }| j                  j                  d	      | _        |d
| j                  z  | _        nd| j                  |fz  | _        d | _        d | _        t#        ddddd      | _        g | _        g | _        t+        | j                  | j                  | j
                  | j                  | j                        | _        | j/                          t1        |d      r*t3        j4                  t6        t2        j8                  d       t1        |d      | _        t1        |d      | _        y )NrA   rB   r@   rG   rI   rJ   rD   rE   rO   zhttps://%s/api/zhttps://%s:%d/api/r	   F)full
generationr   r   validrf   r   r   rg   rh   )r   r   r`   r   rA   rB   r@   lowerrG   rI   rJ   verifyrT  rO   urlis_rest_errorfallback_to_zapi_reasonr>   ontap_versionerrors
debug_logsr   r   check_required_libraryrc   r   r   r   r   log_headerslog_auth_args)r(  r`   rT  r   r   s        r&   r"  zOntapRestAPI.__init__t  s   -9-AFMM|))--j9))--j9))*5))*5;;=!..22?C --11.A''(89  -#'#4#4#8#89N#O <(4==8DH+t}}d.CCDH!'+$!
 *4;;t}}VZVhVhjnj{j{|##%v|,Oxy&v?(1BCr%   c                 $    | j                  |      S r"   )requires_ontap_version)r(  module_names     r&   requires_ontap_9_6zOntapRestAPI.requires_ontap_9_6  s    **;77r%   c                 P    | j                   d| j                   z  nd}|d|d|S )N - %sr   z( only supports REST, and requires ONTAP z
 or later.)rz  )r(  r  r   suffixs       r&   r  z#OntapRestAPI.requires_ontap_version  s/    151C1C1O4---UWMXZacijjr%   c                 b   | j                         }| j                  d| j                  z  nd}|dk7  r|d|z  z  }||d|rdndz  z  }t        |t              rt	        |      dkD  rd	|z  }n8t        |t              rt	        |      dk(  rt        |d
         }nt        |      }d|d|d|dS )Nr  r   rs  rs  rs  z - ONTAP version: %s.%s.%sz - using %sRESTZAPIr   z	any of %sr   zusing z requires ONTAP z" or later and REST must be enabled.)get_ontap_versionrz  r^   listr   r)   )r(  optionsr   rG   current_versionr  tags          r&   options_require_ontap_versionz*OntapRestAPI.options_require_ontap_version  s    002151C1C1O4---UWl*2_DDFmvvFFFgt$W)9'C&3w<1+<gaj/Cg,CTWY`bhiir%   c                 6    |xr | j                         |||fk\  S r"   )r  )r(  rG   minimum_generationminimum_majorminimum_minors        r&   meets_rest_minimum_versionz'OntapRestAPI.meets_rest_minimum_version  s$    jD2249K]\i8jjjr%   c                     | j                         }g }| j                  dk(  r|j                  d| j                  z         d| _        | j                  r|j                  d| j                  z         |dk7  r|j                  d|z         |r+| j                  j                  dj                  |             | j                         }||||fk  r@d	| j                  |d
|||fz        z   }|d|z  z  }| j                  j                  |       y y )Nr=   z?Error: REST is required for this module, found: "use_rest: %s".rR   z(Error using REST for version, error: %s.   z.Error using REST for version, status_code: %s.r   r[   Error: z%d.%d.%dz  Found: %s.%s.%s.)	get_ontap_version_using_restrG   appendrz  r`   r_   r   r  r  )	r(  r  r  r  r  status_codemsgsr   r\   s	            r&    fail_if_not_rest_minimum_versionz-OntapRestAPI.fail_if_not_rest_minimum_version  s   779==G#KKY\`\i\iij KKBTEWEWWX#KKH;VWKK!!diio!6((*(-GGd99+zUgiv  yF  UG  HG  H  HC''11CKK!!c!* Hr%   c                 \    t         s&| j                  j                  t        d             y y )Nrequestsr[   )HAS_REQUESTSr`   r_   r   r(  s    r&   r  z#OntapRestAPI.check_required_library  s%    KK!!&::&F!G r%   c                 n    dt         | j                  j                  z  i}|||d<   |||d<   |||d<   |S )NrI  acceptzX-Dot-SVM-NamezX-Dot-SVM-UUID)rM  r`   r   )r(  r  vserver_namevserver_uuidheaderss        r&   build_headerszOntapRestAPI.build_headers  sS    %'9DKK<M<M'MN &GH#(4G$%#(4G$%r%   c           
      v      j                   |z   } fd} j                  |||||| |             \  }	}
}|	|
|fS )zC send http request and process reponse, including error conditions c                  F   j                   dk(  rt        j                        } | S j                   dk(  r$t        j                  j                  f      } | S j                   dv r$t        j                  j
                  f      } | S t        j                         )Nr   )certr   )r   r   )r)  )r   r>   rI   rJ   rA   rB   KeyError)kwargsr(  s    r&   get_auth_argsz0OntapRestAPI.send_request.<locals>.get_auth_args  s    =04#5#56 M !!Z/D$6$68I8I#JK M !!%HHDMM4==#AB M t//00r%   )ry  _send_request)r(  methodr  r   r  r  filesry  r  r  	json_dicterror_detailss   `           r&   send_requestzOntapRestAPI.send_request  sO    hhn
	 150B0B63PVX\^egln{n}0~-YI}44r%   c                     d }d }	d }
d }| j                         } fdfd} j                  dt        t        | j                  | j
                  | j                  r|nd j                  r|nd                   	 t        j                  |f j                  | j
                  |||d|}|j                  } j                  ||j                         |j                           ||      \  }	}
|
 j#                  |d
||
fz         |
}|sc|	sa|	i }	dk(  rj*                  j-                  d      |	d<   j*                  j-                  dd      j/                  d      r|j0                  |	d<   ||	|fS # t        j                  j                  $ rP}	  |      \  }}
n# t        t         f$ r d }
Y nw xY w|
  j#                  |d|z         t%        |      }Y d }~d }~wt        j                  j&                  $ r+} j#                  |d|z         t%        |      }Y d }~3d }~wt(        $ r+} j#                  |d	|z         t%        |      }Y d }~ed }~ww xY w)Nc                     dk(  r@t        j                  d      r)| j                  }t        |      dkD  rt	        d|z        yyy)zjson() may fail on an empty value, but it's OK if no response is expected.
               To avoid false positives, only report an issue when we expect to read a value.
               The first get will see it.
            GETre   r   zExpecting json, got: %sN)rc   r`   contentr   r  )r  contentsr  r(  s     r&   fail_on_non_empty_valuez;OntapRestAPI._send_request.<locals>.fail_on_non_empty_value  sO    
 ;t{{<O#P#++x=1$$%>%IJJ % $Qr%   c                 z    	 | j                         }||j                  d      fS # t        $ r  |        Y yw xY w)z, extract json, and error message if present r   r   )r  r  r   )r  r  r  s     r&   get_jsonz,OntapRestAPI._send_request.<locals>.get_json  sE    "}} '***  "'1!"s   & ::sendingredacted)r  ry  rx  r   rT  r  r  	auth_args)rx  r   rT  r  r  r  zHTTP error: %szConnection error: %szOther error: %szEndpoint error: %d: %sOPTIONSAllowzContent-Typer   zmultipart/form-datatext)r  	log_debugr:  r>   rx  rT  r  r  r  r6  r  r  raise_for_status
exceptionsr]  r  r  	log_errorr)   r   r   r  r   r   r  )r(  r  ry  r   r  r  r  r  r  r  
json_errorr  r  r  err__r  s   ``              @r&   r  zOntapRestAPI._send_request  sb   	
?((*G	K	+ 	y$t6s4;;_e48LLt?C?O?OGU_CGCUCUi[e(g #h 	i	%'' tDKKPV044QX`etirtH"..KNN;(8(89%%'$,X$6!Iz" !NN;(@KQ[C\(\]&MY 	"%-%5%5%9%9'%B	'"##NB7BBCXY$,MM	&!I}447 "",, 	)"!)(!3J"J/ "!
"!{,<s,BC #C ""22 	%NN;(>(DEHM 	%NN;(9C(?@HM	%sO   A5F   I%F*)G(*F>;G(=F>>%G(( I% H..I%: I  I%c                     d\  }}|r|j                  dd      nd}|dk(  r|}d}d}n+|dvr|}d}n"|r | j                  dd	       d	}||d
|z  z  }d}|||fS )z return (done, message, error)
            done is True to indicate that the job is complete, or failed, or timed out
            done is False when the job is still running
        FNr   r   NfailureT)queuedrunningNr   z$Timeout error: Process still runningr  )r   r  )r(  job_json	job_state	job_error	timed_outdoner   r   s           r&   _is_job_donezOntapRestAPI._is_job_done,  s    ( "e19(,,y"-t	!EGD99EDNN1DE:E$9,,DWe##r%   c                 @   	 |d   d   d   j                  d      d   }d }g }d }d}	d}
d	}d
}|s| j                  |d       \  }}|r|j                  dd       nd }|rL|J|j	                  t        |             |
dz  }
|
|kD  rCdj                  |      }| j                  dd       d}nd}
| j                  ||||	|k\        \  }}}|st        j                  |       |	|z  }	|s||fS # t        $ r,}| j                  dd|d|       d d|d|fcY d }~S d }~ww xY w)N_linksr(  hrefzapi/r   r   zURL Incorrect format: z - Job:    Fstatez - zJob error: Reached max retries.T)
splitr   r  r   r  r)   r   r  timesleep)r(  jobrT  	incrementry  r  r   r}  r   runtimeretriesmax_retriesr  r  r  r  s                   r&   wait_on_jobzOntapRestAPI.wait_on_jobS  sR   	Kh-'/55f=a@C "&((3"5Hi7?Wd3TIY.c)n-1[(!JJv.ENN1&GHD'+'8'89iY`dkYk'l$gu

9%9$# $ ~K  	KNN1c3OPcJJJ	Ks   C( (	D1!DDDc                 B    d}| j                  |||d |      \  }}}||fS )Nr  r  r  r  r(  r  r   r  r  dummyr   r   s           r&   r   zOntapRestAPI.get}  s4     $ 1 1&#vDZa 1 bw~r%   c                     d}d}|dkD  ra| j                  ||||||      \  }}	}
|
r?t        |
t              r/d|
j                  dd      v rt	        j
                  d       |d	z
  }a	 |	|
fS 	
fS )
NPOSTr  r   r  r  r  temporarily lockedr   r      r   r  r^   r>   r   r  r  r(  r  bodyr   r  r  r  retryr  r   r   s              r&   postzOntapRestAPI.post  s    ai$($5$5fc6PT^emr$5$s!E7EE405IUYYW`bdMe5e

2	~w~r%   c                     d}d}|dkD  ra| j                  ||||||      \  }}	}
|
r?t        |
t              r/d|
j                  dd      v rt	        j
                  d       |d	z
  }a	 |	|
fS 	
fS )
NPATCHr  r   r  r  r   r   r  r   r  r  s              r&   patchzOntapRestAPI.patch  s    ai$($5$5fc6PT^emr$5$s!E7EE405IUYYW`bdMe5e

2	~w~r%   c                 B    d}| j                  |||||      \  }}}||fS )NDELETEr  r  )	r(  r  r  r   r  r  r  r   r   s	            r&   deletezOntapRestAPI.delete  s4     $ 1 1&#vDZa 1 bw~r%   c                 B    d}| j                  |||d |      \  }}}||fS )Nr  r  r  r  s           r&   r  zOntapRestAPI.options  s4     $ 1 1&#vDZa 1 bw~r%   c                 z    	 |j                  dd      } j                  D ]"  }	 |j                  |d       j                  |<   $ t         fd j                  D               j                  d<   y # t        $ r! d j                  d<   d j                  d<   Y y w xY w# t        $ r d j                  |<   Y w xY w)	Nr   z	not foundFrv  zunreadable messagert  rs  c              3   N   K   | ]  }|d k7  s	j                   |   dk7    yw)rv  rs  Nr|  )r   r   r(  s     r&   r   z+OntapRestAPI.set_version.<locals>.<genexpr>  s-      *
.13RY>Ds#r)*
s   
%%)r   r  r|  all)r(  r   r   r   s   `   r&   set_versionzOntapRestAPI.set_version  s    	kk)[9G
 %% 	-C-*1++c2*>""3'	-
 '* *
595G5G*
 '
7#  	*/Dw')=Dv&	 " -*,""3'-s"   A2 B2'BBB:9B:c                 z    | j                   d   r,| j                   d   | j                   d   | j                   d   fS y)Nrv  ru  r   r   r  r  r  s    r&   r  zOntapRestAPI.get_ontap_version  sC    g&%%l3T5G5G5PRVRdRdelRmmmr%   c                     d}d}ddgi}| j                  |||      \  }}}|rd|v rt        |d         dkD  r|d   d   }|||fS )Nr  zcluster/nodesr  r   r   r  r   )r  r   )r(  r  r  r   r  r   r   s          r&   get_node_version_using_restz(OntapRestAPI.get_node_version_using_rest  so     YK(&*&7&7F&7&S#WeyG+GI4F0G!0Ki(+GGU**r%   c                 &   	 | j                   j                  d      D cg c]  }t        |       }}t        |      dk(  r|j	                  d       |\  }}}d}| j                         }|d	k(  rd
}n|fk7  rd| j                  d   z  }|r6d| j                   |}| j                  dd| j                   z  di       |S c c}w # t
        t        f$ r6}| j                  j                  d| j                   d|       Y d}~d}~ww xY w)a   Provide a way to override the current version
            This is required when running a custom vsadmin role as ONTAP does not currently allow access to /api/cluster.
            This may also be interesting for testing :)
            Report a warning if API call failed to report version.
            Report a warning if current version could be fetched and is different.
        r     r   z\Error: unexpected format in force_ontap_version, expecting G.M.m or G.M, as in 9.10.1, got: z	, error: r[   Nr   r  z!, unable to read current version:z but current version is %srt  zForcing ONTAP version to r   zset by user to %s)ru  r   r   rt  )rO   r  r<   r   r  	TypeErrorr  r`   r_   r  r|  r  )	r(  r   r   genr   r   r   warningread_versions	            r&   get_ontap_version_from_paramsz*OntapRestAPI.get_ontap_version_from_params  s.   	7'+'?'?'E'Ec'JK!s1vKGK7|q q! 'C --/<'9Gc5%002T5G5G5OOG9=9Q9QSZ[Gi!+d.F.FF	*   / L :& 	7KK!!//6 " 7 7	7s'   C C'C C D,DDc                    d}d}ddgi}| j                  |||      \  }}}	 |r(d|j                  dd      v r| j                         \  }}}|r/d	|j                  dd      v r| j                  j	                  d	       | j                  |       |r| j                  |t        |             | j                  rt| j                         }|r|d
|d|z  }|rQ| j                  j                  |       d| j                  z  }|r| j                  d|       n| j                  d|       d }d}|rt        |      | _        |S d | _        |S # t
        $ r Y w xY w)Nr  clusterr  r   r  zare available in precluster.r   r   zUser is not authorized.z error: z, status_code: zForcing ONTAP version to %sINFOr  )r  r   r  r`   r_   r  r  r  r)   rO   r
  r   r  rz  )	r(  r  r  r   r  r   r   r  r\   s	            r&   r  z)OntapRestAPI.get_ontap_version_using_rest  sf    YK(&*&7&7F&7&S#We	7599YPR;SS.2.N.N.P+We2eii	26NN%%&?@ 	!NN;E
3##88:GE;OO  )3d6N6NNNN63/NN63/EK+0SZ 7;'  		s   AE	 		EEc                     t        |t              rdi }|D ]L  }t        ||   t              s||vri ||<   ||   D ]%  }t        |t              s|D ]  }d||dz   |z   <    ' N |j                  |       |S )zs Get all variable set in a list and add them to a dict so that partially_supported_rest_properties works correctly r   r  )r^   r>   r  r  )r(  
parameterstemp	parameteradictr   s         r&   &convert_parameter_keys_to_dot_notationz3OntapRestAPI.convert_parameter_keys_to_dot_notation  s    j$'D' @	j3T: ,*,Y!+I!6 @%eT2', @>?Y_s%: ;@@	@ d#r%   c                      j                   dvrd j                   z  }d|fS  j                   dk(  r|rddj                  |      z  }d|fS  j                   dk(  ry	 j                  d
   rd}n j                         } j                   dk(  r\|rZ|j	                          j                        dj                   fd|D              }|dk7  rdd|d j                         dfS  j                   dk(  ry|rI j                         d d dkD  r2d|z   _         j                  j                  d j                  z         y	|r|j	                          j                        |D ]i  } j                         d d |d   k  s|d   v s%d|d   dt        |d          _         j                  j                  d j                  z          y	  j                         d d dv ry	|dk(  rdS d	S )N)rR   rN   r=   z7use_rest must be one of: never, always, auto. Got: '%s'FrR   z(REST API currently does not support '%s'r   Tr=   r  rv  r  
c              3      K   | ]<  }j                         d d |d   k  r!|d   v rd|d   dt        |d         d > y w)Nr  r   r   zMinimum version of ONTAP for z is r  )r  r)   )r   propertyr(  temp_parameterss     r&   r   z(OntapRestAPI._is_rest.<locals>.<genexpr>)  sU      ))+BQ/(1+=(1+Q`B` =EQKXVW[IYZs   AAr   r  z  Current version: r  )TNr  	   rr   z?because of unsupported option(s) or option value(s) in REST: %szFalling back to ZAPI %sr  r   r   z5because of unsupported option(s) or option value(s) "z" in REST require ))r     r  )rG   r   r|  r  copyr  r  r{  r`   r   r)   )r(   used_unsupported_rest_properties#partially_supported_rest_propertiesr  r   r  r  r  s   `      @r&   _is_restzOntapRestAPI._is_rest  s+   == ;;MPTP]P]]E%<==H$)I>KkAllE;==G#g&K;;=K==H$)L(oo/O"II/ZOII  C E
 {%I_I_Iabbb==H$+%%'+f4UXxx ,  !:T=Y=Y!YZ. )oo/O"II/ZO? '))+BQ/(1+=(1+Q`B`iqrsitvy  {C  DE  {F  wG  H 0KK$$%>A]A]%]^&' !!#BQ'+;;*c1|D}Dr%   c                     d }|r|D cg c]	  }||v s| }}| j                  |||      \  }}|r||fS |r| j                  j                  |       |S c c}w )Nr[   )r  r`   r_   )	r(  r  unsupported_rest_propertiesr  report_errorr  r   rG   r   s	            r&   is_rest_supported_propertiesz)OntapRestAPI.is_rest_supported_propertiesK  sq    +/(&;V/jaZ[_iZi/j,/j,,'GIlnxy%U?"KK!!e!, 0ks
   	AAc                 B    | j                  |||      \  }}|||S ||fS )z+ only return error if there is a reason to )r  )r(  r  r  r  rG   r   s         r&   r  zOntapRestAPI.is_restV  s6    --(HJmoyz%+38[8cOr%   c                     t         j                  d||       | j                  j                  |       | j                  j                  ||f       y Nz%s: %s)rV  r   r}  r  r~  )r(  r  r   s      r&   r  zOntapRestAPI.log_error]  s;    		(K17#W56r%   c                 l    t         j                  d||       | j                  j                  ||f       y r&  )rV  rW  r~  r  )r(  r  r  s      r&   r  zOntapRestAPI.log_debugb  s)    		(K1W56r%   c                    |d}|rdnd}t        ||      5 }|*|j                  t        |      dt        |      d       n+|j                  t        |             |j                  d       ddd       y# 1 sw Y   yxY w)z
        This function is only for debug purposes, all calls to write_to_file should be removed
        before submitting.
        If data is None, tag is considered as data
        else tag is a label, and data is data.
        Nz/tmp/ontap_logawz: r  )r\  writer)   )r(  r  datafilepathr  modeafiles          r&   write_to_filezOntapRestAPI.write_to_filef  st     'Hs#(D! 	"U#c(CI>?CH%D!	" 	" 	"s   AA88Bc                 `    |d}| j                   D ]  }| j                  ||||       |rd} y )NErrorT)r}  r0  )r(  r  r-  r  r   s        r&   write_errors_to_filez!OntapRestAPI.write_errors_to_filew  s;    ;C[[ 	EsE8V<	r%   c                     |d}| j                   D ]1  \  }}| j                  ||||       |sd}| j                  ||||       3 y )NDebugT)r~  r0  )r(  r  r-  r  r  r   s         r&   write_debug_log_to_filez$OntapRestAPI.write_debug_log_to_file  sT    ;C$(OO 	? KsK6BsGXv>		?r%   )<   N)9.6)r8  N)r   )NNN)iX  r7  r   )NNF)NNT)#rh  ri  rj  rk  r"  r  r  r  r  r  r  r  r  r  r  r  r   r  r  r  r  r  r  r  r
  r  r  r  r#  r  r  r  r0  r3  r6  r$   r%   r&   rq  rq  r  s    7"DH8kjk+&H
5(B5H%$N(T





 
	+B D3Ej	7
7""?r%   rq  r$   r   )NFNrg  )NNNN)Brk  
__future__r   r   r   r2   __metaclass__r$  r   r   r   r  ansible.module_utils.basicr   ansible.module_utils._textr   $ansible.module_utils.ansible_releaser   ANSIBLE_VERSIONImportErrorCOLLECTION_VERSIONrM  r*   netapp_lib.api.zapir   r#   r   r  r  r-   r>   SF_BYTE_MAPPOW2_BYTE_MAP	ERROR_MSG	getLoggerrh  rV  r   r   solidfire.factoryr    r'   r+   r.   rL   rP   rS   rY   rc   r]   r   r   r   r   r   r   r   r   r  r  r  r  r   r   objectrq  r$   r%   r&   <module>rH     s  > C B   	 
  ; 0 S   $&89  (N
L 

  
  	
             !" #$ %& ', @	 g! s 
0J
h$&$ZW@D8036"0f	Y}2+&*
 D$dmm D$NT?6 T?E   O   N  Ll  JsM   D/ D= E E" /D:9D:=EEEEE"E,+E,