o x[h<@sRddlZddlZddlZddlZddlZddlZddlZddlZddlZddl Z ddl m Z m Z ddlm Z ddl mZddlmZmZmZddlmZeeZGdddeZGd d d ejd ZGd d d eZGdddeZGdddeZGdddeZeeeeeefZ eZ!e!"dee!"dee!"dee!"dedS)N)datetimetimezone)Event)Union) performance url_helperutil) DictRegistryc@s eZdZdS)ReportExceptionN)__name__ __module__ __qualname__rr>/usr/lib/python3/dist-packages/cloudinit/reporting/handlers.pyr sr c@s&eZdZdZejddZddZdS)ReportingHandlerzBase class for report handlers. Implement :meth:`~publish_event` for controlling what the handler does with an event. cCdS)zPublish an event.Nrselfeventrrr publish_event"zReportingHandler.publish_eventcCr)z0Ensure ReportingHandler has published all eventsNrrrrrflush&rzReportingHandler.flushN)r r r __doc__abcabstractmethodrrrrrrrs   r) metaclasscs*eZdZdZdfdd ZddZZS) LogHandlerzBPublishes events to the cloud-init log at the ``DEBUG`` log level.DEBUGcs`tt|t|tr n|}z tt|}Wnty*t d|tj }Ynw||_ dS)Nzinvalid level '%s', using WARN) superr__init__ isinstanceintgetattrloggingupper ExceptionLOGwarningWARNlevel)rr* input_level __class__rrr -s     zLogHandler.__init__cCs2tddd|j|jg}||j|dS)N. cloudinit reporting)r$ getLoggerjoin event_typenamelogr* as_string)rrloggerrrrr:szLogHandler.publish_event)r)r r r rr r __classcell__rrr,rr*s rc@seZdZdZddZdS) PrintHandlerzPrint the event as a string.cCst|dSN)printr6rrrrrDszPrintHandler.publish_eventN)r r r rrrrrrr9As r9csBeZdZ      d fdd ZddZddZdd ZZS) WebHookHandlerNc stt|t||||grtj||||d}|j|_ntj|_||_||_||_ t |_ t |_t|_tj|jd|_d|j_|jdS)N) consumer_key token_key token_secretconsumer_secrettargetT)rr<r anyrOauthUrlHelperreadurlendpointtimeoutretriesrfetch_ssl_details ssl_detailsrflush_requestedqueueQueue threadingThreadprocess_requestsevent_processordaemonstart) rrFr=r>r?r@rGrH oauth_helperr,rrr Is&    zWebHookHandler.__init__c Csd} |jr'|dkr'td|js%|j|j|jrd}|jjdd}z@z|j |d|d|d|d|dd d d}Wnt yg}ztd |d||d7}WYd}~nd}~wwW|jn|jwq) NrTzNMultiple consecutive failures in WebHookHandler. Cancelling all queued events.blockF)datarGrHrJ log_req_respz0Failed posting event: %s. This was caused by: %s) rKis_setr'r(rLempty get_nowait task_donegetrEr&)rconsecutive_failedargserrrrPjsD    zWebHookHandler.process_requestscCs@|}td|j||j|jt||j|j |j fdS)NzQueuing POST to %s, data: %s) as_dictr'debugrFrLputjsondumpsrGrHrJ)rr event_datarrrrszWebHookHandler.publish_eventcCs,|jtd|j|jdS)Nz(WebHookHandler flushing remaining events)rKsetr'rfrLr2clearrrrrrs   zWebHookHandler.flush)NNNNNN)r r r r rPrrr8rrr,rr<Hs!&r<cseZdZdZdZdZdZeeZdZdZ dZ dZ d Z d Z d Ze d ffd d ZeddZddZddZddZddZddZddZddZded ed!d fd"d#Zd$d%Zd&d'Zd(d)Zd*d+ZZS),HyperVKvpReportingHandlera, Reports events to a Hyper-V host using Key-Value-Pair exchange protocol and can be used to obtain high level diagnostic information from the host. To use this facility, the KVP user-space daemon (hv_kvp_daemon) has to be running. It reads the kvp_file when the host requests the guest to enumerate the KVP's. This reporter collates all events for a module (origin|name) in a single json string in the dictionary. For more information, see https://technet.microsoft.com/en-us/library/dn798287.aspx#Linux%20guests iii CLOUD_INITmsgresultmsg_i),:z/var/lib/hyperv/.kvp_pool_1FNcsrtt|||_t|j||_t|_| |_ d |j |j |_ tj|jd|_d|j_|jdS)Nz{0}|{1}rAT)rrmr _kvp_file_path_truncate_guest_pool_file _event_typesrLrMq_get_incarnation_noincarnation_noformat EVENT_PREFIXevent_key_prefixrNrO_publish_event_routinepublish_threadrRrS)r kvp_file_path event_typesr,rrr s   z"HyperVKvpReportingHandler.__init__c Cs|jrdSttt}zFztj||kr.t|dWdn1s)wYWnt t fyI}z t d|WYd}~n d}~wwWd|_dSWd|_dSd|_w)a Truncate the pool file if it has not been truncated since boot. This should be done exactly once for the file indicated by KVP_POOL_FILE_GUEST constant above. This method takes a filename so that we can use an arbitrary file during unit testing. Since KVP is a best-effort telemetry channel we only attempt to truncate the file once and only if the file has not been modified since boot. Additional truncation can lead to loss of existing KVPs. Nwz$failed to truncate kvp pool file, %sT) _already_truncated_pool_filetimefloatruptimeospathgetmtimeopenOSErrorIOErrorr'r()clskvp_file boot_timerdrrrrus"   z3HyperVKvpReportingHandler._truncate_guest_pool_filecCs@t}z ttt|WStytd|YdSw)z use the time passed as the incarnation number. the incarnation number is the number which are used to distinguish the old data stored in kvp and the new data. z"uptime '%s' not in correct format.r)rrr"rr ValueErrorr'r()r uptime_strrrrrxs  z-HyperVKvpReportingHandler._get_incarnation_noccst|jd>}t|tj||||j}t||jkr6| |}|V||j}t||jks!t|tj WddS1sHwYdS)z-iterate the kvp file from the current offset.rbN) rrtfcntlflockLOCK_EXseekreadHV_KVP_RECORD_SIZElen_decode_kvp_itemLOCK_UN)roffsetf record_datakvp_itemrrr _iterate_kvpss    "z'HyperVKvpReportingHandler._iterate_kvpscCsd|j|j|jtS)z the event key format is: CLOUD_INIT|||| [|subevent_index] z{0}|{1}|{2}|{3})rzr|r3r4uuiduuid4rrrr _event_key sz$HyperVKvpReportingHandler._event_keycCs*td|j|jf|d|d}|S)Nz%ds%dsutf-8)structpackHV_KVP_EXCHANGE_MAX_KEY_SIZEHV_KVP_EXCHANGE_MAX_VALUE_SIZEencoderkeyvaluer[rrr_encode_kvp_items z*HyperVKvpReportingHandler._encode_kvp_itemcCsdt|}||jkrtd||j|d|jdd}||j|jdd}||dS)Nz$record_data len not correct {0} {1}.rr)rr)rrr rzrdecodestrip)rrrecord_data_lenkvrrrr!s$    z*HyperVKvpReportingHandler._decode_kvp_itemc Cstd|jCt|jd$}t|tj|D]}||q|t|tj Wdn1s7wYWddSWddS1sOwYdS)Nz Appending ab) rTimedrtrrrrwriterr)rrrr[rrr_append_kvp_item8s Pz*HyperVKvpReportingHandler._append_kvp_itemc Cs||j=t|}|dt|d}d}g}d|jd} |||j<d||j<tj||jd}|jt|d} ||d j|j|d| d } d ||} | | | | |d7}|| d}|sh |Sq) NrXr"z":""T separatorsz"{key}":"{desc}")rdescz{}|{}) MSG_KEYrhrir DESC_IDX_KEYJSON_SEPARATORSHV_KVP_AZURE_MAX_VALUE_SIZEreplacerzappendr) rr meta_data description des_in_jsoni result_arraymessage_place_holderdata_without_desc room_for_descrsubkeyrrr _break_downBs8     z%HyperVKvpReportingHandler._break_downrrreturnc Csft||jkr|d|jd}|||g}z||WdSttfy2td||YdSw)zJWrite KVP key-value. Values will be truncated as needed. rrXzfailed posting kvp=%s value=%sN)rrrrrrr'r(rrrr write_key`sz#HyperVKvpReportingHandler.write_keycCs||}|j|jt|jtjd}t ||j r!|j ||j <|j ||j <tj||jd}t||jkr>||||j S|||}|gS)z encode the event into kvp data bytes. if the event content reaches the maximum length of kvp value. then it would be cut to multiple slices. )r4typetsr)rr4r3r fromtimestamp timestamprutc isoformathasattr RESULT_KEYrprrrhrirrrrr)rrrrrr[rrr _encode_eventos    z'HyperVKvpReportingHandler._encode_eventc Cs  d}zv|jjdd}|d7}g}|dur:|||7}z |jjdd}|d7}Wn tjy5d}Ynw|dusz0z||Wnttfy\}z t d|WYd}~nd}~wwWt |D]}|j qbn t |D]}|j qowWn t yYdSwq)NTrrVrXFz failed posting events to kvp, %s) rwrarrLEmptyrrrr'r(ranger`EOFError)ritems_from_queuer encoded_datard_rrrr}s>     z0HyperVKvpReportingHandler._publish_event_routinecCs&|jr |j|jvr|j|dSdSr:)rvr3rwrgrrrrrsz'HyperVKvpReportingHandler.publish_eventcCstd|jdS)Nz0HyperVReportingHandler flushing remaining events)r'rfrwr2rrrrrs zHyperVKvpReportingHandler.flush) r r r rrrrrr{rrrrKVP_POOL_FILE_GUESTrr classmethodrurxrrrrrrstrrrr}rrr8rrr,rrms:      rmr5r;webhookhyperv)#rrrhr$rrLrrNrrrrrtypingrr/rrrcloudinit.registryr r1r r'r&r ABCMetarrr9r<rm HandlerTypeavailable_handlers register_itemrrrrsJ    `