HEX
Server: Apache
System: Linux a16-asgard6.hospedagemuolhost.com.br 5.14.0-570.52.1.el9_6.x86_64 #1 SMP PREEMPT_DYNAMIC Wed Oct 15 06:39:08 EDT 2025 x86_64
User: maoristu4c3dbd03 (1436)
PHP: 8.1.33
Disabled: NONE
Upload Files
File: //usr/lib64/python3.9/site-packages/rhsm/__pycache__/connection.cpython-39.opt-1.pyc
a

X�Zhl\�@sbddlZddlmZddlZddlZddlZddlZddlZddl	Z	ddl
Z
ddlZddlZddl
mZmZmZmZmZmZmZddlmZddlZddlZddlmZddlmZmZddlmZddl m!Z!m"Z"m#Z#m$Z$dd	l%m&Z&dd
lm'Z(ddlm)Z)zddl*Z+e+j,j-Z.Wne/�y,dZ.Yn0zdd
l0m1Z2Wn"e/�y`e3d�dd�Z2Yn0e&�Z4dZ5dZ6dPeeee7defd�dd�Z8e3e3d�dd�Z9e3ej:d�dd�Z;Gdd�dej<�Z=e=�Z>e�?d��@e>�e�?eA�ZBGdd �d eC�ZDGd!d"�d"eC�ZEGd#d$�d$eC�ZFGd%d&�d&eE�ZGGd'd(�d(eE�ZHGd)d*�d*eE�ZIGd+d,�d,ejJ�ZKGd-d.�d.�ZLGd/d0�d0eC�ZMGd1d2�d2eL�ZNGd3d4�d4eE�ZOGd5d6�d6eO�ZPGd7d8�d8eE�ZQGd9d:�d:eE�ZRGd;d<�d<eR�ZSGd=d>�d>eO�ZTGd?d@�d@eS�ZUGdAdB�dBeS�ZVGdCdD�dDeE�ZWdEdF�ZXGdGdH�dHeL�ZYede3fdI�dJdK�ZZGdLdM�dM�Z[GdNdO�dOeL�Z\dS)Q�N)�certificate)�Any�Dict�Iterable�List�Optional�Tuple�Union)�Path��format_datetime)�httplib�ssl)�proxy_bypass)�	urlencode�urlparse�quote�
quote_plus)�get_config_parser)�ourjson)�utils�unknown)�ugettext��messagecCs|S�N�rrr�5/usr/lib64/python3.9/site-packages/rhsm/connection.py�_7srZmulti_environmentT)�value�
safe_value�returncCs&z
t|�WSty |YS0dSr)�int�	Exception)rr rrr�safe_intAs
r$)�hostr!cCsd|vrd|S|SdS)a`
    When you want to use IPv6 address and port in e.g. HTTP header, then you cannot use following
    notation common for IPv4 (147.230.16.1:53). You have to use following notation for IPv6
    [2001:718:1c01:16::aa]:53.
    :param host: hostname or IPv4 or IPv6 address
    :return: When host is IPv6 address, then it encapsulated in [] brackets
    �:z[%s]Nr)r%rrr�normalized_hostHsr')�	timestampr!cCsftj�|�}|j�|�dkr.t�d|�d��|jtj	j
d�}tj�tj	j
�jdd�}t||�}|S)z�Get a difference between server and local clock.

    :param timestamp: A timezone-unaware timestamp in RFC 1123 format.
    :returns: Absolute difference between server and local time.
    ZUTCzExpected UTC timestamp, got 'z', drift check may be off.)�tzinfor)Zmicrosecond)
�dateutil�parser�parser)�tzname�log�warning�replace�datetime�timezoneZutc�now�abs)r(r3�driftrrr�get_time_driftVsr6c@seZdZedd�dd�ZdS)�NullHandlerN)�recordr!cCsdSrr)�selfr8rrr�emitiszNullHandler.emit)�__name__�
__module__�__qualname__rr:rrrrr7hsr7�rhsmc@seZdZdZdS)�NoValidEntitlementzFThrow when there is no valid entitlement certificate for accessing CDNN)r;r<r=�__doc__rrrrr?ssr?c@seZdZdS)�ConnectionExceptionN�r;r<r=rrrrrAysrAc@sZeZdZdZd
eeeed�dd�Ze	ed�dd��Z
e	ed�d	d
��Zed�dd�ZdS)�ProxyExceptionz?
    Thrown in case of errors related to the proxy server.
    N��hostname�port�exccCs||_||_||_dSr)�	_hostnamerFrG)r9rErFrGrrr�__init__�szProxyException.__init__�r!cCs
t|j�Sr)r'rH�r9rrrrE�szProxyException.hostnamecCs|j�d|j��S)Nr&�rErFrKrrr�address�szProxyException.addresscCs.|j}d|��}|jdur*|�d|j��}|S)NzProxy error at z: )rMrG)r9�addr�errrrr�__str__�s


zProxyException.__str__)NNN)
r;r<r=r@�strr"rr#rI�propertyrErMrPrrrrrC}srCc@seZdZdS)�ConnectionSetupExceptionNrBrrrrrS�srSc@s2eZdZdZeejdd�dd�Zed�dd�ZdS)	�BadCertificateExceptionz:Thrown when an error parsing a certificate is encountered.N)�	cert_path�ssl_excr!cCs||_||_dS)z*Pass the full path to the bad certificate.N)rUrV)r9rUrVrrrrI�sz BadCertificateException.__init__rJcCs
d|jS)NzBad certificate at %s)rUrKrrrrP�szBadCertificateException.__str__)	r;r<r=r@rQr�SSLErrorrIrPrrrrrT�srTc@s6eZdZdZeeeed�dd�Zeed�dd��Z	dS)	�ConnectionOSErrorExceptionz�
    Thrown in case of OSError during the connect() of HTTPSConnection,
    in case the OSError does not come from a syscall failure (and thus
    its 'errno' attribute is None.
    )r%rF�handlerrGcCs||_||_||_||_dSr)�_hostrFrYrG)r9r%rFrYrGrrrrI�sz#ConnectionOSErrorException.__init__rJcCs
t|j�Sr)r'rZrKrrrr%�szConnectionOSErrorException.hostN)
r;r<r=r@rQr"�OSErrorrIrRr%rrrrrX�srXc@s0eZdZdZe��Ze��Ze��Ze��Z	dS)�ConnectionTypez/
    Enumerate of allowed connection types
    N)
r;r<r=r@�enum�auto�NO_AUTH�
BASIC_AUTH�CONSUMER_CERT_AUTH�
KEYCLOAK_AUTHrrrrr\�s
r\c@s�eZdZdeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeedd�dd�ZdS)�BaseConnectionN)r%�ssl_portrY�ca_dir�insecure�proxy_hostname�
proxy_port�
proxy_user�proxy_password�no_proxy�username�password�	cert_file�key_file�cert_dir�token�
user_agent�correlation_id�timeout�	auth_typer!c Ks>|pt�dd�|_|p t�dd�|_|p6tt�dd��|_|pLtt�dd��|_|
p^t�dd�}|rn|tjd<t	�
�t�d|�t
|j�r�d|_d|_d|_d|_n�t	��}|dur�||_nt�dd�p�|d|_|dur�||_nt�dd	�p�|d	|_|du�r||_nt�dd
��p"|d|_|	du�r8|	|_nt�dd��pL|d|_|
|_||_||_||_||_||_|�p�t�d
d�|_||_|du�r�d|_tt�dd��}|�r�d|_d}d}d}d}|�r�|�r�d}n(|
�r�|�r�d}n|�r�d}n
|�rd}tdd�||||fD��dk�r,td��d}|j�rX|j�rXdt|j�t|j�f}t|j|j|j|j|j|j|j|j|j|j|j|j|j|j||j|||d�|_|�r�d|}n8|�r�d|}n(|�r�d|j|jf}n|�r�d}nd}d|_ d|_!d}|�r||7}|dt|j�t|j�|j|f7}t�d|�dS) NZserverrE�prefixrFZserver_timeoutrkz-Environment variable NO_PROXY=%s will be usedrgrhriZproxy_usernamerjr>Zca_cert_dirFrfTcSsg|]}|r|�qSrr)�.0rrrr�
<listcomp>+s�z+BaseConnection.__init__.<locals>.<listcomp>�z"Cannot specify multiple auth typeszhttp_proxy=%s:%s )rlrmrqrnrorgrhrirjrerfrprtrsrrruzauth=bearer %szauth=basic username=%sz(auth=identity_cert ca_dir=%s insecure=%szauth=entitlement_certsz	auth=none�zhost=%s port=%s handler=%s %szConnection built: %s)"�config�getr%rYr$rdrt�os�environrZfix_no_proxyr.�debugrrgrhrirjZget_env_proxy_infornrorlrmrqrurerf�lenr#r'�BaseRestLib�conn�	resources�capabilities) r9r%rdrYrerfrgrhrirjrkrlrmrnrorprqrrrsrtru�kwargsZno_proxy_override�infoZconfig_insecureZusing_basic_authZusing_id_cert_authZusing_ent_cert_authZusing_keycloak_authZproxy_descriptionZauth_descriptionZconnection_descriptionrrrrI�s�




�������

�zBaseConnection.__init__)NNNNNNNNNNNNNNNNNNNN)	r;r<r=rrQr"�boolr\rIrrrrrc�sV��rcc@seZdZdS)�TokenAuthExceptionNrBrrrrr�psr�cs@eZdZdZeeedd��fdd�Zeeed�dd�Z�Z	S)	�KeycloakConnectionz'
    Keycloak Based Authentication
    N)�realm�auth_url�resourcer!csTt|�jpd}t|�j}t|�jp$d}tt|�jf|||d�|��||_||_dS)Nrzi�)r%rdrY)	rrE�pathrF�superr�rIr�r�)r9r�r�r�r�r%rYrd��	__class__rrrIys
zKeycloakConnection.__init__)�refreshtokenr!c
Cs~d|jd}|jd|d�}ddi}z|j�|||�}|dWStyx}z"|jdkrbt|j���WYd}~n
d}~00dS)	Nz/realms/z/protocol/openid-connect/token�
refresh_token)Z	client_idZ
grant_typer��Content-type�!application/x-www-form-urlencodedZaccess_tokeni�)r�r�r��request_post�RestlibException�coder��msg)r9r��method�params�headers�data�errr� get_access_token_through_refresh�s


z3KeycloakConnection.get_access_token_through_refresh)
r;r<r=r@rrQrIrr��
__classcell__rrr�rr�tsr�c@sFeZdZdZdeeedd�dd�Zeed�dd��Z	ed�d	d
�Z
dS)r�z�
    Raised when a response with a valid json body is received along with a status code
    that is not in [200, 202, 204, 410, 429]
    See BaseRestLib.validateResult to see when this and other exceptions are raised.
    N�r�r�r�r!cCs||_|pd|_|pi|_dS)Nrz)r�r�r�)r9r�r�r�rrrrI�s
zRestlibException.__init__rJcCstj�|jd�S�NZUnknown�r
Z	responsesr|r�rKrrr�title�szRestlibException.titlecCsd|j�d|j�d|j��S)NzHTTP error (� - z): )r�r�r�rKrrrrP�szRestlibException.__str__)NN)r;r<r=r@r"rQ�dictrIrRr�rPrrrrr��s
r�c@s"eZdZdZeeed�dd�ZdS)�
GoneExceptiona�
    GoneException is used to detect when a consumer has been deleted on the candlepin side.

    A client handling a GoneException should verify that GoneException.deleted_id
    matches the consumer uuid before taking any action (like deleting the consumer
    cert from disk).

    This is to prevent an errant 410 response from candlepin (or a reverse_proxy in
    front of it, or it's app server, or an injected response) from causing
    accidental consumer cert deletion.
    )r�r��
deleted_idcCst�|||�||_dSr)r�rIr�)r9r�r�r�rrrrI�szGoneException.__init__N)r;r<r=r@r"rQrrIrrrrr��sr�c@sNeZdZdZdeeeeedd�dd�Zeed�dd��Z	ed�d	d
�Z
dS)�UnknownContentExceptionz�
    Thrown when the response of a request has no valid json content
    and the http status code is anything other than the following:
    [200, 202, 204, 401, 403, 410, 429, 500, 502, 503, 504]
    N)r��content_type�contentr!cCs||_||_||_dSr)r�r�r�)r9r�r�r�rrrrI�sz UnknownContentException.__init__rJcCstj�|jd�Sr�r�rKrrrr��szUnknownContentException.titlecCsXd|j�d|j��}|jdur.|d|j��7}|jdurL|dt|j���7}|d7}|S)NzUnknown content error (HTTP r�z, type z, len �))r�r�r�r�r�)r9�srrrrP�s

zUnknownContentException.__str__)NN)r;r<r=r@r"rrQrIrRr�rPrrrrr��s
r�c@s4eZdZdZd	eeedd�dd�Zed�dd�ZdS)
�RemoteServerExceptionz�
    Thrown when the response to a request has no valid json content and
    one of these http status codes: [404, 410, 500, 502, 503, 504]
    N)r��request_typerYr!cCs||_||_||_dSr)r�r�rY)r9r�r�rYrrrrI�szRemoteServerException.__init__rJcCs*|jr |jr d|j|j|jfSd|jS)Nz5Server error attempting a %s to %s returned status %szServer returned %s)r�rYr�rKrrrrP�s�zRemoteServerException.__str__)NN)r;r<r=r@r"rQrIrPrrrrr��sr�cs&eZdZdZed��fdd�Z�ZS)�AuthenticationExceptionzAuthentication errorrJcs(tt|���}|d7}|d|j7}|S)N�
z$%s: Invalid credentials for request.)r�r�rPrv)r9�bufr�rrrP�szAuthenticationException.__str__)r;r<r=rvrQrPr�rrr�rr��sr�cs.eZdZdZdeeedd��fdd�
Z�ZS)�RateLimitExceededExceptiona
    Thrown in response to a http code 429.
    This means that too many requests have been made in a given time period.
    The retry_after attribute is an int of seconds to retry the request after.
    The retry_after attribute may not be included in the response.
    Nr�cs|tt|��||�|pi|_d|_|j��D]"\}}|��dkr,t|�|_qPq,|pVd|_|jdurx|jd|j7_dS)Nzretry-afterzAccess rate limit exceededz!, retry access after: %s seconds.)	r�r�rIr�Zretry_after�items�lowerr$r�)r9r�r�r��headerrr�rrrI�s



z#RateLimitExceededException.__init__)NN)	r;r<r=r@r"rQr�rIr�rrr�rr��sr�c@seZdZdZdZdS)�UnauthorizedExceptionzO
    Thrown in response to http status code 401 with no valid json content
    ZUnauthorizedN�r;r<r=r@rvrrrrr�sr�c@seZdZdZdZdS)�ForbiddenExceptionzO
    Thrown in response to http status code 403 with no valid json content
    Z	ForbiddenNr�rrrrr�sr�c@seZdZdS)�ExpiredIdentityCertExceptionNrBrrrrr�sr�cCs(t�d�||f��d���d�}d|S)Nr&�utf-8zBasic %s)�base64Z	b64encode�join�encode�decode)rlrmZencodedrrr�_encode_auths r�cs\eZdZdedd��fdd�
Zdeeeeefeedfd�dd�Z	dd�d	d
�Z
�ZS)
�ContentConnectionN)rpr!csXt�d�dt�tj�}d|vr.||d7}|p4d}tt|�jfd||d�|��dS)Nr�zRHSM-content/1.0 (cmd=%s)�client_versionz/etc/pki/entitlement�/)rYrprr)	r.rr�cmd_name�sys�argvr�r�rI)r9rpr�rrr�rrrI s
��zContentConnection.__init__)r��cert_key_pairsr!cCs"d|j|f}|jj||d�}|S)aI
        Get list of available release versions from the given path
        :param path: path, where is simple text file containing supported release versions
        :param cert_key_pairs: optional argument including list of supported cert and keys
            to reduce number of failed http requests.
        :return:
        z%s/%s)r�)rYr��request_get)r9r�r�rY�resultrrr�get_versions*szContentConnection.get_versionsrJcCsdSrr)r9Z
product_idrrr�_get_versions_for_product7sz+ContentConnection._get_versions_for_product)N)N)r;r<r=rQrIrrr	r�r�r�r�rrr�rr�s
(
r�rJcCstd}zt��}WnJtjtfyZzt��}Wn$tjyDYntyTYn0Yn0|rp|dkrp|dSdS)N)NNr)�locale�	getlocale�Error�
ValueError�getdefaultlocale)Z
new_localerrr�_get_locale;sr�c@s�eZdZUdZdZdZeed<dZe	ed<dCe
e	e
ee
ee
ee
ee	ee
ee
ee
ee
ee
ee
eeee	ee
ee
ee
ee
dd�d	d
�Zdd�dd
�Zeee
e
fd�dd�Zejdd�dd�ZdDe
e
ejd�dd�Ze
e
eeeefdd�dd�Zeedd�dd��Zdd�dd�Zee
eede	fede	ffd�dd ��Z dEe
e
ee
eee
e
fee
eee!e
efdfeej"dffd!�d"d#�Z#dFe
e
eeeeee
e
fee
e!e
efd$�d%d&�Z$ed'�d(d)�Z%dGee
e
dd*�d+d,�Z&eee
d-�d.d/��Z'ee!e
efed0�d1d2��Z(dHe
eeee
e
fee
ed3�d4d5�Z)dIe
eeee
ed6�d7d8�Z*dJe
eee
ed9�d:d;�Z+dKe
eeee
ed6�d<d=�Z,dLe
eeee
ed6�d>d?�Z-ee.j.e
d@�dAdB��Z/dS)Mr�zp
    A low-level wrapper around httplib
    to make rest calls easy and expose the details of
    responses
    Ng�������?�ALPHA�2�KEEP_ALIVE_TIMEOUTF)r%rd�
apihandlerrlrmrgrhrirjrnrorprerfrtrsrqrrrur!cCs�t�d�||_||_||_|p"d|_ddtd�|_|rB||jd<|
|_||_	||_
|
|_||_||_
||_||_||_||_||_|	|_d|_||_||_d|_|r�|r�t||�|jd<n|r�d||jd<dS)Nz!Creating new BaseRestLib instancezpython-rhsm-user-agent�application/json)r�ZAcceptzx-subscription-manager-versionzX-Correlation-ID�
Authorization�Bearer )r.rr%rdr�rr�subman_versionr�rnrorprerfrlrmrtrgrhrirj�smoothed_rtrqru�is_consumer_cert_key_validr�)r9r%rdr�rlrmrgrhrirjrnrorprerfrtrsrqrrrurrrrI]s>

�
zBaseRestLib.__init__rJc
Cs�|jdur�|jjdurzt�d|jj���z|jj��Wn4tyn}zt�d|���WYd}~nd}~00t�d�z|j��Wn4ty�}zt�d|���WYd}~n
d}~00d|_dS)zI
        Try to close connection to server
        :return: None
        NzClosing HTTPS connection z Unable to close TLS connection: zTLS connection closedz Unable to close TCP connection: )�_BaseRestLib__conn�sockr.r�unwrapr#�closer�)r9rOrrr�close_connection�s
&
&zBaseRestLib.close_connectionc	Cs�g}|jdur|j|jfgSt�|j�D]V}|�d�r(|�d�s(tj�|j|�}tj�|jd|�dd�d�}|�	||f�q(|S)zN
        Create list of cert-key pairs to be used with the connection
        N�.pemz-key.pemz
%s-key.pem�.ryr)
rprnror}�listdir�endswithr�r��split�append)r9r�rnrUZkey_pathrrr�_get_cert_key_list�s
 zBaseRestLib._get_cert_key_list)�contextr!c
Cstj�|j�s"t�d|j�dSg}d}zDt�|j�D]2}|�d�r8tj�|j|�}|�	|�|�
|�q8Wn\tjy�}zt
||��WYd}~n6d}~0ty�}zt|j��WYd}~n
d}~00|r�t�d|jd�|�f�nt�d|j�dS)zx
        Tries to load CA certificates to SSL context
        :param context: SSL context
        :return: None
        z.Directory "%s" with CA certificates is missingNrzr�z"Loaded CA certificates from %s: %sz, z*Unable to load any CA certificate from: %s)r}r��isdirrer.r/r�r�r�Zload_verify_locationsr�rrWrTr[rS�strerrorr)r9r�Zloaded_ca_certsrUrnrGr�rrr�_load_ca_certificates�s$

 z!BaseRestLib._load_ca_certificates)rnror!c
Csd|jdur�t��}||jj|jjkrFt�d|jj�d��|��nR|jjdur�|jj|jjkr�t�d|jj�d��|��nt�d|jj	�|jSt�d�t
�t
j�}|j
r�d|_t
j|_nt
j|_|jdur�|�|�|r�tj�|�r�|j||d	�|j�r�|j�r�t�d
t|j�t|j�f�|jdt|j�t|j�fd�}|j�rn|j �rnt!|j|j �|d
<t"j#|j|j||j$d�}|�%|jt|j�|�dt|j�t|j�f|j&d<nt"j#|j|j||j$d�}|j'|_d|_d|_z|�(�WnHt)�y<}z.|j*du�r&t+|j|j|j,|���WYd}~n
d}~00t�d|j	���t-du�r`||_|S)a	
        This method tries to return existing connection, when connection exists and limit of connection
        has not been reached (timeout, max number of requests). When no connection exists, then this
        method creates new TCP and TLS connection.
        NzConnection timeout z. Closing connection...zMaximal number of requests (z ) reached. Closing connection...zReusing connection: %szCreating new connectionF)ZkeyfilezUsing proxy: %s:%sz%s:%s)�
