3 \me@sUddlZddlZddlZddlZddlZddlZddlZddlZddlZddl Z ddl Z ddl m Z m Z mZmZmZddlmZmZejeZdOdPdQdRdSdTdUdVdWdXdYdZd[d ZddddZdZdZdZdegZd d ddddgZdZdZdZ ee eegd d d!id"Z!d d#d d d$id d%d d&gd'Z"d(Z#d)Z$Gd*d+d+ej%Z&Gd,d-d-e'Z(Gd.d/d/e(Z)Gd0d1d1Z*Gd2d3d3e*Z+Gd4d5d5e*Z,Gd6d7d7e,Z-deee dfd8d9Z.d:d;Z/d\d=d>Z0d]d?d@Z1d^dAdBZ2e&ej3ffgZ4dCdDZ5edEkrddl6Z6e.Z7e7dkr e8dFe6j9dGe:e6j;dGkrPeiZ?e@?xe=D]ZAe>e7eAe?dKqtWe8ejBe?dGdd_dNdS)`N) atomic_helperdmisourcessubputil) EventScope EventTypesdc:uuidThostnameroot_authorized_keys user-scriptF user-datacloud-init:user-dataiptables_disable motd_sys_infosdc:datacenter_namesdc:vendor-datasdc:operator-script sdc:hostnamesdc:dns_domain) z instance-idzlocal-hostnamez public-keysz user-scriptzlegacy-user-dataz user-datarrZavailability_zonez vendor-datazoperator-scriptr dns_domainzsdc:nicsz sdc:resolversz sdc:routes)z network-data dns_serversrouteszlx-brandZkvmZSmartOSZ datasourcezsdc:uuiduser-dataz"/native/.zonecontrol/metadata.sockz /dev/ttyS1<Z ephemeral0z/dev/vdb) serial_deviceserial_timeoutmetadata_sockfileZno_base64_decode base64_keys base64_all disk_aliasesZmbr)Z table_typeZlayoutZ overwriteZext4)ZlabelZ filesystemdevice)Z disk_setupZfs_setupaU#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" z/var/dbc@seZdZdZejZejZej e j e j e j hiZddZddZddZdd Zd d Zd d ZddZddZddZeddZdS)DataSourceSmartOSZJoyentcCsdtjj||||tj|jtj|titg|_i|_ d|_ d|_ t j j|jjd|_|jdS)Nscripts)r DataSource__init__r mergemanydictds_cfgZget_cfg_by_path DS_CFG_PATHBUILTIN_DS_CONFIGmetadata network_data_network_configospathjoinpaths get_cpathZ script_base_d_init)selfZsys_cfgZdistror/r3'/usr/lib/python3.6/DataSourceSmartOS.pyr$s  zDataSourceSmartOS.__init__cCstjj|}d||jfS)Nz%s [client=%s])rr#__str__ md_client)r2rootr3r3r4r5s zDataSourceSmartOS.__str__cCsZ|jtjkr$t|_|jdkr$d|_|jtjkrVt|j|jd|jd|jdd|_dS)Nrrr) smartos_typerrr)r8rUNSETget_smartos_environr6jmc_client_factoryr&)r2r3r3r4r1s   zDataSourceSmartOS._initcCsHtjdd}tjjdj|dgrDtjdj|dgdj|dgdS)aMark 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. z-Instance provisioning state set as successfulz/var/svc/Z provisioningZprovision_successN)LOGdebugr,r-existsr.rename)r2Zsvc_pathr3r3r4_set_provisioneds  z"DataSourceSmartOS._set_provisionedc Cs|ji}d}|js$tjddS|jjs@tjd|jdS|jjx0tjD]$\}}|\}}|jj ||d||<qTWx$t jD]\}}|jj |||<qW|jj t jj|jjd|dd}t jj|d }d t} t|j d || d d d t jj|d} t|j d| dd d|j d} dt} t| | |dsd|drX|d|d<n |d|d<d}|drz|d}|dst|| t jj|jjddd|d<tj||jg|_||_|d|_|d|_|d|_|jd S)NzNot running on smartosFz4No metadata device '%r' found for SmartOS datasource)stripZ instancesz instance-iddataz user-scriptz%s/user-scriptTi) content_flinkshebangmodezoperator-script)rErGrHzlegacy-user-dataz%s/mdata-user-datazlocal-hostnamer z user-dataz vendor-datar"zper-boot) user_scriptoperator_scriptZ per_boot_dz network-datar)r1r8r=r>r6r?open_transportSMARTOS_ATTRIB_MAPitemsgetSMARTOS_ATTRIB_JSONget_jsonclose_transportr,r-r.r/r0 LEGACY_USER_Dwrite_boot_contentBUILTIN_VENDOR_DATArr%r)Z userdata_rawZvendordata_rawr* routes_datarA) r2ZmdZudZci_nounZ attributeZ smartos_nounrCZdata_drIZ u_script_lrJZu_dataZu_data_fr3r3r4 _get_datasr              zDataSourceSmartOS._get_datacCsdtS)Nz serial (%s)) SERIAL_DEVICE)r2r3r3r4_get_subplatformMsz"DataSourceSmartOS._get_subplatformcCs|jdj|S)Nr)r&rN)r2namer3r3r4device_name_to_devicePsz'DataSourceSmartOS.device_name_to_devicecCs|jtkrtSiS)N)r8SMARTOS_ENV_KVMBUILTIN_CLOUD_CONFIG)r2r3r3r4get_config_objSs z DataSourceSmartOS.get_config_objcCs |jdS)Nz instance-id)r))r2r3r3r4get_instance_idXsz!DataSourceSmartOS.get_instance_idcCsN|jtjkrd|_|jdkrH|jdk rHt|j|jd|jd|jd|_|jS)Nrr)r*rrr)r+rr9r*convert_smartos_network_datar)rU)r2r3r3r4network_config[s    z DataSourceSmartOS.network_configN)__name__ __module__ __qualname__Zdsnamerr9r8r6rZNETWORKrZBOOT_NEW_INSTANCEZBOOTZ BOOT_LEGACYZdefault_update_eventsr$r5r1rArVrXrZr]r^propertyr`r3r3r3r4r!s" cr!c@s eZdZdS)JoyentMetadataFetchExceptionN)rarbrcr3r3r3r4relsrec@s eZdZdS)JoyentMetadataTimeoutExceptionN)rarbrcr3r3r3r4rfpsrfc@seZdZdZejdZd#ddZddZdd Z d d Z d d Z ddZ d$ddZ d%ddZd&ddZddZddZddZddZdd Zd!d"ZdS)'JoyentMetadataClientz A client implementing v2 of the Joyent Metadata Protocol Specification. The full specification can be found at http://eng.joyent.com/mdata/protocol.html z~V2 (?P\d+) (?P[0-9a-f]+) (?P(?P[0-9a-f]+) (?PSUCCESS|NOTFOUND)( (?P.+))?)NcCs|dkrt}||_||_dS)N)r:r8fp)r2r8rhr3r3r4r$szJoyentMetadataClient.__init__cCsdjtj|jdd@S)Nz{0:08x}zutf-8l)formatbinasciiZcrc32encode)r2bodyr3r3r4 _checksumszJoyentMetadataClient._checksumcCs|jj|j}t|dt|dkrDtdj|dt|d|j|d}|d|krrtdj||d|d|krtdj||d|jddst j d dSt j |d}t j d ||S) NZlengthrlz*Incorrect frame length given ({0} != {1}).Zchecksumz*Invalid checksum (expected: {0}; got {1}). request_idz-Request ID mismatch (expected: {0}; got {1}).ZpayloadzNo value found.zValue "%s" found.) line_regexmatch groupdictintlenrerirmrNr=r>rZb64d)r2Zexpected_request_idframeZ frame_dataZexpected_checksumvaluer3r3r4_get_value_from_frames(     z*JoyentMetadataClient._get_value_from_framecsgfdd}d}xyB|jjd}t|dkr>t|||dkrL|Sj|Wqtk r}z$|jtjkrt|||WYdd}~XqXqWdS)z 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)Nascii)r.decoder3)responser3r4as_asciisz0JoyentMetadataClient._readline..as_asciizPartial response: '%s'r N)rhreadrsrfappendOSErrorerrnoZEAGAIN)r2r{msgZbyteexcr3)rzr4 _readlines"     zJoyentMetadataClient._readlinecCs |jj|jd|jjdS)Nrx)rhwriterkflush)r2rr3r3r4_writeszJoyentMetadataClient._writecCsJtjd|jd|j}tjd||dkrrrre)r2rzr3r3r4 _negotiates    zJoyentMetadataClient._negotiatec Csdjtjdd}dj||f}|r>|dtj|jj7}djt||j ||}t j d|d}|j sx|j d}|j||j}|r|jt j d |d |krdS|j||}|S) Nz{0:08x}rl zV2 {0} {1} {2} z#Writing "%s" to metadata transport.FTz"Read "%s" from metadata transport.SUCCESS)rirandomZrandintr.base64 b64encoderkryrsrmr=r>rhrKrrrQrv) r2rtypeparamrnZ message_bodyrZ need_closerzrur3r3r4requests,    zJoyentMetadataClient.requestFcCs.|jd|d}|dkr|S|r*|r*|j}|S)NZGET)rr)rrC)r2keydefaultrCresultr3r3r4rNs zJoyentMetadataClient.getcCs$|j||d}|dkr|Stj|S)N)r)rNjsonloads)r2rrrr3r3r4rPszJoyentMetadataClient.get_jsoncCs|jdd}|sgS|jdS)NZKEYS)r )rsplit)r2rr3r3r4lists zJoyentMetadataClient.listcCs*djdd||fDj}|jd|dS)N cSsg|]}tj|jqSr3)rrrk).0ir3r3r4 sz,JoyentMetadataClient.put..ZPUT)rr)r.ryr)r2rvalrr3r3r4put szJoyentMetadataClient.putcCs|jr|jjd|_dS)N)rhclose)r2r3r3r4rQs z$JoyentMetadataClient.close_transportcCs|jr |S|j|S)N)rhrK)r2r3r3r4 __enter__szJoyentMetadataClient.__enter__cCs |jdS)N)rQ)r2exc_type exc_value tracebackr3r3r4__exit__szJoyentMetadataClient.__exit__cCstdS)N)NotImplementedError)r2r3r3r4rKsz#JoyentMetadataClient.open_transport)NN)N)NF)N)rarbrc__doc__recompileror$rmrvrrrrrNrPrrrQrrrKr3r3r3r4rgts$  !  rgcs8eZdZeffdd ZddZddZddZZS) JoyentMetadataSocketClientcstt|j|||_dS)N)superrr$ socketpath)r2rr8) __class__r3r4r$$sz#JoyentMetadataSocketClient.__init__cCs4tjtjtj}|j|j|jd|_|jdS)NZrwb)socketZAF_UNIXZ SOCK_STREAMZconnectrmakefilerhr)r2Zsockr3r3r4rK(s  z)JoyentMetadataSocketClient.open_transportcCstjj|jS)N)r,r-r?r)r2r3r3r4r?.sz!JoyentMetadataSocketClient.existscCsd|jj|jfS)Nz%s(socketpath=%s))rrar)r2r3r3r4__repr__1sz#JoyentMetadataSocketClient.__repr__) rarbrcSMARTOS_ENV_LX_BRANDr$rKr?r __classcell__r3r3)rr4r#srcsDeZdZdedffdd ZddZddZd d Zd d ZZ S) JoyentMetadataSerialClient Ncs"tt|j||||_||_dS)N)rrr$r timeout)r2r rr8rh)rr3r4r$6sz#JoyentMetadataSerialClient.__init__cCstjj|jS)N)r,r-r?r )r2r3r3r4r?=sz!JoyentMetadataSerialClient.existscCsZ|jdkrFtj|j|jd}|js2td|j||_tj|tj |j |j dS)N)rzUnable to open %s) rhserialZSerialr rZisOpen SystemErrorfcntllockfZLOCK_EX_flushr)r2Zserr3r3r4rK@s z)JoyentMetadataSerialClient.open_transportc Cstjd|jj}d|j_x(y |jWqtk r>PYqXqWtjd|dkr`d|j_n||j_xntjd|jdy6|j}|dkrP|dkrtjd wjtjd |Wqjtk rtjd YqjXqjWtjd ||j_dS) NzFlushing inputg?z Input emptyz,Writing newline, expecting "invalid command"rzinvalid commandFAILUREzGot "FAILURE". Retrying.z%Unexpected response "%s" during flushzQTimeout while initializing metadata client. Is the host metadata service running?z'Got "invalid command". Flush complete.)r=r>rhrrrfrwarning)r2rrzr3r3r4rJs8         z!JoyentMetadataSerialClient._flushcCsd|jj|j|jfS)Nz%s(device=%s, timeout=%s))rrar r)r2r3r3r4rqsz#JoyentMetadataSerialClient.__repr__) rarbrcr[r$r?rKrrrr3r3)rr4r5s  'rcsNeZdZdZdfdd ZdddZdfd d Zdd d Zdd dZZ S) JoyentMetadataLegacySerialClientaV1 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.rNcs(tt|}|j|||d|_d|_dS)N)rrr$rr)r2r rr8s)rr3r4r$s z)JoyentMetadataLegacySerialClient.__init__FcCs|rd|_d|_d}|jdkrH|j}d|krBtj|jd|_nd|_|jrRdS|jdkr|dkrl|j}t}d|krt|jdjd}xDdd|DD]2}tj|j|r|j|q||kr|j |qW||_dS)NrFr,cSs"g|]}|jdr|ddqS)zb64-N) startswith)rkr3r3r4rszFJoyentMetadataLegacySerialClient._init_base64_keys..) rrrrZis_true_getsetraddremove)r2resetkeysZb64_keysrr3r3r4_init_base64_keyss.   z2JoyentMetadataLegacySerialClient._init_base64_keyscstt|j|||dS)N)rrC)rrrN)r2rrrC)rr3r4rs z%JoyentMetadataLegacySerialClient._getcCs,|tkr dS|j|d|jr"dS||jkS)NF)rT)NO_BASE64_DECODErrr)r2rrr3r3r4is_b64_encodeds  z/JoyentMetadataLegacySerialClient.is_b64_encodedc Csxt}|j|d|d}||kr"|S|j|rhytj|jj}Wn$tjk rft j d||YnX|rt|j }|S)NF)rCrz#Failed base64 decoding key '%s': %s) objectrrrZ b64decoderkryrjErrorr=rrC)r2rrrCZmdefaultrr3r3r4rNs z$JoyentMetadataLegacySerialClient.get)rN)F)NF)F)NF) rarbrcrr$rrrrNrr3r3)rr4rys   " rcCsV|dkrt|}|dkrdS|tkr2t|||dS|tkrFt||dStd|dS)N)r rr8)rr8z"Unknown value for smartos_type: %s)r:r[rrr ValueError)r8rrr uname_versionr3r3r4r;s r;cCs~ddd|g}d}y tj|\}}tjd||Wn8tjk rh}ztjtd||fWYdd}~XnX|dkrvdS|jS)Nfilez--briefz --mime-typezscript %s mime type is %sz%Failed to identify script type for %s)rr=r>ZProcessExecutionErrorrlogexcrC)rEcmdf_typeZ_errer3r3r4 identify_files "rcCs| rtjj|rtj||r6tjj|r6tj||s>dStj|||d|r|jd rt|}|dkrtj|dj d|g|dt j d||ryHtjj|rtj||rtjj|rtj tjj |tj||Wn2tk r}ztjt d|WYdd}~XnXdS) a  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. N)rHz#!z text/plainrz #!/bin/bashzadded shebang to file %sz$failed establishing content link: %s)r,r-r?unlinkislinkrZ write_filerrr.r=r>Z ensure_dirdirnamesymlinkIOErrorr)ZcontentrErFrGrHrrr3r3r4rSs,     rScCsRtj}|dkr|d}|dkr$tS|dkr8tjd}n|}|rN|jdrNtSdS)NrzBrandZ virtual linuxzsystem-product-nameZSmartDC)r,unamerrZ read_dmi_datarr[)rZ product_namerZ system_typer3r3r4r:,s r:c svddddddgddd d d d d ddg ddgd|rHt|ttfsL|g}ng}|rft|ttfsj|g}ng}|srg}dd}dd}|dd|dddg}x|D]}tfdd|jD}|jd|ddd|kr|jd|dig} x>|jdgD],} | d kr"dd!i} ng} tfd"d|jD} | jd#| d$|| r^d%nd&d'|kr|jd'd(rԈd)sԇfd*d+|jd,gD} t| r| d-d)<| jdd)ixR|D]J}tfd.d|jD}|jd|d/i| j|| jd | iqW| j| qW|jd| i|j|qW|rl|jd0||d1d2|d3S)4aReturn 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. Z mac_addressZmturYZparamssubnetstypeaddressZ broadcastZdns_nameserversZ dns_searchZmetricZ pointopointrZscopeZnetworkZgateway)physicalsubnetroutecSsd|kS)N.r3)addrr3r3r4 is_valid_ipv4sz3convert_smartos_network_data..is_valid_ipv4cSsd|kS)N:r3)rr3r3r4 is_valid_ipv6sz3convert_smartos_network_data..is_valid_ipv6N)rpgw)ipv4ipv6c3s&|]\}}|dkr||fVqdS)rNr3)rrv) valid_keysr3r4 sz/convert_smartos_network_data..rZ interface)rrYZmacZipsZdhcpZdhcp4c3s&|]\}}|dkr||fVqdS)rNr3)rrr)rr3r4rsZstatic)rrrrZprimaryFrcs g|]}d|r|qS)rpr3)rr)pgwsprotor3r4rsz0convert_smartos_network_data..gatewaysrc3s&|]\}}|dkr||fVqdS)rNr3)rrr)rr3r4rsdstZ nameserver)rrsearchr|)versionconfig) isinstancertupledictrMupdaterNrsr)r*rrrrrrZnicZcfgrZiprZ routeentsrrZrcfgr3)rrrr4r_Bs          r_cCs tj|tS)N)rZlist_from_depends datasources)Zdependsr3r3r4get_datasource_listsr__main__zDo not appear to be on smartos.r|r`cCs||kr||S|tkr0t|}|j|||<nz|dkrxxd D]}t|||q>Wt|d|d|d|dd||<n2|tkrt|\}}n |d}}|j||d||<||S) Nr` network-datarrr)r*rrrF)rC)rrrr)rOrPload_keyr_rLrN)clientrrDZkeynameZdepkeyrCr3r3r4rs, r)rrrDr: )indentZ sort_keysZ separators)r T)r T)r T)r F)r F)rF)rT)rT)rT)rF)rF)rT)rT)NFr)NN)NNNN)rr)CrrjrrrZloggingr,rrrrZ cloudinitrrrrrZcloudinit.eventrrZ getLoggerrar=rLrOrr[ZDS_NAMEr'rZMETADATA_SOCKFILErWZSERIAL_TIMEOUTr(r\rTrRr#r! Exceptionrerfrgrrrr;rrSr:r_ZDEP_FILESYSTEMrrsysZjmcprintexitrsargvrrrrDrrdumpsr3r3r3r4s  )G0DY  2