oB]c @sqddlZddlZddlZddlZddlZddlZddlZddlZddlZddl m Z ddl m Z ddl m Z ddl mZddlmZe jeZi defd6d efd 6d efd 6d efd 6defd6defd6defd6defd6defd6defd6defd6defd 6defd6Zidd6dd6d d!6Zd"Zd#Zd$Zd%egZddd dd&d gZd'Zd(Zd)Zied*6ed+6ed,6ed-6gd.6ed/6id0d16d26Z iiid3d46ed56ed66d16d76id1d86d9d:6d1d;6gd<6Z!d=Z"d>Z#d?e j$fd@YZ%dAe&fdBYZ'dCe'fdDYZ(dEe)fdFYZ*dGe*fdHYZ+dIe*fdJYZ,dKe,fdLYZ-deeeddMZ/dNZ0dedOdPZ1dddQZ2dddddRZ3e%e j4ffgZ5dSZ6edTkrmddl7Z7e/Z8e8dkrdUGHe7j9dVne:e7j;dVkre<ej=e<ej=dWgZ=n e7j;dVZ=dXZ>iZ?x'e=D]Z@e>dYe8dZe@d[e?q'WejAe?d\dVd]ed^daGHndS(biN(tlog(tserial(tsources(tutil(t EventTypessdc:uuids instance-idthostnameslocal-hostnametroot_authorized_keyss public-keyss user-scripts user-dataslegacy-user-datascloud-init:user-datatiptables_disablet motd_sys_infossdc:datacenter_nametavailability_zonessdc:vendor-datas vendor-datassdc:operator-scriptsoperator-scripts sdc:hostnamessdc:dns_domaint dns_domainssdc:nicss network-datas sdc:resolverst dns_serverss sdc:routestroutesslx-brandtkvmtSmartOSt datasourcessdc:uuiduser-datas"/native/.zonecontrol/metadata.socks /dev/ttyS1i<t serial_devicetserial_timeouttmetadata_sockfiletno_base64_decodet base64_keyst base64_alls/dev/vdbt ephemeral0t disk_aliasestmbrt table_typetlayoutt overwritet disk_setuptlabeltext4t filesystemtdevicetfs_setupsU#cloud-boothook #!/bin/sh fname="%(per_boot_d)s/01_smartos_vendor_data.sh" mkdir -p "${fname%%/*}" cat > "$fname" <<"END_SCRIPT" #!/bin/sh ## # This file is written as part of the default vendor data for SmartOS. # The SmartOS datasource writes the listed file from the listed metadata key # sdc:operator-script -> %(operator_script)s # user-script -> %(user_script)s # # You can view content with 'mdata-get ' # for script in "%(operator_script)s" "%(user_script)s"; do [ -x "$script" ] || continue echo "executing '$script'" 1>&2 "$script" done END_SCRIPT chmod +x "$fname" s/var/dbtDataSourceSmartOScBseZdZejZejZdZdZdZ dZ dZ dZ dZ dZd Zed ZRS( tJoyentcCstjj||||tj|jtj|titg|_i|_ d|_ d|_ |j djtjtjj|jjd|_|jdS(Ntnetworktscripts(Rt DataSourcet__init__Rt mergemanydicttds_cfgtget_cfg_by_patht DS_CFG_PATHtBUILTIN_DS_CONFIGtmetadatatNonet network_datat_network_configt update_eventstaddRtBOOTtostpathtjointpathst get_cpatht script_base_dt_init(tselftsys_cfgtdistroR7((sG/usr/lib/python2.7/site-packages/cloudinit/sources/DataSourceSmartOS.pyR's   !cCs#tjj|}d||jfS(Ns%s [client=%s](RR&t__str__t md_client(R;troot((sG/usr/lib/python2.7/site-packages/cloudinit/sources/DataSourceSmartOS.pyR>sc Cs|jtjkr<t|_|jdkr<d|_q<n|jtjkrtd|jd|jdd|jdd|jd|_ndS(Nt smartos_typeRRR(RARtUNSETtget_smartos_environR.R?tjmc_client_factoryR)(R;((sG/usr/lib/python2.7/site-packages/cloudinit/sources/DataSourceSmartOS.pyR:s    cCsitjdd}tjjdj|dgretjdj|dgdj|dgndS(sMark the instance provisioning state as successful. When run in a zone, the host OS will look for /var/svc/provisioning to be renamed as /var/svc/provision_success. This should be done after meta-data is successfully retrieved and from this point the host considers the provision of the zone to be a success and keeps the zone running. s-Instance provisioning state set as successfuls/var/svct/t provisioningtprovision_successN(tLOGtdebugR4R5texistsR6trename(R;tsvc_path((sG/usr/lib/python2.7/site-packages/cloudinit/sources/DataSourceSmartOS.pyt_set_provisioneds !c Cs|ji}d}|js0tjdtS|jjsVtjd|jtS|jjxBtj D]4\}}|\}}|jj |d|||R:RMRqRsRuRxRytpropertyR{(((sG/usr/lib/python2.7/site-packages/cloudinit/sources/DataSourceSmartOS.pyR"s      W    tJoyentMetadataFetchExceptioncBseZRS((R|R}(((sG/usr/lib/python2.7/site-packages/cloudinit/sources/DataSourceSmartOS.pyRSstJoyentMetadataTimeoutExceptioncBseZRS((R|R}(((sG/usr/lib/python2.7/site-packages/cloudinit/sources/DataSourceSmartOS.pyRWstJoyentMetadataClientcBseZdZejdZdddZdZdZ dZ dZ dZ ddZ ded Zdd Zd Zd Zd ZdZdZdZdZRS(s A client implementing v2 of the Joyent Metadata Protocol Specification. The full specification can be found at http://eng.joyent.com/mdata/protocol.html s~V2 (?P\d+) (?P[0-9a-f]+) (?P(?P[0-9a-f]+) (?PSUCCESS|NOTFOUND)( (?P.+))?)cCs.|dkrt}n||_||_dS(N(R.RCRAtfp(R;RAR((sG/usr/lib/python2.7/site-packages/cloudinit/sources/DataSourceSmartOS.pyR'gs   cCs#djtj|jdd@S(Ns{0:08x}sutf-8I(tformattbinasciitcrc32tencode(R;tbody((sG/usr/lib/python2.7/site-packages/cloudinit/sources/DataSourceSmartOS.pyt _checksummscCs|jj|j}t|dt|dkratdj|dt|dn|j|d}|d|krtdj||dn|d|krtdj||dn|jddst j d dSt j |d}t j d ||S( NtlengthRs*Incorrect frame length given ({0} != {1}).tchecksums*Invalid checksum (expected: {0}; got {1}).t request_ids-Request ID mismatch (expected: {0}; got {1}).tpayloadsNo value found.sValue "%s" found.(t line_regextmatcht groupdicttinttlenRRRR]R.RHRIRtb64d(R;texpected_request_idtframet frame_datatexpected_checksumtvalue((sG/usr/lib/python2.7/site-packages/cloudinit/sources/DataSourceSmartOS.pyt_get_value_from_frameqs(   csgfd}d}xtry^|jjd}t|dkrat||n|dkrt|Sj|Wqtk r}|jtjkrt||nqXqWdS(s Reads a line a byte at a time until is encountered. Returns an ascii string with the trailing newline removed. If a timeout (per-byte) is set and it expires, a JoyentMetadataFetchException will be thrown. csdjjdS(NRNtascii(R6tdecode((tresponse(sG/usr/lib/python2.7/site-packages/cloudinit/sources/DataSourceSmartOS.pytas_asciissPartial response: '%s'iis N( RcRtreadRRtappendtOSErrorterrnotEAGAIN(R;Rtmsgtbytetexc((RsG/usr/lib/python2.7/site-packages/cloudinit/sources/DataSourceSmartOS.pyt _readlines  cCs*|jj|jd|jjdS(NR(RtwriteRtflush(R;R((sG/usr/lib/python2.7/site-packages/cloudinit/sources/DataSourceSmartOS.pyt_writescCsftjd|jd|j}tjd||dkrUtd|ntjddS(NsNegotiating protocol V2s NEGOTIATE V2 s read "%s"tV2_OKs'Invalid response "%s" to "NEGOTIATE V2"sNegotiation complete(RHRIRRR(R;R((sG/usr/lib/python2.7/site-packages/cloudinit/sources/DataSourceSmartOS.pyt _negotiates    c Csdjtjdd}dj||f}|r\|dtj|jj7}ndjt||j ||}t j d|t }|j s|jt}n|j||j}|r|jnt j d|d|krdS|j||}|S( Ns{0:08x}iIt sV2 {0} {1} {2} s#Writing "%s" to metadata transport.s"Read "%s" from metadata transport.tSUCCESS(RtrandomtrandintR6tbase64t b64encodeRRRRRHRIRYRRZRcRRR`R.R( R;trtypetparamRt message_bodyRt need_closeRR((sG/usr/lib/python2.7/site-packages/cloudinit/sources/DataSourceSmartOS.pytrequests(&       cCsG|jddd|}|dkr(|S|rC|rC|j}n|S(NRtGETR(RR.RO(R;tkeytdefaultROtresult((sG/usr/lib/python2.7/site-packages/cloudinit/sources/DataSourceSmartOS.pyR]s   cCs2|j|d|}|dkr%|Stj|S(NR(R]R.tjsontloads(R;RRR((sG/usr/lib/python2.7/site-packages/cloudinit/sources/DataSourceSmartOS.pyR_s cCs)|jdd}|sgS|jdS(NRtKEYSs (Rtsplit(R;R((sG/usr/lib/python2.7/site-packages/cloudinit/sources/DataSourceSmartOS.pytlistscCsSdjg||fD]}tj|j^qj}|jddd|S(NRRtPUTR(R6RRRRR(R;RtvaltiR((sG/usr/lib/python2.7/site-packages/cloudinit/sources/DataSourceSmartOS.pytputs 4cCs|jddd|S(NRtDELETER(R(R;R((sG/usr/lib/python2.7/site-packages/cloudinit/sources/DataSourceSmartOS.pytdeletescCs&|jr"|jjd|_ndS(N(RtcloseR.(R;((sG/usr/lib/python2.7/site-packages/cloudinit/sources/DataSourceSmartOS.pyR`s  cCs|jr |S|j|S(N(RRZ(R;((sG/usr/lib/python2.7/site-packages/cloudinit/sources/DataSourceSmartOS.pyt __enter__s  cCs|jdS(N(R`(R;texc_typet exc_valuet traceback((sG/usr/lib/python2.7/site-packages/cloudinit/sources/DataSourceSmartOS.pyt__exit__s cCs tdS(N(tNotImplementedError(R;((sG/usr/lib/python2.7/site-packages/cloudinit/sources/DataSourceSmartOS.pyRZsN(R|R}t__doc__tretcompileRR.R'RRRRRRRYR]R_RRRR`RRRZ(((sG/usr/lib/python2.7/site-packages/cloudinit/sources/DataSourceSmartOS.pyR[s&             tJoyentMetadataSocketClientcBs/eZedZdZdZdZRS(cCs#tt|j|||_dS(N(tsuperRR't socketpath(R;RRA((sG/usr/lib/python2.7/site-packages/cloudinit/sources/DataSourceSmartOS.pyR'scCsHtjtjtj}|j|j|jd|_|jdS(Ntrwb(tsockettAF_UNIXt SOCK_STREAMtconnectRtmakefileRR(R;tsock((sG/usr/lib/python2.7/site-packages/cloudinit/sources/DataSourceSmartOS.pyRZscCstjj|jS(N(R4R5RJR(R;((sG/usr/lib/python2.7/site-packages/cloudinit/sources/DataSourceSmartOS.pyRJscCsd|jj|jfS(Ns%s(socketpath=%s)(t __class__R|R(R;((sG/usr/lib/python2.7/site-packages/cloudinit/sources/DataSourceSmartOS.pyt__repr__s(R|R}tSMARTOS_ENV_LX_BRANDR'RZRJR(((sG/usr/lib/python2.7/site-packages/cloudinit/sources/DataSourceSmartOS.pyRs   tJoyentMetadataSerialClientcBs>eZdeddZdZdZdZdZRS(i cCs/tt|j||||_||_dS(N(RRR'R ttimeout(R;R RRAR((sG/usr/lib/python2.7/site-packages/cloudinit/sources/DataSourceSmartOS.pyR' s cCstjj|jS(N(R4R5RJR (R;((sG/usr/lib/python2.7/site-packages/cloudinit/sources/DataSourceSmartOS.pyRJscCs|jdkrktj|jd|j}|jsLtd|jn||_tj |tj n|j |j dS(NRsUnable to open %s( RR.RtSerialR RtisOpent SystemErrortfcntltlockftLOCK_EXt_flushR(R;tser((sG/usr/lib/python2.7/site-packages/cloudinit/sources/DataSourceSmartOS.pyRZs   cCs=tjd|jj}d|j_x-trTy|jWq(tk rPPq(Xq(Wtjd|dkr}d|j_n ||j_xtrtjd|jdyO|j}|dkrPn|dkrtjd wntjd |Wqtk rtjd qXqWtjd ||j_dS( NsFlushing inputg?s Input emptyis,Writing newline, expecting "invalid command"s sinvalid commandtFAILUREsGot "FAILURE". Retrying.s%Unexpected response "%s" during flushsQTimeout while initializing metadata client. Is the host metadata service running?s'Got "invalid command". Flush complete.( RHRIRRRcRRRtwarning(R;RR((sG/usr/lib/python2.7/site-packages/cloudinit/sources/DataSourceSmartOS.pyR s6                  cCsd|jj|j|jfS(Ns%s(device=%s, timeout=%s)(RR|R R(R;((sG/usr/lib/python2.7/site-packages/cloudinit/sources/DataSourceSmartOS.pyREsN( R|R}RvR.R'RJRZRR(((sG/usr/lib/python2.7/site-packages/cloudinit/sources/DataSourceSmartOS.pyR s    %t JoyentMetadataLegacySerialClientcBsSeZdZdddZedZdedZedZdedZ RS(sV1 of the protocol was not safe for all values. Thus, we allowed the user to pass values in as base64 encoded. Users may still reasonably expect to be able to send base64 data and have it transparently decoded. So even though the V2 format is now used, and is safe (using base64 itself), we keep legacy support. The way for a user to do this was: a.) specify 'base64_keys' key whose value is a comma delimited list of keys that were base64 encoded. b.) base64_all: string interpreted as a boolean that indicates if all keys are base64 encoded. c.) set a key named b64- with a boolean indicating that is base64 encoded.i cCs8tt|}|j|||d|_d|_dS(N(RRR'R.RR(R;R RRAts((sG/usr/lib/python2.7/site-packages/cloudinit/sources/DataSourceSmartOS.pyR'Ys cCsj|rd|_d|_nd}|jdkrr|j}d|krftj|jd|_qrt|_n|jrdS|jdkrf|dkr|j}nt}d|krt|jdj d}nxxg|D]}|j dr|d^qD]J}tj|j|r:|j |q ||kr |j |q q W||_ndS(NRRt,sb64-i( R.RRRRtis_truet_getRYtsetRt startswithR2tremove(R;tresettkeystb64_keystkR((sG/usr/lib/python2.7/site-packages/cloudinit/sources/DataSourceSmartOS.pyt_init_base64_keys_s.         !3 cCs"tt|j|d|d|S(NRRO(RRR](R;RRRO((sG/usr/lib/python2.7/site-packages/cloudinit/sources/DataSourceSmartOS.pyRscCs:|tkrtS|jd||jr-tS||jkS(NR(tNO_BASE64_DECODERYRRRcR(R;RR((sG/usr/lib/python2.7/site-packages/cloudinit/sources/DataSourceSmartOS.pytis_b64_encodeds   cCst}|j|dtd|}||kr4|S|j|rytj|jj}Wqtt j fk rt j d||qXn|r|j }n|S(NRORs#Failed base64 decoding key '%s': %s(tobjectRRYRRt b64decodeRRt TypeErrorRtErrorRHRRO(R;RRROtmdefaultR((sG/usr/lib/python2.7/site-packages/cloudinit/sources/DataSourceSmartOS.pyR]s  N( R|R}RR.R'RYRRRR](((sG/usr/lib/python2.7/site-packages/cloudinit/sources/DataSourceSmartOS.pyRJs   " cCs|dkrt|}n|dkr+dS|tkrPtd|d|d|S|tkrotd|d|Std|dS(NR RRARs"Unknown value for smartos_type: %s(R.RCRvRRRt ValueError(RARRRt uname_version((sG/usr/lib/python2.7/site-packages/cloudinit/sources/DataSourceSmartOS.pyRDs      cCsddd|g}d}y,tj|\}}tjd||Wn0tjk rv}tjtd||fnX|dkrdS|jS(Ntfiles--briefs --mime-typesscript %s mime type is %ss%Failed to identify script type for %s(R.RtsubpRHRItProcessExecutionErrortlogexcRO(RRtcmdtf_typet_errte((sG/usr/lib/python2.7/site-packages/cloudinit/sources/DataSourceSmartOS.pyt identify_filesicCsz| r)tjj|r)tj|n|rQtjj|rQtj|n|s[dStj||d||r|jd rt|}|dkrtj|dj d|gd|t j d|qn|rvyjtjj|rtj|n|rItjj|rItj tjj |tj||nWqvtk rr}tjt d|qvXndS( s  Write the content to content_f. Under the following rules: 1. If no content, remove the file 2. Write the content 3. If executable and no file magic, add it 4. If there is a link, create it @param content: what to write @param content_f: the file name @param backup_d: the directory to save the backup at @param link: if defined, location to create a symlink to @param shebang: if no file magic, set shebang @param mode: file mode Becuase of the way that Cloud-init executes scripts (no shell), a script will fail to execute if does not have a magic bit (shebang) set for the file. If shebang=True, then the script will be checked for a magic bit and to the SmartOS default of assuming that bash. NRUs#!s text/plains s #!/bin/bashsadded shebang to file %ss$failed establishing content link: %s(R4R5RJtunlinktislinkRt write_fileRRR6RHRIt ensure_dirtdirnametsymlinktIOErrorR(tcontentRRRSRTRURR((sG/usr/lib/python2.7/site-packages/cloudinit/sources/DataSourceSmartOS.pyRbs,  cCsvtj}|dkr%|d}n|dkr5tS|dkrStjd}n|}|rr|jdrrtSdS(NisBrandZ virtual linuxssystem-product-nametSmartDC(R4tunameR.RRt read_dmi_dataRRv(Rt product_nameRt system_type((sG/usr/lib/python2.7/site-packages/cloudinit/sources/DataSourceSmartOS.pyRCs     c siddddddgd6dd d d d d dddg d6ddgd6|rxt|ttfs~|g}q~ng}|rt|ttfs|g}qng}|sg}nd}d}ii|d6d,d6d6i|d6d,d6d6}g}xR|D]J}tfd|jD} | jidd6|dd6d|krz| ji|dd6ng} x|jdgD]} | dkridd6} nog} tfd |jD} | jid!d6| d6|| r dnd}d"|kr|jd"tr||dsg|jd#gD] }||d|rO|^qO}t |r|d$||d<| ji||dd6qqnxi|D]a}tfd%|jD}|ji|d&d6| j || ji| d6qW| j | qW| ji| d6|j | q W|r|j id'd6|d6|d(6nid)d*6|d+6S(-sReturn a dictionary of network_config by parsing provided SMARTOS sdc:nics configuration data sdc:nics data is a dictionary of properties of a nic and the ip configuration desired. Additional nic dictionaries are appended to the list. Converting the format is straightforward though it does include duplicate information as well as data which appears to be relevant to the hostOS rather than the guest. For each entry in the nics list returned from query sdc:nics, we create a type: physical entry, and extract the interface properties: 'mac' -> 'mac_address', 'mtu', 'interface' -> 'name'. The remaining keys are related to ip configuration. For each ip in the 'ips' list we create a subnet entry under 'subnets' pairing the ip to a one in the 'gateways' list. Each route in sdc:routes is mapped to a route on each interface. The sdc:routes properties 'dst' and 'gateway' map to 'network' and 'gateway'. The 'linklocal' sdc:routes property is ignored. t mac_addresstmtuRttparamstsubnetsttypetphysicaltaddresst broadcasttdns_nameserverst dns_searchtmetrict pointopointR tscopetsubnetR$tgatewaytroutecSs d|kS(Nt.((taddr((sG/usr/lib/python2.7/site-packages/cloudinit/sources/DataSourceSmartOS.pyt is_valid_ipv4MscSs d|kS(Nt:((R&((sG/usr/lib/python2.7/site-packages/cloudinit/sources/DataSourceSmartOS.pyt is_valid_ipv6PsRtgwtipv4tipv6c3s1|]'\}}|dkr||fVqdS(RN((t.0Rtv(t valid_keys(sG/usr/lib/python2.7/site-packages/cloudinit/sources/DataSourceSmartOS.pys Zs t interfacetmactipstdhcptdhcp4c3s1|]'\}}|dkr||fVqdS(R"N((R-RR.(R/(sG/usr/lib/python2.7/site-packages/cloudinit/sources/DataSourceSmartOS.pys hs tstatictprimarytgatewaysic3s1|]'\}}|dkr||fVqdS(R$N((R-RR.(R/(sG/usr/lib/python2.7/site-packages/cloudinit/sources/DataSourceSmartOS.pys ~s tdstt nameservertsearchitversiontconfigN( t isinstanceRttupleR.tdictR\tupdateR]RYRR(R/R R R R'R)tpgwsR<tnictcfgRtipR"t routeentstprotoR*R7R$trcfg((R/sG/usr/lib/python2.7/site-packages/cloudinit/sources/DataSourceSmartOS.pyRz s       "   "    % " cCstj|tS(N(Rtlist_from_dependst datasources(tdepends((sG/usr/lib/python2.7/site-packages/cloudinit/sources/DataSourceSmartOS.pytget_datasource_listst__main__sDo not appear to be on smartos.iR{c Cs||kr||S|tkr@t|}|j|||s                          (>Y   0      ,