!;Vc@sOdZddkZddkZddkZddkZddklZddkZddk Z ddk Z ddk Z ddk l Z lZlZddkiiiiiiZddklZlZlZlZlZlZlZl Z l!Z!l"Z"l#Z#ddk$Z$e$i%dde&dZ'd Z(d Z)d Z*d Z+d dgZ,d Z-d Z.dZ/dZ0e0Z1ddddgZ2de i3fdYZ4de#fdYZ5de i3fdYZ6de7fdYZ8de7fdYZ9de7fd YZ:d!e7fd"YZ;d#e7fd$YZ<d%Z=e>e?e>e>d&Z@d'ZAe>e?e>e>e>d(ZBe>e?e>e>e>e>d)ZCe'd*ZDe'e>d+ZEd,ZFe)d-ZGe)e>e>d.ZHd/ZIe>d0ZJe>d1ZKe>e>d2ZLe>e>e?e>e>e>d3ZMe>e>e?e>e>e>e>d4ZNe>d5ZOe>e>d6ZPdS(7sconnect - RAD connection oriented utilities This module facilitates communication with RAD instances via a number of alternative transports. The RadConnection class acts as the primary interface and offers a connection to a RAD instance which may be used to: - locate objects - invoke object methods - read/write object properties - subscribe/unsubscribe to object events iN(tSSL(t RADPackert RADUnpackertRecordMarkingSocket( t_Opt_Schemet _RequestErrort_ErrortADRNamet RADInterfacet _raise_errort _read_timet _ADRPatterntTypet RADStructtignoretcategorys/system/volatile/rad/radsockets%/system/volatile/rad/radsocket-unauthi0iitXDRs HTTP/JSONiitsuccesss2protocol requested (%d) is too old for this servers2protocol requested (%d) is too new for this servers7encoding requested (%s) is not supported by this servert _RadReadercBs eZdZdZdZRS(se A utility class which reads RAD protocol message and posts them on for further consumption. cCs&tii|t|_||_dS(s Create a RadReader object. N(t threadingtThreadt__init__tTruetdaemont _connection(tselft connection((s../common/connect.pyR\s cCsgy;x4to,|ii\}}|ii||qWWn%tj o}|ii|nXdS(s1 Called when a thread is started on this object. N(RRt _read_messaget _post_messaget Exceptiont _set_error(Rtmsgtserialtexc((s../common/connect.pytrunbs(t__name__t __module__t__doc__RR#(((s../common/connect.pyRYs tRadUpdateParametercBseZdZdZRS(s4A generic struct to use for passing _rad_update argscCst|||dS(N(tsetattr(Rtfieldtvalue((s../common/connect.pyRns(R$R%R&R(((s../common/connect.pyR'lst_RadEventReadercBs eZdZdZdZRS(s[ A utility class which reads RAD events and posts them on for further consumption. cCs&tii|t|_||_dS(s! Create a RadEventReader object. N(RRRRRR(RR((s../common/connect.pyRus c Cs5y xto|ii}|iiiizx|iiD]}|i|dijoqAn|di |i }d}|i dj o.|i it|it|i |i}n%|i it|it|i}|d|||dqAWWdQXqWWn%tj o}|ii|nXdS(s1 Called when a thread is started on this object. iiiN(RRt _read_eventt_slockt__exit__t __enter__t _subscriberstsourcet_idt_eventsteventtNonetsubtypettypet_unpackRtpayloadtFalseRR(Rtevttsubt event_typetobjR"((s../common/connect.pyR#{s*    +(R$R%R&RR#(((s../common/connect.pyR+rs t RadConnectioncBseZdZededZdZdZdZ dZ dZ dZ dZ d Zd Zd Zd Zd ZdddZddZdZddZdZddZddZdZdZRS(s! A connection to a RAD instance. c Csti|_ti|_ti|_ti|_ti|i|_ti|i|_d|_ h|_ g|_ g|_ t||_d|_d|_d}|djobtti}|ddgjo d}q |ddjod|dN(RIR5(Rtstate((s../common/connect.pyt__repr__s c Cs|iiiz.|ip t||_|iinWdQX|iiiz.|ip t||_|iinWdQXdS(s Start our reader thread. N( RER.R/RLRtstartR-RMR+(R((s../common/connect.pyRbs  cCsQ|iiiz6|iodS||_|ii|iiWdQXdS(s Set our closed error state. N(RDR.R/RIRGt notifyAllRH(Rterr((s../common/connect.pyRs    cCs1|iott|in|idS(s@ If we are closed, raise an IOError. Wait on the supplied cond. N(RItIOErrortstrtwait(Rtcond((s../common/connect.pyt_wait_until_closeds cCs2|iit|ii}||ifS(s Read a RAD protocol message. (RKt skip_recordRt read_recordt unpack_hyper(Rt munpacker((s../common/connect.pyR s cCsm|iiizR|djo'|iit||iin||i|<|i iWdQXdS(s Post a RAD protocol message, supplied in packed. If serial is not 0, then it is a request response from the server, otherwise it is an event response from the server. iN( RDR.R/R3tappendtRadEventRGRxRJRH(RtpackedR!((s../common/connect.pyRs   cCsM|i}|i}|tijo|i||St||dS(s7 Unpack a RAD protocol message, supplied in munpacker. N(t unpack_intt unpack_opaqueRtOKtresetR(RRterrorR9((s../common/connect.pyt_unpack_messages    c Cs|iiizU|ipG|i\}}||jotd||fn|i|SWdQX|iiizKx%||ijo|i |i qW|ii |}|i|SWdQXdS(sv Read a RAD protocol response and return the unpacked message. Ensure the serial number matches reqserial.s%Bad response (serial %d, expected %d)N( RER.R/RLRRRRDRJR~RHtpop(Rt reqserialRR!((s../common/connect.pyt_read_response)s  cCs|iiizi|i}t}|i||i||i||id7_|ii |i t |SWdQXdS(s Write a RAD protocol request and return the allocated serial number. The operation and buffer are packed before transmission.iN( RCR.R/RaRt pack_hypert pack_enumt pack_opaqueRKtwritet get_bufferR(RtopcodeRjR!trpacker((s../common/connect.pyt _make_request:s     cCs]|iiizBx+t|idjo|i|iqW|iidSWdQXdS(s} Perform a blocking read for an event. Arguments: Returns: RadEvent: A RAD event. iN(RDR.R/tlenR3R~RGR(R((s../common/connect.pyR,Hs cCs,t}h}|i}|dj o |i}n|i|i|it|it|x2|iD]'}|i||i|i|qlWx,|D]$}|i||i||qW|pt |i }d|d maximum supported by client (%d).isError listing %s: %sN(Rt_nameR5t_kvst pack_stringt_domaint pack_uintRt_kvpairsRNt_versionRUtpack_intt get_schemeRtGLOBRRtLISTRRRR R{t get_messaget unpack_uinttrangeRRR8R:(RtproxytpatternRgtlpackertsuffixtnametkeytsert lunpackertextnamestncountti((s../common/connect.pyt list_objectsWsL           #c Cst|to|i}|}n=t|to|i}|i}ntdt||dj ot|i |i i d|}t|t o|i i |iqt|to|i i |qtdt|nt}|i|i |it|i x2|i D]'}|i||i|i |q+W|i|id|i|id|iti|i}y|i|}Wn8tj o,} t| dt|| ifnX|||i||iS(s; Return a RadInterface which is identified by this name. Arguments: tgt: ADRName or Proxy a RAD ADRName or a Proxy object (for singletons) suffix: _ADRPattern or a dict a name suffix Returns: RadInterface a RADInterface object sillegal tgt, %s.Rsillegal suffix, %s.iisError getting %s: %sN(t isinstanceRt_proxyR t __class__RRUR{R5RRtcopyR tupdateRtdictRRRRRRRRtLOOKUPRRRR RR( RttgtRRRtgpackerRRt gunpackerR((s../common/connect.pyt get_objects>          cCs1g}x$|D]}|i|i|q W|S(s Return a list of RadInterfaces based on the list of ADRNames/Proxies Arguments: names: list of ADRName/Proxies a list of ADRName/Proxies Returns: list of RADInterfaces a list of RADInterface objects (RR(RRtresR((s../common/connect.pyt get_objectss cCs|i|}|i|S(s1 Create an object, based on a prototype. Arguments: tgt: prototype object a prototype of the object args: list of constructor arguments a list of arguments Returns: object of type tgt a proxy to the new server object (Rt _rad_create(RRtargstproto((s../common/connect.pyt create_objectscCs |iS(s Delete an object. Arguments: tgt: object to be deleted object Returns: None (t _rad_delete(RR((s../common/connect.pyt delete_objects cCs5x%|D]}t|||||R4tcallbacktusertevpackerRR((s../common/connect.pyt subscribes   # c Cst}|i|i|i||iti|i}yh|i||i i i z@g}|i D]"}|d|jo ||qtqt~|_ WdQXWn2t j o&}t|d||ifnXdS(s Unsubscribe from this object's event notifications. Arguments: obj: RadObject a RAD interface event: string name of the event Returns: iNsError unsubscribing from %s: %s(RRR2RRRtUNSUBRRR-R.R/R0RR R(RR>R4RRt_[1]R<R((s../common/connect.pyt unsubscribes   F cCs$|itd|iidS(sO Close this connection. Arguments: Returns: sclose() calledN(RRzRKRo(R((s../common/connect.pyRo3s N(R$R%R&RR5tRAD_PROTO_ENCODE_XDRRR/R.RvRbRR~RRRRRR,RRRRRRRRRo(((s../common/connect.pyR?s0 M        - 0      RcBseZdZdZRS(s A RAD event instance. source _Type.LONG id of generating object sequence _Type.LONG sequence number of event tstamp _Type.ULONG time of event event string event name payload _Type.OPAQUE event payload cCsO|i|_|i|_t||_|i|_|i|_dS(s Create a RadEvent object. Arguments: unpacker: Unpacker event unpacker Returns: RadEvent N( RR1tsequenceR ttstampt unpack_stringR4RR9(Rtunpacker((s../common/connect.pyRIs (R$R%R&R(((s../common/connect.pyR@stProcessPseudoSocketcBsDeZdZdZdZdZdZdZdZRS(s A class which implements a sufficient amount of the socket.socket interface to allow a pipe to communicate like a RecordMarkingSocket. cCs%||_|i|_|i|_dS(N(t_procesststdint_intstdoutt_out(Rtprocess((s../common/connect.pyRbs  cCs|S(N((R((s../common/connect.pyR/gscCs|itS(N(RoR:(RRpRqRr((s../common/connect.pyR.js cCsti|ii|S(N(tostreadRtfileno(Rtnbytes((s../common/connect.pyRRnscCs#|ii|}|ii|S(N(RRtflush(RRjtcnt((s../common/connect.pyR[ws cCs|iidS(N(Rt terminate(R((s../common/connect.pyRo|s( R$R%R&RR/R.RRR[Ro(((s../common/connect.pyR^s    tRadURIcBs5eZdZd ZedZdZd dZRS( tradtradstsshtunixtpamc Cs|i|d|_d|_||_d|_ti|_t |_ d|_ t |_ ti|i}|idjo|i|_n|i|jo#td|i||ifn|idjo|i|_n|i dj o|i |_ n|idjot|idjotd|in|i|_|iido*|iido|id d !|_qn(|idjotd |in|idjo|i|_ n|i d j o|i |_ n|i dj og}|i id D]!}|ido ||qq~}t|djodx6tiD]+}d|}||jo||_PqYqYW|idjotd|i qqd|_n d|_dS(s Create a RadURI instance. Arguments: src string, URI of a rad instance schemes list of strings, specifying which schemes are to be recognised Returns: RadURI: encapsulates useful information extracted from URI Rts'Scheme '%s' not in schemes '%s' in : %sRRs"Invalid URI, hostname required: %st[t]iis$Invalid URI, no hostname allowed: %st/t,sauth=isauth=%ss$Unrecognised authenticaton class: %sN(NR(NR(RRR(NR(NR(NR(t_RadURI__register_schemesR5tcredential_classtschemetsrcthosttgetpasstgetuserRt RAD_PORT_TLStporttauthtRAD_PATH_AFUNIX_AUTHtpathturlparseRUtusernamethostnamet startswithtendswithtquerytsplitRRtCREDENTIAL_CLASSES( RRtschemesturiRtatauthstklassR((s../common/connect.pyRs^         &A      cCs=x6tdttD]}tt|i|qWdS(s Modify urlparse so that it will be aware of our schemes. Arguments: schemes List of scheme names(strings) Returns: cSs |idS(tuses_(R(ts((s../common/connect.pytsN(tfiltertdirRtgetattrtextend(RRtmethod((s../common/connect.pyt__register_schemess cCsq|idjot|i|i}nb|idjot|i|i}n9|idjot|i|i}nt|i}|i dj o|dj o|i djotddk i }|i |}y|i|i|iWqHtj o)}|itdt|qHXqi|itd|iqm|itd |in|S( s Connect to a RAD instance at the specified URI. Arguments: cred Credentials, required for authentication Returns: RadConnection: a connection to RAD RRRRiNsAuthentication failed: %ss&Unrecognised authentication method: %ss5Authentication parameter is required for this URI: %s(Rt connect_tcpRRt connect_tlst connect_sshRt connect_unixRRR5trad.authRtRadAutht pam_logintpasswRRoRUR{R(RtcredtcontradaRte((s../common/connect.pytconnects2     (sradsradsssshR(spamN(R$R%t RAD_SCHEMESRRRR5R(((s../common/connect.pyRs  L t_ZonesBridgePseudoSocketcBsGeZdZddZdZdZdZdZdZ RS(s A class which implements a sufficient amount of the socket.socket interface to allow a zonesbridge.IO object communicate like a RecordMarkingSocket. cCs"||_|i|||_dS(N(t_ziotopenRadt_token(RtziotzoneR((s../common/connect.pyRs cCs|S(N((R((s../common/connect.pyR/scCs|itS(N(RoR:(RRpRqRr((s../common/connect.pyR."s cCs|ii|i|S(N(R RR"(RR((s../common/connect.pyRR&scCs|ii|i|dS(N(R RR"(RRj((s../common/connect.pyR[)scCs|ii|idS(N(R RoR"(R((s../common/connect.pyRo,sN( R$R%R&R5RR/R.RRR[Ro(((s../common/connect.pyRs     cCs+|dj o|ddjo ||S|S(s Return a path rooted at root. iRN(R5(trootR((s../common/connect.pyt _map_path3s cCst|ddt|ddt|dg}|d j o1xY|D]"}|idt||gqDWn,|idt|ddt|dg|o|idgn|d j o|i|n|id d g|S( s Get a List[string] suitable to use when spawning a RAD process via subprocess.Popen(). Arguments: modules List[string], a list of modules to load debug boolean, run the spawned RAD process in debug mode root string, root directory to use for the spawned RAD process auxargs List[string], additional argument to supply to the spawned RAD process Returns: List[string]: A list containing a command plus arguments s/usr/lib/rad/rads-Ms"/usr/lib/rad/transport/mod_pipe.sos&/usr/lib/rad/protocol/mod_proto_rad.sos-ms/usr/lib/rad/modules/usr/lib/rad/site-moduless-ds-ts stdin:exitN(R&R5R(tmodulestdebugR%tauxargstcmdtmodule((s../common/connect.pyt build_rad_cmd=s  $ cGsM|dj od||f}ndddddd|g}|i||S( s Get a command to ssh to the given host as the given user and run the given command remotely Arguments: host string, target host user string, remote user, or None to connect as the local user *remote_cmd arbitrary argument list, an optional command to run remotely Returns: List[string]: A list containing a command plus arguments s%s@%ss /usr/bin/sshs-qs-etnones-os BatchMode yesN(R5R(RRt remote_cmdR*((s../common/connect.pyt build_ssh_cmdds   cCsFt||||}ti|ddtitid|}t|S(st Get a transport suitable for connecting to a privately spawned RAD process. Arguments: modules List[string], a list of modules to load, or all system modules if not specified debug boolean, run the spawned RAD process in debug mode env Dictionary[string, string], environment for the spawned RAD process root string, root directory to use for the spawned RAD process auxargs List[string], additional argument to supply to the spawned RAD process Returns: ProcessPseudoSocket: a "socket" for a spawned RAD process itenvN(R,t subprocesstPopenR5tPIPER(R'R(R0R%R)R*Rc((s../common/connect.pyt_get_private_transports cCs(t|||||}t|d|S(s1 Connect to a privately spawned instance of RAD using a pipe. Arguments: modules List[string], a list of modules to load debug boolean, run the spawned RAD process in debug mode env Dictionary[string, string], environment for the spawned RAD process root string, root directory to use for the spawned RAD process auxargs List[string], additional argument to supply to the spawned RAD process locale string, locale Returns: RadConnection: a connection to RAD Re(R4R?(R'R(R0R%R)ReRc((s../common/connect.pytconnect_privatescCs)tititi}|i||S(s Get a transport suitable for connecting to a local RAD instance. Arguments: path string, path to the socket Returns: socket.socket: a Unix Domain(AF_UNIX) socket (tsockettAF_UNIXt SOCK_STREAMR(RRc((s../common/connect.pyt_get_unix_transports  cCst|}t|d|S(s Connect to a RAD instance over a Unix Domain Socket. Arguments: path string, path to the socket locale string, locale Returns: RadConnection: a connection to RAD Re(R9R?(RReRc((s../common/connect.pyRs cCs |djS(so callback for certificate validation should return true if verification passes and false otherwise i((tconntx509terrnoterrdepthtretcode((s../common/connect.pyt_tls_verify_cbscCstiti}|iti|iti|iti|dj o$|iti t |i |nt i t i t i}ti||}|i||f|i|S(s Get a TLS transport suitable for connecting to a remote host. Arguments: host string, target host port int, target port Returns: SSL.Connection: a TLS based socket N(RtContextt SSLv23_METHODt set_optionst OP_NO_SSLv2t OP_NO_SSLv3t OP_NO_TLSv1R5t set_verifyt VERIFY_PEERR?tload_verify_locationsR6tAF_INETR8t ConnectionRt do_handshake(Rtca_certsRtcontextRc((s../common/connect.pyt_get_tls_transports  cCs"t|||}t|d|S(s  Connect to a RAD instance over TLS. Arguments: host string, target host port int, target port locale string, locale ca_certs string, path to file containing CA certificates Returns: RadConnection: a connection to RAD Re(RNR?(RRReRLRc((s../common/connect.pyRscCs/tititi}|i||f|S(s Get a TCP transport suitable for connecting to a remote host. Arguments: host string, target host port int, target port Returns: socket.socket: a socket (R6RIR8R(RRRc((s../common/connect.pyt_get_tcp_transport)s cCst||}t|d|S(s Connect to a RAD instance over TCP. Arguments: host string, target host port int, target port locale string, locale Returns: RadConnection: a connection to RAD Re(ROR?(RRReRc((s../common/connect.pyR>scCs=t||d}ti|ddtiti}t|S(sA Get an SSH transport to a remote (unix domain socket) rad daemon. Arguments: host string, target host running a local (unix domain socket) rad daemon user string, remote user, or None to connect as the local user Returns: ProcessPseudoSocket: a "socket" for a spawned RAD process s/usr/lib/rad/radpipeiN(R/R1R2R5R3R(RRR*Rc((s../common/connect.pyt_get_ssh_transportPs !cCst||}t|d|S(s Connect to a remote host's (unix domain socket) rad daemon through SSH. The SSH connection must use non-interactive (i.e. agent-based) authentication and should not emit any output other than that of the remote rad daemon. Arguments: host string, target host running a local (unix domain socket) rad daemon user string, remote user, or None to connect as the local user locale string, locale Returns: RadConnection: a connection to RAD Re(RPR?(RRReRc((s../common/connect.pyResc CsLt||t||||}ti|ddtiti}t|S(s Get an SSH transport to a remote private copy of rad. Arguments: host string, target host user string, remote user, or None to connect as the local user modules List[string], a list of modules to load, or all system modules if not specified debug boolean, run the spawned RAD process in debug mode env Dictionary[string, string], environment for the spawned RAD process root string, root directory to use for the spawned RAD process auxargs List[string], additional argument to supply to the spawned RAD process Returns: ProcessPseudoSocket: a "socket" for a spawned RAD process iN(R/R,R1R2R5R3R( RRR'R(R0R%R)R*Rc((s../common/connect.pyt_get_ssh_private_transportys !c Cs.t|||||||}t|d|S(s} Connect to a privately spawned copy of rad on a remote host through SSH. The SSH connection must use non-interactive (i.e. agent-based) authentication and should not emit any output other than that of the remote rad daemon. Arguments: host string, target host user string, remote user, or None to connect as the local user modules List[string], a list of modules to load, or all system modules if not specified debug boolean, run the spawned RAD process in debug mode env Dictionary[string, string], environment for the spawned RAD process root string, root directory to use for the spawned RAD process auxargs List[string], additional argument to supply to the spawned RAD process locale string, locale Returns: RadConnection: a connection to RAD Re(RQR?( RRR'R(R0R%R)ReRc((s../common/connect.pytconnect_ssh_privates cCs%|iti}t|||S(s Get a transport suitable for connecting to a local zone. Arguments: rcon RadConnection, Connection to a global zone zone string, Name of a local zone user string, user name Returns: _ZonesBridgePseudoSocket: a "socket" for a local zone (Rt zonesbridgetIOR(trconR$RR#((s../common/connect.pyt_get_zone_transportscCs"t|||}t|d|S(s Connect to a RAD instance in a local zone. Arguments: rcon RadConnection, Connection to a global zone zone string, Name of a local zone user string, user name locale string, locale Returns: RadConnection: a connection to RAD Re(RVR?(RUR$RReRc((s../common/connect.pyt connect_zones(QR&RReRORR6tOpenSSLRRSR1RRtrad.encodings.xdrRRRt1rad.bindings.com.oracle.solaris.rad.zonesbridge_1tbindingstcomtoracletsolarisRt zonesbridge_1RStclientRRRRRR R R R R RtwarningstfilterwarningstDeprecationWarningRtRAD_PATH_AFUNIX_UNAUTHRRtRAD_PROTO_ENCODE_HTTP_JSONR`R\t RAD_PROTO_HANDSHAKE_ERR_OLDPROTOt RAD_PROTO_HANDSHAKE_ERR_NEWPROTOR^R]R_RRR'R+tobjectR?RRRRR&R5R:R,R/R4R5R9RR?RNRRORRPRRQRRRVRW(((s../common/connect.pyt%sz        L   !+ '     #     #