User-Agent�HostzProxy-Authorization)r�rtr�rzCreated connection: T).r��time�last_request_time�keep_alive_timeoutr.rr��max_requests_numZrequests_numr�r�
SSLContextZPROTOCOL_TLS_CLIENTrfZcheck_hostnameZ	CERT_NONEZverify_modeZ
CERT_REQUIREDrer�r}r��existsZload_cert_chainrgrhr'r$rrr%rdrirjr�r
�HTTPSConnectionrtZ
set_tunnelr�r�Zconnectr[�errnorXr��REUSE_CONNECTION)r9rnror3r�Z
proxy_headersr�r�rrr�_create_connection�sj


���




��� 
zBaseRestLib._create_connection)r�rY�
final_headers�bodyr!cCs�tj�dd�dkrdSt�tj�dd�rn|jdurn|jjdurntt�dtjj	��tt�|jj�tjj
��|j�rh|j�rhtt�dtjj	��d}|j
r�|j
r�|jr�||j
�d|j�d	�7}n|j
r�|js�||j
�d	�7}|t|j��dt|j���7}tt�|tjj��d}d}|jdu�r>t|jd
��r>t|jd
�}|du�rN|�}|�rhtt�|tjj
��d}|j�rxd}|jtjk�r�|d7}nP|jtjk�r�|d
7}n8|jtjk�r�|d7}n |jtjk�r�|d7}n|d7}tt�dtjj	��tt�|�d�dt|j��dt|j��|��tjj�dt�|�tjj
��tj�dd��r�tt�dtjj	��tt�|�tjj
��tj�dd��r�|du�r�tt�dtjj	��tt�|�tjj��tj�dd��r�tt�dtjj	��tj t!j"d�tj�dd��r�t#d�}	|	j$dd�t%j%�&��'d�}
d }t#|
�d!|�d"��}|	|}
|
�(��sX�qd|d#7}�q.|
j)d$d%d&��}tj |d�Wd�n1�s�0Ytt�d'tjj	��tt*|
���t�dS)(a
        This method can print debug information about sent http request. We do not use
        httplib.HTTPConnection.debuglevel = 1, because it doesn't provide control about displayed information.
        The debug print is printed to stdout, when environment variable SUBMAN_DEBUG_PRINT_REQUEST is set.
        Output can be modified with following environment variables:
         * SUBMAN_DEBUG_PRINT_REQUEST_HEADER
         * SUBMAN_DEBUG_PRINT_REQUEST_BODY
        :param request_type: (GET, POST, PUT, ...)
        :param handler: e.g. /candlepin/status
        :param final_headers: HTTP headers used by request
        :param body: request can contain body. It is usually dictionary, but it can be anything that
            can be serialized by json.dumps()
        :return: None
        ZSUBMAN_DEBUG_PRINT_REQUESTrzNZSUBMAN_DEBUG_TCP_IPzTCP socket:zProxy:zhttps://r&�@Z_tunnel_headersz	insecure z
keycloak authz
basic authz
consumer authzno authzundefined authzRequest:� z using Z!SUBMAN_DEBUG_PRINT_REQUEST_HEADERzRequest headers:ZSUBMAN_DEBUG_PRINT_REQUEST_BODYz
Request body:ZSUBMAN_DEBUG_PRINT_TRACEBACKSzCurrent call stack:)�fileZSUBMAN_DEBUG_SAVE_TRACEBACKSz
/tmp/rhsm/T)�exist_okz%Y-%m-%d_%H-%M-%Srrz.logry�wr�)�encodingzCall stack file:)+r}r~r|�printr�r�r�colorize�COLOR�GREEN�BLUErgrhrirjr'r$ZMAGENTA�hasattr�getattrrfrur\rbr`rar_r%rd�RED�YELLOW�	traceback�print_stackr��stdoutr
�mkdirr1r3�strftimer��openrQ)r9r�rYr�r�Z	proxy_msgZ
tunnel_msgZtunnel_headersZauthZ	debug_dirr(�i�filenameZ	debug_logZhandlerrr�_print_debug_info_about_request<s���
�




������
,z+BaseRestLib._print_debug_info_about_request)r�r!cCs�tj�dd�r�tt�dtjj��tt�|d�tjj��tt�dtjj��tt�|d�tjj	��|dr�tt�dtjj��tt�|d�tjj
��t�d	S)
z�
        This method can print result of HTTP request to stdout, when
        environment variable SUBMAN_DEBUG_PRINT_RESPONSE is set
        :param result: response from candlepin server
        :return: None
        ZSUBMAN_DEBUG_PRINT_RESPONSErzz	Response:�statuszResponse headers:r�r�zResponse body:N)r}r~r|r�rrrrrrr)r�rrr� _print_debug_info_about_response�s	z,BaseRestLib._print_debug_info_about_responsecCs�z2ddl}z|jjj}Wnty.d}Yn0WntyHd}Yn0|durZt�}n|}|r�|���dd��	dd�d|j
