
    Vhq3                     &   d dl mZmZmZ eZd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mZ d dlmZ d d	lmZmZ d d
lmZmZ 	 d dlmZ d dlmZ dZdZdZ dZ!dZ"dZ#dZ$dZ%dZ&dZ'dZ(dZ)d Z*d Z+d Z,d dZ-d Z.e/dk(  r e.        yy# e$ r dZY =w xY w)!    )absolute_importdivisionprint_functiona  
---
module: redfish_firmware
short_description: To perform a component firmware update using the image file available on the local or remote system
version_added: "2.1.0"
description:
    - This module allows the firmware update of only one component at a time.
      If the module is run for more than one component, an error message is returned.
    - Depending on the component, the firmware update is applied after an automatic or manual reboot.
extends_documentation_fragment:
  - dellemc.openmanage.redfish_auth_options
options:
    image_uri:
        description:
            - Firmware Image location URI or local path.
            - For example- U(http://<web_address>/components.exe) or /home/firmware_repo/component.exe.
        type: str
        required: true
    transfer_protocol:
        description: Protocol used to transfer the firmware image file. Applicable for URI based update.
        type: str
        default: HTTP
        choices: ["CIFS", "FTP", "HTTP", "HTTPS", "NSF", "OEM", "SCP", "SFTP", "TFTP"]
    job_wait:
        description: Provides the option to wait for job completion.
        type: bool
        default: true
    job_wait_timeout:
        type: int
        description:
            - The maximum wait time of I(job_wait) in seconds. The job is tracked only for this duration.
            - This option is applicable when I(job_wait) is C(true).
            - "Note: If a firmware update needs a reboot, the job will get scheduled and waits for
              no of seconds specfied in I(job_wait_time). to reduce the wait time either give
              I(job_wait_time) minimum or make I(job_wait)as false and retrigger."
        default: 3600
requirements:
    - "python >= 3.9.6"
    - "urllib3"
author:
    - "Felix Stephen (@felixs88)"
    - "Husniya Hameed (@husniya_hameed)"
    - "Shivam Sharma (@Shivam-Sharma)"
    - "Kritika Bhateja (@Kritika_Bhateja)"
    - "Abhishek Sinha (@ABHISHEK-SINHA10)"
notes:
    - Run this module from a system that has direct access to Redfish APIs.
    - This module supports both IPv4 and IPv6 addresses.
    - This module supports only iDRAC9 and above.
    - This module does not support C(check_mode).
a  
---
- name: Update the firmware from a single executable file available in a HTTP protocol
  dellemc.openmanage.redfish_firmware:
    baseuri: "192.168.0.1"
    username: "user_name"
    password: "user_password"
    ca_path: "/path/to/ca_cert.pem"
    image_uri: "http://192.168.0.2/firmware_repo/component.exe"
    transfer_protocol: "HTTP"

- name: Update the firmware from a single executable file available in a HTTP protocol with job_Wait
  dellemc.openmanage.redfish_firmware:
    baseuri: "192.168.0.1"
    username: "user_name"
    password: "user_password"
    ca_path: "/path/to/ca_cert.pem"
    image_uri: "http://192.168.0.2/firmware_repo/component.exe"
    transfer_protocol: "HTTP"
    job_wait: true
    job_wait_timeout: 600

- name: Update the firmware from a single executable file available in a local path
  dellemc.openmanage.redfish_firmware:
    baseuri: "192.168.0.1"
    username: "user_name"
    password: "user_password"
    ca_path: "/path/to/ca_cert.pem"
    image_uri: "/home/firmware_repo/component.exe"
a(  
---
msg:
  description: Overall status of the firmware update task.
  returned: always
  type: str
  sample: "Successfully updated the firmware."
task:
  description: Returns ID and URI of the created task.
  returned: success
  type: dict
  sample: {
        "id": "JID_XXXXXXXXXXXX",
        "uri": "/redfish/v1/TaskService/Tasks/JID_XXXXXXXXXXXX"
    }
error_info:
  type: dict
  description: Details of http error.
  returned: on http error
  sample:  {
        "error": {
            "@Message.ExtendedInfo": [
                {
                    "Message": "Unable to complete the operation because the JSON data format entered is invalid.",
                    "Resolution": "Do the following and the retry the operation:
                        1) Enter the correct JSON data format and retry the operation.
                        2) Make sure that no syntax error is present in JSON data format.
                        3) Make sure that a duplicate key is not present in JSON data format.",
                    "Severity": "Critical"
                },
                {
                    "Message": "The request body submitted was malformed JSON and
                        could not be parsed by the receiving service.",
                    "Resolution": "Ensure that the request body is valid JSON and resubmit the request.",
                    "Severity": "Critical"
                }
            ],
            "code": "Base.1.2.GeneralError",
            "message": "A general error has occurred. See ExtendedInfo for more information."
        }
    }
