Ñò ¯ÉzQc@sédZddkZddkZddkZddkZddkiiZddk ii Z ddk Z ddk Z ddkZ ddklZddklZeidƒdj peiiddƒdj Zdefd„ƒYZdS( s‹ Interfaces used within the package client to operate on a remote image. Primarily used by linked images when recursing into child images. iÿÿÿÿN(tglobal_settings(t DebugValuestpkgremote_debugtPKG_PKGREMOTE_DEBUGt PkgRemotecBsÔeZdZdZdZdZd„Zeed„Zd„Z d„Z d„Z d „Z d „Z dd „Zd „Zd „Zd„Zd„Zd„Zd„Zd„Zd„Zd„Zd„Zd„ZRS(saThis class is used to perform packaging operation on an image. It utilizes the "remote" subcommand within the pkg.1 client to manipulate images. Communication between this class and the "pkg remote" process is done via RPC. This class essentially implements an RPC client and the "pkg remote" process is an RPC server.s call-idles call-setups call-startedcCs}d|_d|_d|_d|_d|_d|_|i|_d|_ d|_ d|_ d|_ d|_ |iƒdS(N(tNonet_PkgRemote__rpc_server_proct_PkgRemote__rpc_server_fstdoutt_PkgRemote__rpc_server_fstderrt%_PkgRemote__rpc_server_prog_pipe_fobjt_PkgRemote__rpc_clientt%_PkgRemote__rpc_client_prog_pipe_fobjt_PkgRemote__IDLEt_PkgRemote__statet_PkgRemote__pkg_opt_PkgRemote__kwargst_PkgRemote__async_rpc_callert_PkgRemote__async_rpc_waitert_PkgRemote__resultt_PkgRemote__set_state_idle(tself((s:/usr/lib/python2.6/vendor-packages/pkg/client/pkgremote.pyt__init__Bs            cCsptpdS|odt|ƒ}n,|odt|ƒ}ndt|ƒ}tiid||fƒdS(sLog debugging messages.NsPkgRemote(%s) client thread 1: sPkgRemote(%s) client thread 2: sPkgRemote(%s) client: s%s%s(RtidRtloggertinfo(Rtmsgtt1tt2tprefix((s:/usr/lib/python2.6/vendor-packages/pkg/client/pkgremote.pyt __debug_msgXsc CsÝtiiƒd|dtidd|d|iƒg}|iddi|ƒƒti ƒ}ti ƒ}y"ti i |d|d |ƒ}Wn$t j o}t i|ƒ‚nX||_||_||_||_d S( sŽFork off a "pkg remote" server process. 'img_path' is the path to the image to manipulate. 'server_cmd_pipe' is the server side of the command pipe which the server will use to receive RPC requests. 'server_prog_pipe_fobj' is the server side of the progress pipe which the server will write to to indicate progress.s-Rs --runid=%stremotes --ctlfd=%ss --progfd=%ssRPC server cmd: %st tstdouttstderrN(tpkgtmisct api_pkgcmdRt client_runidtfilenot_PkgRemote__debug_msgtjointtempfilet TemporaryFilet pkgsubprocesstPopentOSErrortapxt_convert_errorRRRR ( Rtimg_pathtserver_cmd_pipetserver_prog_pipe_fobjtpkg_cmdtfstdouttfstderrtpte((s:/usr/lib/python2.6/vendor-packages/pkg/client/pkgremote.pyt__rpc_server_forkgs$       c Cstiƒ\}}tiƒ\}}ti|dƒ}ti|dƒ}tii|ƒ}|i|||ƒti|ƒ||_||_ dS(scStart a new RPC Server process. 'img_path' is the path to the image to manipulate.trwN( tostpipetfdopenR"t pipeutilstPipedServerProxyt_PkgRemote__rpc_server_forktcloseR R ( RR0tclient_cmd_pipeR1tclient_prog_pipetserver_prog_pipetclient_prog_pipe_fobjR2t rpc_client((s:/usr/lib/python2.6/vendor-packages/pkg/client/pkgremote.pyt__rpc_server_setups    cCs˜d|_|io|iiƒ|iiƒnd|_d|_d|_|io|iiƒn|i o|i iƒnd|_ d|_ dS(s)Close connection to a RPC Server process.N( RR Rt terminatetwaitRRRR(RR R (R((s:/usr/lib/python2.6/vendor-packages/pkg/client/pkgremote.pyt__rpc_server_fini¯s         cCs |iiƒS(ssReturn the progress pipe for the server process. We use this to monitor progress in the RPC server(R R&(R((s:/usr/lib/python2.6/vendor-packages/pkg/client/pkgremote.pyR&ËscCsZ|iiƒ}tiƒ}|i|tiƒx%|idƒoti|dƒq1WdS(sDrain the client progress pipe.ii(N(R R&tselecttpolltregistertPOLLINR:tread(RtprogfdR6((s:/usr/lib/python2.6/vendor-packages/pkg/client/pkgremote.pyt__rpc_client_prog_pipe_drainÑs  cCsp|dj o+|i|jptd|i|f‚n |i}||ijo©|idjptd|i‚|idjptd|i‚|idjptd|i‚|idjptd|i‚|idjptd|i‚ns||i jo©|idj ptd|i‚|idj ptd|i‚|idjptd|i‚|idjptd|i‚|idjptd|i‚nº||i jo©|idj ptd|i‚|idj ptd|i‚|idj ptd|i‚|idj ptd|i‚|idjptd|i‚ndS(sSanity check our internal call state. 'state' is an optional parameter that indicates which state we should be in now. (without this parameter we just verify that the current state, whatever it is, is self consistent.)s%s == %ss %s is Nones%s is not NoneN( RR tAssertionErrorR RRRRRt_PkgRemote__SETUPt_PkgRemote__STARTED(Rtstate((s:/usr/lib/python2.6/vendor-packages/pkg/client/pkgremote.pyt__state_verifyÚsJ  cCse|iƒ|i|_d|_d|_d|_d|_d|_|i d|iƒ|iƒdS(sHEnter the __IDLE state. This clears all RPC call state.sset call state: %sN( t_PkgRemote__state_verifyR R RRRRRRR'(R((s:/usr/lib/python2.6/vendor-packages/pkg/client/pkgremote.pyt__set_state_idle s       cCsY|id|iƒ|i|_||_||_|id|i|fƒ|iƒdS(shEnter the __SETUP state. This indicates that we're all ready to make a call into the RPC server. 'pkg_op' is the packaging operation we're going to do via RPC 'kwargs' is the argument dict for the RPC operation. 't' is the RPC client thread that will call into the RPC server.RTsset call state: %s, pkg op: %sN(RVR RRR RRR'(Rtpkg_optkwargs((s:/usr/lib/python2.6/vendor-packages/pkg/client/pkgremote.pyt__set_state_setups     cCsS|id|iƒ|i|_||_||_|id|iƒ|iƒdS(s£Enter the __SETUP state. This indicates that we've started a call to the RPC server and we're now waiting for that call to return.RTsset call state: %sN(RVRRRSR RRR'(Rtasync_rpc_callertasync_rpc_waiter((s:/usr/lib/python2.6/vendor-packages/pkg/client/pkgremote.pyt__set_state_started7s    c Ksù|id||fdtƒd}}t||ƒ}y||}Wn2tj o&}|idtiƒdtƒnX|id|dtƒ|idƒdi|i ƒƒ} |idƒdi|i ƒƒ} |iddtƒ||| | fS( sûRPC thread callback. This routine is invoked in its own thread (so the caller doesn't have to block) and it makes a blocking call to the RPC server. 'kwargs' is the argument dict for the RPC operation.sstarting pkg op: %s; args: %sRscaught exception %ss returned: %sittexitingN( R'tTrueRtgetattrt Exceptiont tracebackt format_exctseekR(t readlines( RR4R5RERXRYtrvR7t rpc_methodR R!((s:/usr/lib/python2.6/vendor-packages/pkg/client/pkgremote.pyt__rpc_async_callerHs      cCsj|iddtƒ|iƒyti|iƒdƒWnttfj onX|iddtƒdS(sRPC waiter thread. This thread waits on the RPC thread and signals its completion by writing a byte to the progress pipe. The RPC call thread can't do this for itself because that results in a race (the RPC thread could block after writing this byte but before actually exiting, and then the client would read the byte, see that the RPC thread is not done, and block while trying to read another byte which would never show up). This thread solves this problem without using any shared state.tstartingRt.R_N(R'R`R(R:twriteR&tIOErrorR-(Rt async_callt prog_pipe((s:/usr/lib/python2.6/vendor-packages/pkg/client/pkgremote.pyt__rpc_async_waiterjs  cKs|i||ƒ|iƒdS(s¸Prepare to perform a RPC operation. 'pkg_op' is the packaging operation we're going to do via RPC 'kwargs' is the argument dict for the RPC operation.N(t_PkgRemote__set_state_setupt&_PkgRemote__rpc_client_prog_pipe_drain(RRXRY((s:/usr/lib/python2.6/vendor-packages/pkg/client/pkgremote.pyt__rpc_client_setupscKs.|idƒ|i|ƒ|i||dS(sPublic interface to setup a remote packaging operation. 'img_path' is the path to the image to manipulate. 'pkg_op' is the packaging operation we're going to do via RPC 'kwargs' is the argument dict for the RPC operation.ssetup()N(R't_PkgRemote__rpc_server_setupt_PkgRemote__rpc_client_setup(RR0RXRY((s:/usr/lib/python2.6/vendor-packages/pkg/client/pkgremote.pytsetup‹s  cCs–|idƒ|i|iƒtiiƒ}|i|i|i|i |i |i |i tiiƒ}|i|i ||iƒ|i||ƒdS(s7Public interface to start a remote packaging operation.sstart()N(R'RVRRR"R#t AsyncCalltstartt_PkgRemote__rpc_async_callerRRR RRt_PkgRemote__rpc_async_waiterR t_PkgRemote__set_state_started(RR[R\((s:/usr/lib/python2.6/vendor-packages/pkg/client/pkgremote.pyRx˜s    cCsj|idƒ|i|i|igjpt‚|iƒ|i|ijo t}n|iiƒ}|S(sRPublic interface to query if a remote packaging operation is done.s is_done()( R'R RRRSRQRrtFalseRtis_done(RRg((s:/usr/lib/python2.6/vendor-packages/pkg/client/pkgremote.pyR}¯s #  cCsì|idƒ|i|iƒd}}y|iiƒ}Wntiij o }nXt i }d}}|djo|\}}}}nt |ƒt jo t i }n|dj o t i }n|i ƒ|iƒ||||fS(sgPublic interface to get the result of a remote packaging operation. If the operation is not yet completed, this interface will block until it finishes. The return value is a tuple which contains: 'rv' is the return value of the RPC operation 'e' is any exception generated by the RPC operation 'stdout' is the standard output generated by the RPC server during the RPC operation. 'stderr' is the standard output generated by the RPC server during the RPC operation.sresult()R^N(R'RVRSRRtresultR"R#tAsyncCallExceptiontpkgdefst EXIT_OOPSttypetintt_PkgRemote__rpc_server_finiR(RtrvtupleR7RgR R!((s:/usr/lib/python2.6/vendor-packages/pkg/client/pkgremote.pyR~Ás$          cCsH|i|i|igjpt‚|idƒ|iƒ|iƒdS(s7Public interface to abort an in-progress RPC operation.scall abort requestedN(R RRRSRQR'R„R(R((s:/usr/lib/python2.6/vendor-packages/pkg/client/pkgremote.pytabortôs#  N(t__name__t __module__t__doc__R RRRSRR|R'R?RtR„R&RrRRVRRqR{RyRzRuRvRxR}R~R†(((s:/usr/lib/python2.6/vendor-packages/pkg/client/pkgremote.pyR6s.  (   2    "    3(R‰R:RJR)Rctpkg.client.api_errorstclientt api_errorsR.tpkg.client.pkgdefsR€tpkg.miscR"t pkg.nrlockt pkg.pipeutilst pkg.clientRtpkg.client.debugvaluesRt get_valueRtenvirontgetRtobjectR(((s:/usr/lib/python2.6/vendor-packages/pkg/client/pkgremote.pyts