d<dS)z
        Set accepted language in http header according current settings or environment variable
        :return: None
        rNr�-r�ryzAccept-Language)�subscription_manager.i18nZi18n�LOCALE�language�AttributeError�ImportErrorr�r�r0r�r�)r9�subscription_managerrZlcrrr�_set_accept_language_in_header�s
z*BaseRestLib._set_accept_language_in_header)�keep_alive_headerr!c	Cs�d}d}t�d�}|��}|D]x}|�|�}|dur�|��\}}|dkrZt|��d�}q�|dkrtt|��d�}q�t�d|���qt�d|���q||fS)z�
        Try to parse 'Keep-Alive' header received from candlepin server
        :param keep_alive_header: string with value of the header
        :return: Tuple containing connection timeout and maximal number of requests
        Nz^(.*)=(\d+)[,;]*$rtry�maxzUnknown Keep-Alive argument: z1Unable to parse value of Keep-Alive HTTP header: )�re�compiler��search�groupsr"r.r)	rr�r��patternr��itemZ
search_result�keyrrrr�parse_keep_alive_header�s

z#BaseRestLib.parse_keep_alive_header)r�rYr�r�r��descriptionr!cCsHd}d}t�|���|D�]�\}	}
z�|j|	|
d�}|�||||�t��}||_|j||||d�t��}
|��}|�|
|�|�	��
d�|jt|�
��d�}|jdkr�d|_W�q n|jr�t�d|t|j�f�Wqtj�y.|j�r |j�s t�|j�}|���s d	|_t��|j�s*�Yqtj�yx}z0|j�rb|j�rbt|j|j|d
���WYd}~qd}~0tj t!f�y�}zht"|t#��r�|j�r�|j�r�t|j|j|d
��t$j%j&}t'|�t'|�v�r�t|j|j|d
���WYd}~qd}~00q|j�r t(dt|j�|f��Wd�n1�s60Y||fS)a

        Try to do HTTP request
        :param request_type: string representing request type
        :param handler: path of the request
        :param final_headers: dictionary with HTTP headers
        :param body: body of request if any
        :param cert_key_pairs: list of tuples. Tuple contain cert and key
        :param description: description of request
        :return: tuple of two items. First is dictionary (content, status and header) of response.
            Second item is response from server.
        N)rnro)r�r�r�)r�rr���Tz-Unable to get valid response: %s from CDN: %sFrDzKCannot access CDN content on: %s using any of entitlement cert-key pair: %s))rZLiveStatusMessager�rr�r�ZrequestZgetresponse�_update_smoothed_response_time�readr�rr�Z