N)SSLError)RedfishRedfishAnsibleModule)missing_required_lib)ConnectionErrorSSLValidationError)URLError	HTTPError)RequestField)encode_multipart_formdataTFUpdateServicezJobService/Jobs/{job_id}z%Job wait timed out after {0} seconds.zFirmware update failed.z"Successfully updated the firmware.z(Successfully scheduled the firmware job.successfailed	timed_out	schedulederroredc                     g }| j                  d      \  }}}|j                         }t        d||      }|j                  |       |j	                  |       t        |      \  }}||fS )z+Encode multipart/form-data for file upload.file)namedatafilename)content_type)getreadr   make_multipartappendr   )	payload_filefieldsf_namef_dataf_typef_binary	req_fieldr   r   s	            w/home/dcms/DCMS/lib/python3.12/site-packages/ansible_collections/dellemc/openmanage/plugins/modules/redfish_firmware.py_encode_form_datar(      sn    F)--f5FFF{{}H&x&II&1
MM)26:D,    c                 ~   | j                  ddj                  | j                  t                    }|j                  d   }|j
                  d   }d}|j                  j                  d      }|j                  j                  d      j                  d      }d	|v rm|j                  d	      }|j                  d
      }	t        |	t              r||	v rd|v r|j                  d      }n!|j                  dj                  |             ||||j                  d       t        |      t        |      t        |      fS )zFReturns all the URI which is required for firmware update dynamically.GET{0}{1}Actionstransfer_protocolNHttpPushUriFirmwareInventoryz	@odata.idz#UpdateService.SimpleUpdatez(TransferProtocol@Redfish.AllowableValuestargetz6Target firmware version does not support {0} protocol.msgzATarget firmware version does not support redfish firmware update.)invoke_requestformatroot_uriUPDATE_SERVICE	json_dataparamsr   
isinstancelist	fail_jsonstr)
objmoduleaction_respaction_attrprotocol
update_uripush_uriinventory_uriupdate_serviceprotos
             r'   _get_update_service_targetrH      s)   $$UHOOCLL.,YZK''	2K}}01HJ$$((7H))--.ABFF{SM$3$)FG""#MNeT"x5'8X=W'++H5J!Y!`!`ai!jkX-1F`a}s8}c*o==r)   c           	         |j                   j                  d      }|j                   d   }t        | |      \  }}}|j                  d      r||d}| j	                  d||      }|S | j	                  d|      }	t        t        j                  j                  |      d      5 }
d	|j                  t        j                        d
   |
dfi}t        |      \  }}ddd       d|	j                  j                  d      i}|j                  di       | j	                  d||d|j                   d         }|j                  dk(  r3d|j                  j                  d      i}| j	                  d||      }|S |}|S # 1 sw Y   xY w)zJFirmware update using single binary file from Local path or HTTP location.	image_urir.   http)ImageURITransferProtocolPOST)r   r+   rbr   zmultipart/form-dataNzIf-MatchetagzContent-TypeFtimeout)r   headersdumpapi_timeout   rL   location)r9   r   rH   
startswithr4   openospathjoinsplitsepr(   rS   updatestatus_code)r>   r?   
image_pathtrans_protorE   rD   rC   payloadupdate_statusresp_invimg_filebinary_payloadr   ctyperS   upload_statuss                   r'   firmware_updaterj      s   "";/J-- 34K*DS&*Q'M8ZV$){K**6:G*L  %%e];"'',,z*D1 	<X$z'7'7'?'CXOd&efN+N;KD%	< x//33F;<./**68$PW^cqwq~q~  @I  rJ*  K$$+!=#8#8#<#<Z#HIG..vz.PM  *M	< 	<s   "6E::Fc                    	 t        | j                  d      5 }d}d}d}||k  r	 |j                  ddj                  |j                  |            }|j
                  j                  d      dk(  rV|j
                  j                  d	      d
k(  r8|j
                  j                  d      dk(  rt        }t        }nt        }t        }n ||z  }t        j                  |       ||k  r|sdj
                  j                  d      dk(  r+|j
                  j                  d	      dk(  rt        }t         }nt"        j                  |      }t$        }d d d        fS # t        t        f$ r ||z  }t        j                  |       Y w xY w# 1 sw Y   <xY w# t&        $ r9}	t)        |	      }| j+                  t)        |             t,        }Y d }	~	||fS d }	~	ww xY w)NFreq_sessionr    r+   r,   PercentCompleted   JobState	Completed	JobStatusOKStartingr2   )r   r9   r4   r5   r6   r8   r   JOBSTATUS_SUCCESSSUCCESS_JOB_MSGJOBSTATUS_FAILEDFAIL_JOB_MSGtimesleepr   r   JOBSTATUS_SCHEDULEDSCHEDULE_JOB_MSGJOB_WAIT_MSGJOBSTATUS_TIMED_OUT	Exceptionr=   	exit_jsonJOBSTATUS_ERRORED)