getheadersr�rpr.rr'r%rrWrnr�create_from_file�is_validr��socketZgaierrorrgrhrC�errorr[�
isinstance�ConnectionErrorr
�PROXY_AUTHENTICATION_REQUIREDrrQr?)r9r�rYr�r�r�r%�responser�rnror�Zts_startZts_end�id_certrOr�rrr�
_make_request�sh
�

��
��$zBaseRestLib._make_request)r�r�r�r�r�r%r!cCs|j|}|��|dus&t|�dkr.|��}|durZd|vrZ|ddkrZt|��d�}n|durttj|tjd�}nd}|jdur�d|j	d<t
�d	||f�|jr�|j|j	d
<|j	�
�}	|dur�d|	d<|r�|	�|�z|�|||	|||�\}
}WnJtj�y>t
�d
�|��t
�d�|�|||	|||�\}
}Yn0|�|
�dt|
d�}|�d��rxd||�d�f}d|||f}t
�|�|jddd���}
|
dk�r�t
�d�nD|
dk�r�t
�d�|��n&|
dk�r�t
�d�nt
�d|
���|�d�}|jdu�rr|du�rr|�|�\}}|du�rN||j_t
�d|�d��|du�rr||j_t
�d|�d��|�d�}|du�rzRt|�}d|�d �}|tjd!d"�k�r�t
�|�n|tjd#d$�k�r�t
�|�Wn&t�y�t
�d%|�d&��Yn0|� |
||�|
S)'a�
        Make HTTP request to candlepin server
        :param request_type: string representing request type
        :param method: path of the request
        :param params: data (usually dictionary) of request if any
        :param headers: dictionary with HTTP headers
        :param cert_key_pairs: list of tuples. Tuple contain cert and key
        :param description: description of request
        :return: Dictionary (content, status and headers) of response.
        Nrr�r�r�)�defaultz
keep-aliveZ
ConnectionzMaking request: %s %sr��0zContent-LengthzConnection closed by serverzTrying request once againzResponse: status=rzx-candlepin-request-uuidz%s, requestUuid=%sz%s, request="%s %s"rzzServer wants to keep connectionr�z9Server wants to close connection. Closing HTTP connectionz1HTTP header 'Connection' not included in responsez/Unsupported value of HTTP header 'Connection': z
Keep-AlivezConnection timeout: z& is used from 'Keep-Alive' HTTP headerzMax number of requests: �datez&Local system clock seems to be off by z , please check your system time.ry)Zhours�)Zminutesz:Could not check if local clock is off from server's time '�')!r�rr�r�rr��json�dumpsr�r�r.rrr�copy�updater2r
ZRemoteDisconnectedr�rrQZ	getheaderr�r$r�Zmax_request_numr6r1�	timedeltar/r#�	exception�validateResult)r9r�r�r�r�r�r%rYr�r�r�r0Zresponse_logZconnection_http_headerZkeep_alive_http_headerr�r�Zresponse_sent_atr5rrrr�_requestNs�
��
�



�

�
�











�
�
zBaseRestLib._request)�
response_timecCsP|jdur||_n|j|jd|j||_t�d|d�d|jd�d��dS)z�
        Method for computing smoothed time of response. It is based on computing SRTT (See RFC 793).
        :param response_time: response time of the latest http request
        :return: None
        NryzResponse time statistics: z.4fzs (latest), zs (smoothed))r�r�r.r)r9r@rrrr'�s
�z*BaseRestLib._update_smoothed_response_time)r�r�rYr!c
Cs�t|d�dv�r�i}|�d�s&i}n�zt�|d�}Wn�ty|}z,t�d|d�t�d|�WYd}~nHd}~0ty�}z(t�d|d�t�|�WYd}~n
d}~00|�r�t|d�dkr�t	|d|d|d	��n(t|d�tt
j�k�rt|j
|jd
��|�|�}t|d�dv�rHt|d||�d�d
��t|d�dv�r�|j
�r�|j�r�t�|j�}|���r�t|dd|�d���t|d||�d���n�t|d�dv�r�t|d||d��n�t|d�dv�r�t|d||d��n�t|d�dv�r t|d||d��nxt|d�dv�rJt|d|�d�d
��nNt|d�tt
j�k�rtt|j
|jd
��n$t|d|�di��d�|�d���dS)a(
        Try to validate result of HTTP request. Raise exception, when validation of
        result failed
        :param result: Dictionary holding result
        :param request_type: String representation of original request
        :param handler: String containing handler of request
        r)Z200Z202Z204Z304r�zResponse: %szJSON parsing error: %sN�410�displayMessageZ	deletedIdrL)Z429r�)r�)Z401zmUnable to make a connection using SSL client certificate. Please review proxy configuration and connectivity.)�404rA�500Z502Z503Z504)r�rY)Z403�Content-Type)rQr|r8�loadsr�r.r,r#r=r�r
r/rCrgrh�#_parse_msg_from_error_response_bodyr�rnrr)r*r�r�r�r�r�)r9r�r�rY�parsedr�Z	error_msgr1rrrr>�s`

" 
�
��zBaseRestLib.validateResult)r�r!cCsDd|vr|dSd|vr0d�dd�|dD��Sd|vr@|dSdS)NrB�errorsr�css|]}d|VqdS)z%sNr)rw�errmsgrrr�	<genexpr>=�zBBaseRestLib._parse_msg_from_error_response_body.<locals>.<genexpr>Zerror_description)r�)r�rrrrG5sz/BaseRestLib._parse_msg_from_error_response_body)�request_resultr!cCsBt|d�sdSzt�|d�WStjy<|dYS0dS)a
        Extracts the data within the 'content' field of the result from a successful http response.
        :param request_result: Response result from an http request.
        :return: Data from the 'content' field of the result or None if the response had a 204 status.
        r�N)r�r8rFZJSONDecodeError)rMrrr�_extract_content_from_responseCs	z*BaseRestLib._extract_content_from_response)r�r�r�r%r!cCs|jd||||d�}|�|�S)NZGET)r�r�r%�r?rN)r9r�r�r�r%r�rrrr�Us
�zBaseRestLib.request_get)r�r�r�r%r!cCs|jd||||d�}|�|�S)NZPOST�r�r%rO�r9r�r�r�r%r�rrrr�as
�zBaseRestLib.request_post)r�r�r%r!cCs|jd|||d�}|�|�S)NZHEADrPrO)r9r�r�r%r�rrr�request_headiszBaseRestLib.request_headcCs|jd||||d�}|�|�S)NZPUTrPrOrQrrr�request_putms
�zBaseRestLib.request_putcCs|jd||||d�}|�|�S)NZDELETErPrOrQrrr�request_deleteus
�zBaseRestLib.request_delete)�dtr!cCst|dd�S)zJ
        Format a datetime to HTTP-date as described by RFC 7231.
        T)Zusegmtr)rUrrr�_format_http_date}szBaseRestLib._format_http_date)NNNNNNNNNNFNNNNN)NN)N)NNNN)NN)NNN)NNN)NN)NNN)NNN)0r;r<r=r@r�r��float�__annotations__r�r"rQrr�r\rIr�rrr�rr�r�r