r?   job_urijob_wait_timeoutintervalr>   track_counterfinal_jobstatusjob_msgresponseerror_messages
             r'   wait_for_job_completionr      s   ",V]]6 	:#M OG#33)"11%W^9_`H))--.?@CGHL^L^LbLbcmLnr}L}#--11+>$F.?O&5G.>O&2G!X-MJJx(  #33$ #%%))*;<AhFXFXF\F\]gFhlvFv&9O.G +112BCG&9O;	:D G### "8, )!X-MJJx()#	: 	:<  ,m$S\*+G##	,se   F FBEFE F&A&FF )FFFFFF 	G,GGc                     dddddg dddddd	dd
dd	d} t        | d      }t        s|j                  t        d             	 d}t	        |j
                  d      5 }t        ||      }|j                  r2d}|j                  j                  d      }|j                  d      d   }n&|j                  |t        j                  |             d d d        |j
                  d   }|j
                  d   }|r|dkD  rt        j                        }	t        ||	|j
                  d         \  }
}|
t         k(  r,|j#                  ||t        j                  |      dd       y |j#                  ||t        j                  |      dd       y |j#                  |t        j                  |      dd       y # 1 sw Y   xY w# t$        $ r:}|j#                  t'        |      t        j(                  |      d       Y d }~y d }~wt*        t,        t.        t0        t2        t4        t6        t8        t:        t<        t>        t@        f$ r%}|j                  t'        |             Y d }~y d }~ww xY w) NTr=   )requiredtypeHTTP)	CIFSFTPr   HTTPSNSFOEMSCPSFTPTFTP)r   defaultchoicesFbool)r   r   r   inti  )rJ   r.   job_waitr   )argument_specsupports_check_modeurllib3r2   z*Failed to submit the firmware update task.rl   z0Successfully submitted the firmware update task.Location/rP   )r3   
error_infor   r   r   )job_id)r   )iduri)r3   taskr   )r3   r   changed)r3   r   r   )!r   HAS_LIBr<   r	   r   r9   rj   r   rS   r   r]   jsonloadsJOB_URIr5   r   rx   r   r   r=   loadRuntimeErrorr   r   r
   KeyErrorImportError
ValueError	TypeErrorIOErrorAssertionErrorOSErrorr   )specsr?   messager>   statustask_urir   r   r   r   job_respr   erres                 r'   mainr     sB   "&6&+  LQ  R!&4H).$O	E "!#F 1)<=%>V]]5 	M$S&1F~~L!>>--j9!,R0  WF9K L	M ==,!==);<(1,nnFn3G 7Z`ZgZghzZ{ |Hg++  W&_eIf3gpt u  W&_eIf3gqu vfW^^[a^Eb/cmqr%	M 	M&  OSX$))C.NN($6YRZ\ %SV$$%sK   G !A1G BG (+G +G  G	G 	I30H

AI3I..I3__main__)i     )0
__future__r   r   r   r   __metaclass__DOCUMENTATIONEXAMPLESRETURNr   rZ   rz   sslr   Cansible_collections.dellemc.openmanage.plugins.module_utils.redfishr   r   ansible.module_utils.basicr	   ansible.module_utils.urlsr
   r   +ansible.module_utils.six.moves.urllib.errorr   r   urllib3.fieldsr   urllib3.filepostr   r   r   r7   r   r~   ry   rw   r}   rv   rx   r   r|   r   r(   rH   rj   r   r   __name__ r)   r'   <module>r      s    C B2h>)
X  	   m ; I K+:G !
$6(6=   ! !  	>(0$$N&%R zF q  Gs   B BB