r�r�r�r	rr�staticmethodrrr$rZHTTPResponser2r?r'r>rGrNr�r�rRrSrTr1rVrrrrr�Ms�
��@\�v*&�$�S�
�Z
��
����	��r�cs�eZdZdZdd��fdd�Zdd�dd�Zed�dd	�Zee	e
d
�dd�Zed�d
d�Z
e	e
d�dd�Zed�dd�Ze	e	e	ee	efd�dd�Zd�e	e	eee	e	e	e	ee	e	ee	ee	ee	fe	e	e	ed�dd�Zd�e	e	eeed�dd�Zd�e	eeedfd�d d!�Zd�e	eed"�d#d$�Zd�e	eeeee	eefe	e	e
e	ee	ee	ee	fe	e	ed%�d&d'�Ze	ed(�d)d*�Ze	e	ed+�d,d-�Ze	e	ed+�d.d/�Zeee	eefeee	eefd0�d1d2�Zee	efee	efd3�d4d5�Ze	eed6�d7d8�Z e	eeed9�d:d;�Z!e	ed(�d<d=�Z"d�e	e#j#ed>�d?d@�Z$d�e	e#j#ed>�dAdB�Z%e	edC�dDdE�Z&e	ed(�dFdG�Z'e	eedH�dIdJ�Z(e	e
dK�dLdM�Z)d�e	eeee	eedN�dOdP�Z*e	eedK�dQdR�Z+d�e	e#j#edS�dTdU�Z,d�e	e	e-eedV�dWdX�Z.d�e	e#j#eedY�dZd[�Z/e	e	e
d\�d]d^�Z0e	e	e
d_�d`da�Z1e	edK�dbdc�Z2d�e	e
e#j#e	e	e	e#j#e-e-eedf�
dgdh�Z3e	edK�didj�Z4e	eedK�dkdl�Z5d�e	e
eedm�dndo�Z6e	ee	dC�dpdq�Z7e	eedC�drds�Z8e	edK�dtdu�Z9d�e	e
e
dw�dxdy�Z:ed�dzd{�Z;e	eedK�d|d}�Z<e	eeeed~�dd��Z=d�e	eeeed��d�d��Z>d�e	e	e	eedfd��d�d��Z?e	e	d��d�d��Z@d�e	e
e	d��d�d��ZA�ZBS)��
UEPConnectionzh
    Class for communicating with the REST interface of a Red Hat Unified
    Entitlement Platform.
    NrJcsVdt�tj�}d|vr$||d7}d|vr8||d7}tt|�jfd|i|��dS)aT
        Multiple ways to authenticate:
            - username/password for HTTP basic authentication. (owner admin role)
            - uuid/key_file/cert_file for identity cert authentication.
              (consumer role)
            - token (when supported by the server)

        Must specify only one method of authentication.
        zRHSM/1.0 (cmd=%s)r�Zdbus_senderrrN)rr�r�r�r�rZrI)r9r�rrr�rrrI�s
zUEPConnection.__init__cCsHi|_|jjdtd�d�}|D]}|d|j|d<qt�d|j�dS)a�
        Load the list of supported resources by doing a GET on the root
        of the web application we're configured to use.

        Need to handle exceptions here because sometimes UEPConnections are
        created in a state where they can't actually be used. (they get
        replaced later) If something goes wrong making this request, just
        leave the list of supported resources empty.
        r�zFetching supported resources�r%Zhref�relz+Server supports the following resources: %sN)r�r�r�rr.r)r9Zresources_list�rrrr�_load_supported_resources�s

z'UEPConnection._load_supported_resourcescCs|jdur|��|jS)z_
        Get list of supported resources.
        :return: list of supported resources
        N�r�r^rKrrr�get_supported_resources�s
z%UEPConnection.get_supported_resources)�
resource_namer!cCs|jdur|��||jvS)z�Check if the server supports a particular resource.

        :param resource_name:
            Resource to be requested.
            When `None`, API call 'GET /' is made to cache all supported resources.
        Nr_)r9rarrr�supports_resource�s
zUEPConnection.supports_resourcecCs\|��}|�d�}|dur.t�d|�g}n*t|t�rL|sLt�d|�nt�d|�|S)zo
        Loads manager capabilities by doing a GET on the status
        resource located at '/status'
        ZmanagerCapabilitiesNzaThe status retrieved did not                       include key 'managerCapabilities'.
Status:'%s'zHThe managerCapabilities list                       was empty
Status:'%s'z)Server has the following capabilities: %s)�	getStatusr|r.rr-�list)r9rr�rrr�_load_manager_capabilities�s"
����z(UEPConnection._load_manager_capabilities)�
capabilityr!cCs|jdur|��|_||jvS)zU
        Check if the server we're connected to has a particular capability.
        N)r�re)r9rfrrr�has_capability�s

zUEPConnection.has_capabilitycOs|jjdtd�d�S)Nz/status/zChecking connection statusr[�r�r�r)r9�argsr�rrr�ping�szUEPConnection.ping)�cloud_id�metadata�	signaturer!cCs,|||d�}ddi}|jjd||td�d�S)a9Obtain cloud JWT.

        This method is part of the Cloud registration v2: standard or anonymous flow.

        :param cloud_id: Cloud provider, e.g. 'aws', 'azure' or 'gcp'.
        :param metadata: Base64 encoded public cloud metadata.
        :param signature: Base64 encoded public cloud signature.
        )�typerlrmrEr�z/cloud/authorize?version=2zFetching cloud token)r�r�r�r%)r�r�r)r9rkrlrmr�r�rrr�getCloudJWT�s
���zUEPConnection.getCloudJWTr�system)�name�
consumer_type�facts�owner�environments�environment_names�keys�installed_products�uuid�
hypervisor_id�content_tags�role�addons�
service_level�usage�	jwt_tokenr!cCs�|duri}|||d�}|r$||d<|	r0|	|d<|
durDd|
i|d<|durT||d<|durd||d<|
durt|
|d<|dur�||d	<|dur�||d
<|dur�|�t�r�g}|�d�D]}|�d|i�q�||d
<n@|du�r|�t��rg}|�d�D]}|�d|i�q�||d
<i}|�r,dj|d�|d<d}|�rR|�t��sRd|�|�}nR|�r�td|i�}d||f}d}|�r�|d}|D]}|||�|�}d}�q�|jj|||t	d�d�S)z8
        Creates a consumer on candlepin server
        N)rnrqrs�installedProductsry�hypervisorId�contentTagsr|�addOnsr�serviceLevel�,�idrurqzBearer {jwt_token})r�r�z
/consumersz/environments/%s/consumersrtz%s?%srzz&activation_keys=zRegistering systemrP)
rg�	MULTI_ENVr�r��format�sanitizerr�r�r)r9rqrrrsrtrurvrwrxryrzr{r|r}r~rr�r��env_list�environmentZ
env_name_listZenv_namer��urlZquery_paramZprependr#rrr�registerConsumer�s`�
zUEPConnection.registerConsumer)rt�env�host_guest_mapping�optionsr!c
Cs�|�d�r�|jjd}d|jjd<|dd�}|rN|jrNt|j�dkrN|j|d<t|�}d||f}|jj||td	�d
�}	||jjd<n,t||d��}d|}|jj||td	�d
�}	|	S)
a&
        Sends a mapping of hostIds to list of guestIds to candlepin
        to be registered/updated.
        This method can raise the following exceptions:
            - RestLibException with http code 400: this means no mapping
            (or a bad one) was provided.
            - RestLibException with other http codes: Please see the
            definition of RestLibException above for info about this.
            - RateLimitExceededException: This means that too many requests
            have been made in the given time period.

        Zhypervisors_asyncr�z
text/plainF)r�Zcloakedr�reporter_idz/hypervisors/%s?%sz8Updating detected virtual machines running on given hostr[)rtr�z/hypervisors?%s)rgr�r�r�r�rr�r)
r9rtr�r�r�ZpriorContentTyper��query_paramsr��resrrr�hypervisorCheckInNs,


��zUEPConnection.hypervisorCheckIn)rtr�r!cCs\|�d�r"|r"|jr"t|j�dks&dSi}|j|d<t|�}d||f}|jj|td�d�S)a*
        Sends the reporter id to candlepin
        to update the hypervisors it has previously reported.
        This method can raise the following exception:
            - RateLimitExceededException: This means that too many requests
            have been made in the given time period.
        Zhypervisors_heartbeatrNr�z/hypervisors/%s/heartbeat?%szUpdating hypervisor informationr[)rgr�r�rr�rSr)r9rtr�r�r�r�rrr�hypervisorHeartbeatxs

���
z!UEPConnection.hypervisorHeartbeat)�
consumer_uuidrsr!cCs|j||d�S)z>
        Update a consumers facts on candlepin server
        )rs)�updateConsumer)r9r�rsrrr�updateConsumerFacts�sz!UEPConnection.updateConsumerFacts)ryrsrx�guest_uuidsr~�release�autohealrzr{r|r}rrur!cCs<i}|dur||d<|dur*|�|�|d<|dur:||d<|durJ||d<|durZ||d<|durnd|i|d<|	dur~|	|d<|
dur�|
|d	<|dur�t|t�r�||d
<nt|t�r�|g|d
<|dur�||d<|
du�rg}|
�d�D]}|�d
|i�q�||d<|du�r||d<d|�|�}|jj||t	d�d�}|S)a�
        Update a consumer on the server.

        Rather than requiring a full representation of the consumer, only some
        information is passed depending on what we wish to update.

        Note that installed_products and guest_uuids expects a certain format,
        example parsing is in subscription-manager's format_for_server() method.

        This can raise the following exceptions:
            - RestlibException - This will include an http error code and a
            translated message that provides some detail as to what happend.
            - GoneException - This indicates that the consumer has been deleted
        Nr��guestIdsrsZ
releaseVerr�r�r�r|r�rr�r�rur��
/consumers/%szUpdating consumer informationr[)
�sanitizeGuestIdsr-rdrQr�r�r�r�rSr)r9ryrsrxr�r~r�r�rzr{r|r}rrur�r�r�r��retrrrr��sD





zUEPConnection.updateConsumer)ryr!cCs"d|�|�}|jj|td�d�S)Nz/consumers/%s/guestids�Fetching guest informationr[�r�r�r�r�r9ryr�rrr�getGuestIds�szUEPConnection.getGuestIds)ry�
guest_uuidr!cCs,d|�|�|�|�f}|jj|td�d�S)N�/consumers/%s/guestids/%sr�r[r��r9ryr�r�rrr�
getGuestId�szUEPConnection.getGuestIdcCs,d|�|�|�|�f}|jj|td�d�S)Nr�zRemoving guestsr[�r�r�rTrr�rrr�
removeGuestId�szUEPConnection.removeGuestId)r�r!cs�fdd�|pgD�S)Ncsg|]}��|��qSr)�sanitizeGuestId)rw�guestIdrKrrrx�rLz2UEPConnection.sanitizeGuestIds.<locals>.<listcomp>r)r9r�rrKrr��szUEPConnection.sanitizeGuestIds)r�r!cCsRt|t�r|St|t�rFdt|���vr>|�d�r6|S|dStd��td��dS)zj
        Sanitizes one or more provided guest Ids.
        :param guestId: One or more guest Ids.
        r�ZguestidszIError: A 'guestId' key was not found in the provided guest Id dictionary.z>Error: Only a string or dictionary data type can be sanitized.N)r-rQr�rdrwrb�KeyError�	TypeError)r9r�rrrr��s


zUEPConnection.sanitizeGuestId)r��	pkg_dictsr!cCs$d|�|�}|jj||td�d�S)z�
        Updates the consumer's package profile on the server.

        pkg_dicts expected to be a list of dicts, each containing the
        package headers we're interested in. See profile.py.
        z/consumers/%s/packages�Updating profile informationr[�r�r�rSr)r9r�r�r�rrr�updatePackageProfile�sz"UEPConnection.updatePackageProfile)r��profiler!cCs$d|�|�}|jj||td�d�S)a
        Updates the costumers' combined profile containing package profile,
        enabled repositories and dnf modules.
        :param consumer_uuid: UUID of consumer
        :param profile: Combined profile
        :return: Dict containing response from HTTP server
        z/consumers/%s/profilesr�r[r�)r9r�r�r�rrr�updateCombinedProfilesz#UEPConnection.updateCombinedProfilecCs"d|�|�}|jj|td�d�S)z�
        Returns a consumer object with pem/key for existing consumers
        :param uuid: UUID of consumer (part of installed consumer cert, when system is registered)
        r�zFetching consumer keysr[r�r�rrr�getConsumerszUEPConnection.getConsumer)ry�on_dater!cCs@d|�|�}|r,d||j|��dd�f}|jj|td�d�S)zP
        Returns a compliance object with compliance status information
        z/consumers/%s/compliance�
%s?on_date=%sT��pluszChecking compliance statusr[�r��	isoformatr�r�r�r9ryr�r�rrr�
getComplianceszUEPConnection.getCompliancecCs@d|�|�}|r,d||j|��dd�f}|jj|td�d�S)z_
        Returns a system purpose compliance object with compliance status information
        z /consumers/%s/purpose_compliancer�Tr�z)Checking system purpose compliance statusr[r�r�rrr�getSyspurposeCompliancesz%UEPConnection.getSyspurposeCompliance)�	owner_keyr!cCs"d|�|�}|jj|td�d�S)zM
        Retrieves the system purpose settings available to an owner
        z/owners/%s/system_purposez*Fetching available system purpose settingsr[r�)r9r�r�rrr�getOwnerSyspurposeValidFields(sz+UEPConnection.getOwnerSyspurposeValidFieldscCs"d|�|�}|jj|td�d�S)zM
        Returns an owner object with pem/key for existing consumers
        z/consumers/%s/owner�Fetching organizationsr[r�r�rrr�getOwner/szUEPConnection.getOwner)rlr!cCs8d|�|�}|jj|td�d�}dd�|p.gD�}|S)z�
        Returns a list of owners for given user. This method requires admin connection and authenticated
        using username/password
        z/users/%s/ownersr�r[cSsg|]}|dur|�qSrr)rw�xrrrrx@rLz.UEPConnection.getOwnerList.<locals>.<listcomp>r�)r9rlr�Zownersrrr�getOwnerList6szUEPConnection.getOwnerList)�
consumerIdr!cCs&d|�|�}|jj|td�d�duS)z�
        Deletes a consumer from candlepin server
        :param consumerId: consumer UUID (it could be found in consumer cert, when system is registered)
        r�zUnregistering systemr[Nr��r9r�r�rrr�unregisterConsumerCsz UEPConnection.unregisterConsumer)r��serials�jwtr!cCsTd|�|�}|r(d�|�}d||f}i}|r>d|��|d<|jj||td�d�S)a%
        Fetch all entitlement certificates for this consumer. Specify a list of serial numbers to
        filter if desired

        :param consumer_uuid: consumer UUID
        :param serials: list of entitlement serial numbers
        :param jwt: JWT identifying an anonymous system
        �/consumers/%s/certificatesr�z
%s?serials=%sr�r�zFetching certificatesrP)r�r�r�r�r)r9r�r�r�r�Zserials_strr�rrr�getCertificatesKs
zUEPConnection.getCertificatescCs"d|�|�}|jj|td�d�S)z�
        Get serial numbers for certs for a given consumer. Returned list is list of dictionaries, because
        it contains additional information about entitlement certificates
        :param consumerId: consumer UUID
        z"/consumers/%s/certificates/serialsz#Fetching certificate serial numbersr[r�r�rrr�getCertificateSerialscsz#UEPConnection.getCertificateSerials)r��if_modified_sincer!cCs8d|}i}|r"t�|�}||d<|jj||td�d�S)a�
        Get the content of the accessible content cert for a given consumer. This method works only in the
        case, when simple content access is used by current owner (organization)
        :param consumerId: consumer UUID
        :param if_modified_since: If present, only return the content if it was altered since the given date
        :return: Dictionary with the last modified date and the content
        z /consumers/%s/accessible_contentzIf-Modified-Sincez"Fetching content for a certificaterP)r�rVr�r�r)r9r�r�r�r�r(rrr�getAccessibleContentls

�z"UEPConnection.getAccessibleContent)r��poolId�quantityr!cCs<d|�|�|�|�f}|r(d||f}|jj|td�d�S)z�
        Subscribe consumer to a subscription by pool ID
        :param consumerId: consumer UUID
        :param poolId: pool ID
        :param quantity: the desired quantity of subscription to be consumed
        z"/consumers/%s/entitlements?pool=%sz%s&quantity=%s�Updating subscriptionsr[�r�r�r�r)r9r�r�r�r�rrr�bindByEntitlementPool}sz#UEPConnection.bindByEntitlementPool)r��entitle_dater!cCs@d|�|�}|r,d||j|��dd�f}|jj|td�d�S)a�
        Same as bindByProduct, but assume the server has a list of the
        system's products. This is useful for autosubscribe. Note that this is
        done on a best-effort basis, and there are cases when the server will
        not be able to fulfill the client's product certs with entitlements
        :param consumerId: consumer UUID
        :param entitle_date: The date, when subscription will be valid
        �/consumers/%s/entitlementsz%s?entitle_date=%sTr�r�r[)r�r�r�r�r)r9r�r�r�rrr�bind�s	zUEPConnection.bind)r��serialr!cCs4d|�|�|�t|��f}|jj|td�d�duS)z�
        Try to remove consumed pool by serial number
        :param consumerId: consumer UUID
        :param serial: serial number of consumed pool
        z/consumers/%s/certificates/%s�
Unsubscribingr[N)r�rQr�rTr)r9r�r�r�rrr�unbindBySerial�szUEPConnection.unbindBySerial)r��pool_idr!cCs0d|�|�|�|�f}|jj|td�d�duS)z�
        Try to remove consumed pool by pool ID
        :param consumer_uuid: consumer UUID
        :param pool_id: pool ID
        :return: None
        z"/consumers/%s/entitlements/pool/%sr�r[Nr�)r9r�r�r�rrr�unbindByPoolId�szUEPConnection.unbindByPoolIdcCs"d|�|�}|jj|td�d�S)z�
        Try to remove all consumed pools
        :param consumerId: consumer UUID
        :return: Dictionary containing statistics about removed pools
        r�r�r[r�r�rrr�	unbindAll�szUEPConnection.unbindAllFr)
�consumer�listAll�	active_onrt�
filter_string�future�
after_date�page�items_per_pager!c
Cs|r$d|�|�}
|r:d|
|f}
n|r2d|}
ntd��|rFd|
}
|dvrZd|
|f}
|rxd|
|j|��d	d
�f}
|r�|s�d|
|j|��d	d
�f}
|r�d|
|j|d	d
�f}
|d
kr�d|
|�|�f}
|	d
kr�d|
|�|	�f}
|jj|
td�d�}|S)z�
        List pools for a given consumer or owner.

        Ideally, try to always pass the owner key argument. The old method is deprecated
        and may eventually be removed.
        z/owners/%s/pools?z
%sconsumer=%sz/pools?consumer=%sz2Must specify an owner or a consumer to list pools.z%s&listall=true)�addZonlyz%s&%s_future=truez%s&after=%sTr�z%s&activeon=%sz
%s&matches=%srz
%s&page=%sz%s&per_page=%szFetching poolsr[)r�r#r�r�r�r)r9r�r�r�rtr�r�r�r�r�r��resultsrrr�getPoolsList�s.
zUEPConnection.getPoolsListcCs&d|�|�}|jj|td�d�}|S)z�
        Try to get current release for given consumer
        :param consumerId: consumer UUID
        :return: Dictionary with current release. It returns dictionary even no release is set.
            Like {'releaseVer': None}
        z/consumers/%s/releasezFetching release informationr[r�)r9r�r�r�rrr�
getRelease�szUEPConnection.getReleasecCs"d|�|�}|jj|td�d�S)a\
        Gets the available content releases for a consumer.

        NOTE: Used for getting the available release versions
              from katello. In hosted candlepin scenario, the
              release versions will come from the CDN directly
              (API not implemented in candlepin).
        :param consumerId: consumer UUID
        z /consumers/%s/available_releaseszFetching available releasesr[r�r�rrr�getAvailableReleases�s
z"UEPConnection.getAvailableReleases)r��
request_certsr!cCs8d|�|�}|sd}nd}|jj||td�d�}|S)a(
        Try to get list of consumed entitlement certificates
        :param consumerId: consumer UUID
        :param request_certs: If this argument is true, then response will include entitlement certs too
        :return: List of dictionaries containing information about entitlements
        r�z3?exclude=certificates.key&exclude=certificates.certrzzFetching entitlementsr[r�)r9r�r�r��filtersr�rrr�getEntitlementListsz UEPConnection.getEntitlementListcCs&d|�|�}|jj|td�d�}|S)zu
        List the service levels available for an owner
        :param owner_key: owner ID (organization ID)
        z/owners/%s/servicelevelszFetching service levelsr[r��r9r�r�r�rrr�getServiceLevelListsz!UEPConnection.getServiceLevelListcCs&d|�|�}|jj|td�d�}|S)z�
        List the environments for a particular owner.

        Some servers may not support this and will error out. The caller
        can always check with supports_resource("environments").
        z/owners/%s/environmentszFetching environmentsr[r�r�rrr�getEnvironmentListsz UEPConnection.getEnvironmentListcCs"d|�|�}|jj|td�d�S)z�
        Try to regenerate consumer certificate
        :param consumerId: consumer UUID
        :return: Dictionary containing information about consumer and new consumer certificate
        r�zUpdating certificater[r�r�rrr�regenIdCertificate$sz UEPConnection.regenIdCertificateT)�consumer_id�
lazy_regenr!c
Cs�d|�|�}|r|d7}d}z|jj|td�d�d}Wn`ttjtfy�}z@t|tj�slt	|j
�dkr�t�d�t�|�n|�WYd	}~n
d	}~00|S)
a�
        Regenerates all entitlements for the given consumer
        :param consumer_id: consumer UUID
        :param lazy_regen: When True then only mark certificates dirty and allow it to be regenerated
        on-demand on candlepin server. When False, then certificates are regenerated immediately
        :return True when regenerating of certificates was successful. Otherwise, return False
        r�z?lazy_regen=trueFzUpdating certificatesr[TrCzJUnable to refresh entitlement certificates: Service currently unsupported.N)
r�r�rSrr�r
Z
BadStatusLiner�r-rQr�r.r)r9r�r�r�r�r�rrr�regenEntitlementCertificates-s	
z*UEPConnection.regenEntitlementCertificatescCsd}|jj|td�d�S)z�
        Try to get information about status of server and supported capabilities
        :return: Dictionary with information about server
        z/statuszChecking server statusr[rh)r9r�rrrrcKszUEPConnection.getStatuscCs"d|�|�}|jj|td�d�S)zk
        Get all the overrides for the specified consumer
        :param consumerId: consumer UUID
        �/consumers/%s/content_overrideszFetching content overridesr[r�r�rrr�getContentOverridesSsz!UEPConnection.getContentOverrides)r��	overridesr!cCs$d|�|�}|jj||td�d�S)al
        Set an override on a content object
        :param consumerId: consumer UUID
        :param overrides: list of dictionaries. The dictionary have to have the following structure:
            {"contentLabel": "repo_id", "name": "label_name", "value": "label_value"}
        :return List of dictionaries containing all overrides for given repository
        r�zUpdating content overridesr[r�)r9r�r�r�rrr�setContentOverrides[sz!UEPConnection.setContentOverrides)r�r�r!cCs,d|�|�}|sg}|jj||td�d�S)aw
        Delete an override on a content object
        :param consumerId: consumer UUID
        :param params: List of dictionaries containing overrides to be deleted. The dictionary have to
            have the following structure: {"contentLabel": "repo_id", "name": "label_name"}
        :return List of dictionaries containing all overrides for given repository
        r�zRemoving content overridesr[r�)r9r�r�r�rrr�deleteContentOverridesfsz$UEPConnection.deleteContentOverrides)r��email�langr!cCspd|}|d|�|�7}|sFt��ddurFt��d���dd�}|r\|d|�|�7}|jj|td�d	�S)
a�
        Activate a subscription by machine, information is located in the consumer facts
        :param consumerId: consumer UUID
        :param email: The email for sending notification. The notification will be sent by candlepin server
        :param lang: The locale specifies the language of notification email
        :return When activation was successful, then dictionary is returned. Otherwise, None is returned.
        z/subscriptions?consumer_uuid=%sz	&email=%srNrrz&email_locale=%sZ
Activatingr[)r�r�r�r�r0r�r�r)r9r�r�r�r�rrr�activateMachinesszUEPConnection.activateMachine)�job_idr!cCs0tddi�}d||f}|jj|td�d�}|S)z8
        Returns the status of a candlepin job.
        Zresult_dataTz/jobs/%s?%szFetching jobr[)rr�r�r)r9r�r�r�r�rrr�getJob�szUEPConnection.getJob)�	url_paramr�r!cCs"|rtt|��}ntt|��}|S)a
        This is a wrapper around urllib.quote to avoid issues like the one
        discussed in http://bugs.python.org/issue9301
        :param url_param: String with URL parameter
        :param plus: If True, then replace ' ' with '+'
        :return: Sanitized string
        )rrQr)r9r�r�Zsane_stringrrrr��szUEPConnection.sanitize)rrpNNNNNNNNNNNNNN)N)N)N)NNNNNNNNNNNN)N)N)NN)N)N)N)	NFNNNNNrr)F)T)N)N)F)Cr;r<r=r@rIr^r�r`rrQr�rbrdrergrrjrro�setr	rr�r�r�r�r�r�r�r�r�r�r�r�r�r1r�r�r�r�r�r�r�r�r�r"r�r�r�r�r�r�r�r�r�r�r�r�r�rcr�r�r�r�r�r�r�rrr�rrZ�s
��P*	��F0 
		
��		
��2
		
	rZ)N)]r�r>rr1Zdateutil.parserr*r�Zloggingr}r+r�r�r�typingrrrrrrr	�pathlibr
rr]Zemail.utilsrZ
rhsm.httpsr
rZurllib.requestr�urllib.parserrrrZrhsm.configrrr8rZsubscription_manager.versionr�versionZpkg_versionr�rrrrrQr{r�r�r"r$r'r<r6ZHandlerr7�hZ	getLoggerZ
addHandlerr;r.r#r?rArCrSrTrX�Enumr\rcr�r�r�r�r�r�r�r�r�r�r�r�r�r�r�rZrrrr�<module>s�$

&
>