<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Chmouel&#039;s Blog &#187; Openstack</title>
	<atom:link href="http://blog.chmouel.com/category/openstack/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.chmouel.com</link>
	<description>Random and probably boring stuff.</description>
	<lastBuildDate>Thu, 02 May 2013 08:19:11 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.5.1</generator>
<atom:link rel="hub" href="http://pubsubhubbub.appspot.com"/><atom:link rel="hub" href="http://superfeedr.com/hubbub"/>		<item>
		<title>Keystone and PKI tokens overview</title>
		<link>http://blog.chmouel.com/2013/05/02/keystone-pki-tokens-overview/</link>
		<comments>http://blog.chmouel.com/2013/05/02/keystone-pki-tokens-overview/#comments</comments>
		<pubDate>Thu, 02 May 2013 08:00:15 +0000</pubDate>
		<dc:creator>chmouel</dc:creator>
				<category><![CDATA[Keystone]]></category>
		<category><![CDATA[Openstack]]></category>

		<guid isPermaLink="false">http://blog.chmouel.com/?p=651</guid>
		<description><![CDATA[PKI tokens has been implemented in keystone by Adam Young and others and was shipped for the OpenStack grizlly release. It is available since the version 2.0 API of keystone. PKI is a beautiful acronym to Public-key infrastructure which according to wikipedia defines it like this : Public-key cryptography is a cryptographic technique that enables [...]]]></description>
				<content:encoded><![CDATA[<p>PKI tokens has been implemented in keystone by <a href="http://adam.younglogic.com/">Adam Young</a> and others and was shipped for the OpenStack grizlly release. It is available since the version 2.0 API of keystone.</p>
<p>PKI is a beautiful acronym to <a href="http://en.wikipedia.org/wiki/Public-key_infrastructure">Public-key infrastructure</a> which according to wikipedia defines it like this :</p>
<blockquote><p>Public-key cryptography is a cryptographic technique that enables users to securely communicate on an insecure public network, and reliably verify the identity of a user via digital signatures.</p></blockquote>
<p>As described more lengthy on this IBM <a href="https://www.ibm.com/developerworks/community/blogs/e93514d3-c4f0-4aa0-8844-497f370090f5/entry/openstack_keystone_workflow_token_scoping?lang%3Den">blog post</a> keystone will start to generate a public and a private key and store it locally.</p>
<p>When getting the first request the service (i.e: <a href="http://github.com/openstack/swift">Swift</a>) will go get the public certificate from keystone and store it locally for later use.</p>
<p>When the user is authenticated and a PKI token needs to be generated, keystone will take the private key and encrypt the token and the metadata (i.e: roles, endpoints, services).</p>
<p>The service by the mean of the auth_token middleware will decrypt the token with the public key and get the info to pass on to the service it set the *keystone.identity* WSGI environement variable to be used by the other middleware of the service in the paste pipeline.</p>
<p>The PKI tokens are then much more secure since the service can trust where the token is coming from and much more efficient since it doesn&#8217;t have to validate it on every request like done for UUID token.</p>
<h2>Auth token</h2>
<p>This bring us to the auth_token middleware. The auth token middleware is a central piece of software of keystone to provide a generic middleware for other python WSGI services to integrate with keystone.</p>
<p>The auth_token middleware was moved in grizzly to the python-keystoneclient package, this allows us to don&#8217;t have to install a full keystone server package to use it (remember this is supposed to be integrated directly in services).</p>
<p>You usually would add the auth_token middleware in your paste pipeline at the begining of it (there may be other middlewares before like logging, catch_errors and stuff so not quite the first one).</p>
<pre class="example">[filter:authtoken]
signing_dir = /var/cache/service
paste.filter_factory = keystoneclient.middleware.auth_token:filter_factory
auth_host = keystone_host
auth_port = keystone_public_port
auth_protocol = keystone_public_port
auth_uri = http://keystone_host:keystone_admin_port/
admin_tenant_name = service
admin_user = service_user
admin_password = service_password
</pre>
<p>There is much more options to the auth_token middleware, I invite you to refer to your service documentation and read a bit the top of the auth_token file <a href="https://github.com/openstack/python-keystoneclient/blob/master/keystoneclient/middleware/auth_token.py">here</a>.</p>
<p>When the service get a request with a <strong>X-Auth-Token</strong> header containing a PKI token the auth middleware will intercept it and start to do some works.</p>
<p>It will validate the token by first md5/hexdigesting it, this is going to be the key in memcache as you may have seen the PKI token since containing all the metadatas can be very long and are too big to server as is for memcache.</p>
<p>It will check if we have the key in memcache and if not start verify the signed token.</p>
<p>Before everything the token is checked if it was revoked (see my previous article about <a href="http://blog.chmouel.com/2013/04/22/howto-revoke-a-token-with-keystone-and-pki-v2-0-api/">PKI revoked tokens</a>). The way it&#8217;s getting the revoked token is to first check if the token revocation list is expired (by default it will do a refresh for it every seconds).</p>
<p>If it need to be refreshed it will do a request to the url &#8216;<em>/v2.0/tokens/revoked</em>&#8216; with an admin token to the keystone admin interface and get the list of revoked tokens.</p>
<p>The list get stored as well on disk for easy retrieval.</p>
<p>If the token is not revoked it will convert the token to a proper CMS format and start verifying it.</p>
<p>Using the signing cert filename and the ca filename it will invoke the command line openssl CLI to do a cms -verify which will decode the cms token providing the decoded data.  If the cert filename or the ca filename was missing it will fetch it again.</p>
<p>Fetching the signing cert will be done by doing a non authenticated query to the keystone admin url &#8216;<em>/v2.0/certificates/signing</em>&#8216;. Same goes for the ca making a query to the keystone url &#8216;<em>/v2.0/certificates/ca</em>&#8216;.</p>
<p>When we have the decoded data we can now build our environement variable for the other inside the environement variable call keystone.token_info this will be used next by the other services middleware. Bunch of new headers will be added to the request with for example the User Project ID Project Name etc..</p>
<p>The md5/hexdigest PKI token is then stored with the data inside memcache.</p>
<p>And that&#8217;s it, there is much more information on the IBM blog post and on Adam&#8217;s blog I am mentionning earlier.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.chmouel.com/2013/05/02/keystone-pki-tokens-overview/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Howto revoke a token with keystone and PKI (v2.0 API)</title>
		<link>http://blog.chmouel.com/2013/04/22/howto-revoke-a-token-with-keystone-and-pki-v2-0-api/</link>
		<comments>http://blog.chmouel.com/2013/04/22/howto-revoke-a-token-with-keystone-and-pki-v2-0-api/#comments</comments>
		<pubDate>Mon, 22 Apr 2013 22:38:27 +0000</pubDate>
		<dc:creator>chmouel</dc:creator>
				<category><![CDATA[Openstack]]></category>

		<guid isPermaLink="false">http://blog.chmouel.com/?p=618</guid>
		<description><![CDATA[This is something I have been asked and I was at first under impression it was only available in v3, digging a bit more into the code there is actually a way to do that in v2 when you are using PKI tokens. Since I could not find much documentation online here is a description [...]]]></description>
				<content:encoded><![CDATA[<p>This is something I have been asked and I was at first under impression it was only available in v3, digging a bit more into the code there is actually a way to do that in v2 when you are using PKI tokens. Since I could not find much documentation online here is a description of the steps how to do it.</p>
<p>Let first get a PKI token, you can do it the hard way by sending a json blob to the keystone url and parse the json results like this :</p>
<pre>$ curl -s -d '{"auth": {"tenantName": "tenant", "passwordCredentials": {"username": "user", "password": "password"}}}' -H 'Content-type: application/json' http://localhost:5000/v2.0/tokens</pre>
<p>or do the easy way by gettting my script available here :</p>
<p><a href="http://p.chmouel.com/ks">http://p.chmouel.com/ks</a></p>
<p>and use it like that :</p>
<pre>eval $(bash ks -s localhost tenant:user password)</pre>
<p>it will give you a variable $TOKEN and a variable $STORAGE_URL that you can use further down.</p>
<p>now let&#8217;s try to use it with our swift :</p>
<pre>$ curl -i -H "X-Auth-Token: $TOKEN" ${STORAGE_URL}
HTTP/1.1 204 No Content
Content-Length: 0
Accept-Ranges: bytes
X-Timestamp: 1366666887.01151
X-Account-Bytes-Used: 0
X-Account-Container-Count: 0
Content-Type: text/html; charset=UTF-8
X-Account-Object-Count: 0
X-Trans-Id: tx5b50dc6d01d04923a40a1486c13dd94d
Date: Mon, 22 Apr 2013 22:01:00 GMT</pre>
<p>all good here,</p>
<p>so now go inside your keystone.conf and get your admin/service token or use that friendly copy and paste command line :</p>
<pre>$ ADMIN_TOKEN=$(sed -n '/^admin_token/ { s/.*=[ ]*//;p }' /etc/keystone/keystone.conf)</pre>
<p>and use it to DELETE the token we do that request directly to our keystone which is localhost here point it wherever you want:</p>
<pre>$ curl -X DELETE -i -H "X-Auth-Token: $ADMIN_TOKEN" http://localhost:5000/v2.0/tokens/$TOKEN
HTTP/1.1 204 No Content
Vary: X-Auth-Token
Content-Length: 0
Date: Mon, 22 Apr 2013 22:01:08 GMT</pre>
<p>We can still use it because the token is still in the cache. By default tokens are cached in memcache as good as 5 minutes but the<br />
revocation list is fetched every seconds or so.</p>
<pre>$ curl -i -H "X-Auth-Token: $TOKEN" ${STORAGE_URL}
204 No Content
Content-Length: 0
Accept-Ranges: bytes
X-Timestamp: 1366666887.01151
X-Account-Bytes-Used: 0
X-Account-Container-Count: 0
Content-Type: text/html; charset=UTF-8
X-Account-Object-Count: 0
X-Trans-Id: tx9018045ce1324203a91e882ec6d27ac3
Date: Mon, 22 Apr 2013 22:01:12 GMT</pre>
<p>but after a bit (like over a minute or so) we are getting a proper denied:</p>
<pre>$ curl -i -H "X-Auth-Token: $TOKEN" ${STORAGE_URL}
HTTP/1.1 401 Unauthorized
Content-Length: 131
Content-Type: text/html; charset=UTF-8
X-Trans-Id: tx9133daf949204f0facf45152a43836bb
Date: Mon, 22 Apr 2013 22:27:23 GMT

<html>&gt;h1&lt;Unauthorized< <p>This server could not verify that you are authorized to access the document you requested.</html>
</pre>
<p>and from the log messages:</p>
<pre>proxy-server Token 49d94a8ca068013b6efe79e3463627c8 is marked as having been revoked
proxy-server Token validation failure.#012Traceback (most recent call last):#012  File "/opt/stack/python-keystoneclient/keystoneclient/middleware/auth_token.py", line 689, in _validate_user_token#012    verified = self.verify_signed_token(user_token)#012  File "/opt/stack/python-keystoneclient/keystoneclient/middleware/auth_token.py", line 1045, in verify_signed_token#012    raise InvalidUserToken('Token has been revoked')#012InvalidUserToken: Token has been revoked

[..]
proxy-server Marking token MIIGogYJK...... as unauthorized in memcache
</pre>
<p>bingo the token has been now revoked properly.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.chmouel.com/2013/04/22/howto-revoke-a-token-with-keystone-and-pki-v2-0-api/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Upload to OpenStack Swift via CORS/HTML5 request.</title>
		<link>http://blog.chmouel.com/2013/02/01/swift-with-cors-request/</link>
		<comments>http://blog.chmouel.com/2013/02/01/swift-with-cors-request/#comments</comments>
		<pubDate>Fri, 01 Feb 2013 12:06:23 +0000</pubDate>
		<dc:creator>chmouel</dc:creator>
				<category><![CDATA[Openstack]]></category>

		<guid isPermaLink="false">http://blog.chmouel.com/?p=573</guid>
		<description><![CDATA[One of our client at eNovance had a need to be able to upload to Swift directly from a web browser without going via a PHP proxy. Things in browser-land are not exactly the same as what we have in user-land, it is a bit more restricted to ensure the end-user security and there is [...]]]></description>
				<content:encoded><![CDATA[<p>One of our client at <a href="http://enovance.com">eNovance</a> had a need to be able to upload to Swift directly from a web browser without going via a PHP proxy.</p>
<p>Things in browser-land are not exactly the same as what we have in user-land, it is a bit more restricted to ensure the end-user security and there is a few hoops to jump through to get it working.</p>
<p>To be able to do a xmlrpc upload to another server (swift in this case) there is a &#8216;standard/recommendation&#8217; document made by W3C about it located here :</p>
<p><a href="http://www.w3.org/TR/2013/CR-cors-20130129/">http://www.w3.org/TR/2013/CR-cors-20130129/</a></p>
<p>Basically what happen when in Javascript we do :</p>

<div class="wp_codebox"><table><tr id="p5732"><td class="code" id="p573code2"><pre class="javascript" style="font-family:monospace;">request.<span style="color: #000066;">open</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;POST&quot;</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">&quot;http://swift/AUTH_account/container/&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
request.<span style="color: #660066;">setRequestHeader</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'X-Auth-Token'</span><span style="color: #339933;">,</span> myToken<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
request.<span style="color: #660066;">send</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>The browser just before the request will send an OPTIONS request to check with the server if the request is allowed by the server. This look like this when uploading to Swift :</p>
<p style="text-align: center;"><a href="http://blog.chmouel.com/wp-content/uploads/2013/02/Screen-Shot-2013-02-01-at-12.29.50.png"><img class="aligncenter  wp-image-575" alt="Screen Shot 2013-02-01 at 12.29.50" src="http://blog.chmouel.com/wp-content/uploads/2013/02/Screen-Shot-2013-02-01-at-12.29.50.png" width="678" height="459" /></a></p>
<p>The Options request that the browser does is literally asking for the server (swift) to know if this domain where it&#8217;s uploading from is allowed to upload directly via xmlrpc. The request looks like this :</p>
<p style="text-align: left;"><a href="http://blog.chmouel.com/wp-content/uploads/2013/02/Screen-Shot-2013-02-01-at-12.39.50.png"><img class="aligncenter  wp-image-576" alt="Screen Shot 2013-02-01 at 12.39.50" src="http://blog.chmouel.com/wp-content/uploads/2013/02/Screen-Shot-2013-02-01-at-12.39.50.png" width="564" height="340" /></a>It says, hello there: my Origin: is this IP and I want to be able to access with this method &#8216;PUT&#8217;, can I do it ? The server will reply something along (if it&#8217;s allowed), yeah sure please feel free to send this headers along and those methods and Origin are actually what I am allowing.</p>
<p>Thanks to the work of <a href="http://www.17od.com/">Adrian Smith</a> this is supported since Swift version 1.7.5 (and improved in 1.7.6), you can do  at server level config or with headers on container easily see the full detailled documentation here:</p>
<p><a href="http://docs.openstack.org/developer/swift/cors.html">http://docs.openstack.org/developer/swift/cors.html</a></p>
<p>While working on this I could not find a clear example to test it, I only found a great article on this page :</p>
<p><a href="ttp://www.ioncannon.net/programming/1539/direct-browser-uploading-amazon-s3-cors-fileapi-xhr2-and-signed-puts/">http://www.ioncannon.net/programming/1539/direct-browser-uploading-amazon-s3-cors-fileapi-xhr2-and-signed-puts/</a></p>
<p>that was targetted to amazon s3 and I adapted it to use with OpenStack Swift.</p>
<p>You can find it here and use it as an example for your application :</p>
<p><a href="https://github.com/chmouel/cors-swift-example">https://github.com/chmouel/cors-swift-example</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.chmouel.com/2013/02/01/swift-with-cors-request/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>In belgium for Fosdem this weekend.</title>
		<link>http://blog.chmouel.com/2013/01/31/in-belgium-for-fosdem-this-weekend/</link>
		<comments>http://blog.chmouel.com/2013/01/31/in-belgium-for-fosdem-this-weekend/#comments</comments>
		<pubDate>Thu, 31 Jan 2013 22:04:45 +0000</pubDate>
		<dc:creator>chmouel</dc:creator>
				<category><![CDATA[Openstack]]></category>

		<guid isPermaLink="false">http://blog.chmouel.com/?p=571</guid>
		<description><![CDATA[With a team of colleagues from enovance we are going to be this week-end (2/3 Feb 2013) in Brussels for Fosdem. Feel free to catch me if you want to have a chat about Swift or OpenStack in general. I will be wearing a enovance woodie/t-shirt. See you there!]]></description>
				<content:encoded><![CDATA[<p>With a team of colleagues from <a href="http://enovance.com">enovance</a> we are going to be this week-end (2/3 Feb 2013) in Brussels for Fosdem.</p>
<p>Feel free to catch me if you want to have a chat about Swift or OpenStack in general. I will be wearing a enovance woodie/t-shirt.</p>
<p>See you there!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.chmouel.com/2013/01/31/in-belgium-for-fosdem-this-weekend/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Emacs and nosetests</title>
		<link>http://blog.chmouel.com/2012/10/14/emacs-and-nosetests/</link>
		<comments>http://blog.chmouel.com/2012/10/14/emacs-and-nosetests/#comments</comments>
		<pubDate>Sun, 14 Oct 2012 14:19:07 +0000</pubDate>
		<dc:creator>chmouel</dc:creator>
				<category><![CDATA[Emacs]]></category>
		<category><![CDATA[Openstack]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://blog.chmouel.com/?p=549</guid>
		<description><![CDATA[Sometime you just need a long trans atlantic flight and a stupidly long stop-over in a random city to do some of those task that can improve your day to day but you never take some time to do it. When using emacs I wanted a simple way to launch a nosetests on the current function [...]]]></description>
				<content:encoded><![CDATA[<p>Sometime you just need a long trans atlantic flight and a stupidly long stop-over in a random city to do some of those task that can improve your day to day but you never take some time to do it.</p>
<p>When using emacs I wanted a simple way to launch a nosetests on the current function my cursor is in Emacs. The syntax on nosetests is a bit tricky and I actually always have to look at my shell history to know the proper syntax (nosetests directory/filename.py:Class.function).</p>
<p>I created a simple wrapper for emacs for  that which allow to just hit a key to copy the nosetests command to feed to your shell or to use it for the compile buffer.</p>
<p>It&#8217;s available from here :</p>
<p><a href="https://github.com/chmouel/emacs-config/blob/master/modes/nosetests.el">https://github.com/chmouel/emacs-config/blob/master/modes/nosetests.el</a></p>
<p>I have binded those keys for my python mode hook :</p>

<div class="wp_codebox"><table><tr id="p5494"><td class="code" id="p549code4"><pre class="lisp" style="font-family:monospace;"><span style="color: #66cc66;">&#40;</span>local-set-key <span style="color: #66cc66;">&#40;</span>kbd <span style="color: #ff0000;">&quot;C-S-t&quot;</span><span style="color: #66cc66;">&#41;</span> 'nosetests-copy-shell-comand<span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">&#40;</span>local-set-key <span style="color: #66cc66;">&#40;</span>kbd <span style="color: #ff0000;">&quot;C-S-r&quot;</span><span style="color: #66cc66;">&#41;</span> 'nosetests-compile<span style="color: #66cc66;">&#41;</span></pre></td></tr></table></div>

<p>Happy <a href="http://en.wikipedia.org/wiki/Test-driven_development">TDD</a>!!!!</p>
<p><b>UPDATE</b>: There was an another nose mode already that does much more available here : <a href="https://bitbucket.org/durin42/nosemacs/">https://bitbucket.org/durin42/nosemacs/</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.chmouel.com/2012/10/14/emacs-and-nosetests/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Using python-novaclient against Rackspace Cloud next generation (powered by OpenStack)</title>
		<link>http://blog.chmouel.com/2012/08/17/using-python-novaclient-against-rackspace-cloud-next-generation-powered-by-openstack/</link>
		<comments>http://blog.chmouel.com/2012/08/17/using-python-novaclient-against-rackspace-cloud-next-generation-powered-by-openstack/#comments</comments>
		<pubDate>Fri, 17 Aug 2012 10:09:42 +0000</pubDate>
		<dc:creator>chmouel</dc:creator>
				<category><![CDATA[Cloud]]></category>
		<category><![CDATA[Openstack]]></category>

		<guid isPermaLink="false">http://blog.chmouel.com/?p=540</guid>
		<description><![CDATA[With the modular auth plugin system merged into python-novaclient it is now very easy to use nova CLI against the Rackspace Public Cloud powered by OpenStack. we even have a metapackage that would install all the needed bits. This should be easy as doing this : pip install rackspace-novaclient and all dependencies and extensions will [...]]]></description>
				<content:encoded><![CDATA[<p>With the <a href="https://github.com/openstack/python-novaclient/commit/86c713b17ac8984b54ff767d83ab41037e7a7833">modular auth plugin system</a> merged into python-novaclient it is now very easy to use nova CLI against the Rackspace Public Cloud powered by OpenStack.</p>
<p>we even have a metapackage that would install all the needed bits. This should be easy as doing this :</p>
<p style="padding-left: 30px;">pip install rackspace-novaclient</p>
<p>and all dependencies and extensions will be installed. To actually use the CLI you just need to specify the right arguments (or via env variable see nova &#8211;help) like this :</p>
<p style="padding-left: 30px;">nova &#8211;os_auth_system rackspace &#8211;os_username $USER &#8211;os_tenant_name $USER &#8211;os_password $KEY</p>
<p>on RAX cloud, usually the username is the tenant name so this should match.</p>
<p>For the UK Cloud you just need to change the auth_system to rackspace_uk like this :</p>
<p style="padding-left: 30px;">nova &#8211;os_auth_system rackspace_uk &#8211;os_username $USER &#8211;os_tenant_name $USER &#8211;os_password $KEY</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.chmouel.com/2012/08/17/using-python-novaclient-against-rackspace-cloud-next-generation-powered-by-openstack/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>swift.common.client library and swift CLI has moved to its own project</title>
		<link>http://blog.chmouel.com/2012/06/13/swift-common-client-library-and-swift-cli-has-moved-to-its-own-project/</link>
		<comments>http://blog.chmouel.com/2012/06/13/swift-common-client-library-and-swift-cli-has-moved-to-its-own-project/#comments</comments>
		<pubDate>Wed, 13 Jun 2012 12:50:56 +0000</pubDate>
		<dc:creator>chmouel</dc:creator>
				<category><![CDATA[Openstack]]></category>

		<guid isPermaLink="false">http://blog.chmouel.com/?p=538</guid>
		<description><![CDATA[Historically if you wanted to write software in python against OpenStack swift, people would have use the python-cloudfiles library or swift.common.client shipped with Swift. python-cloudfiles was made mostly for Rackspace CloudFiles before even Swift existed and does a lot of extra stuff not needed for OpenStack Swift (i.e: CDN). swift.common.client was designed for OpenStack Swift from [...]]]></description>
				<content:encoded><![CDATA[<p>Historically if you wanted to write software in python against OpenStack swift, people would have use the python-cloudfiles library or swift.common.client shipped with Swift.</p>
<p><a href="https://github.com/rackspace/python-cloudfiles">python-cloudfiles</a> was made mostly for Rackspace CloudFiles before even Swift existed and does a lot of extra stuff not needed for OpenStack Swift (i.e: CDN).</p>
<p>swift.common.client was designed for OpenStack Swift from the ground up but is included with Swift which made people having to download the full Swift repository if they wanted to use or tests against it. (i.e: OpenStack glance).</p>
<p>As yesterday we have now removed swift.common.client wth the bin/swift CLI and moved it to its own repository available here :</p>
<p><a href="https://github.com/chmouel/python-swiftclient">https://github.com/openstack/python-swiftclient</a></p>
<p>This should be compatible with swift.common.client with only difference being to import swiftclient instead of importing swift.common.client</p>
<p>At this time we are using the same launchpad project as swift so feel free to send bugs/feature request under the swift  project in launchpad :</p>
<p><a href="https://bugs.launchpad.net/swift/+filebug">https://bugs.launchpad.net/swift/+filebug</a></p>
<p>and add the tag python-swiftclient there.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.chmouel.com/2012/06/13/swift-common-client-library-and-swift-cli-has-moved-to-its-own-project/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>S3 emulation to OpenStack Swift has moved</title>
		<link>http://blog.chmouel.com/2012/05/24/s3-emulation-to-openstack-swift-has-moved/</link>
		<comments>http://blog.chmouel.com/2012/05/24/s3-emulation-to-openstack-swift-has-moved/#comments</comments>
		<pubDate>Thu, 24 May 2012 15:09:59 +0000</pubDate>
		<dc:creator>chmouel</dc:creator>
				<category><![CDATA[Openstack]]></category>

		<guid isPermaLink="false">http://blog.chmouel.com/?p=532</guid>
		<description><![CDATA[A little note about swift3 the S3 emulation layer to OpenStack Swift As from this review we have removed it from Swift since the decision[1] was made that only the official OpenStack API would be supported in Swift. The development will be continued in fujita&#8217;s repository on github at this URL : https://github.com/fujita/swift3 Feel free to grab the middle-ware or [...]]]></description>
				<content:encoded><![CDATA[<p>A little note about swift3 the S3 emulation layer to OpenStack Swift</p>
<p>As from this <a href="https://review.openstack.org/#/c/7628/">review</a> we have removed it from Swift since the decision[1] was made that only the official OpenStack API would be supported in Swift. The development will be continued in fujita&#8217;s repository on github at this URL :</p>
<p><a href="https://github.com/fujita/swift3">https://github.com/fujita/swift3</a></p>
<p>Feel free to grab the middle-ware or report issue from fujita&#8217;s repository.</p>
<p>[1] Globally for OpenStack not just for Swift.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.chmouel.com/2012/05/24/s3-emulation-to-openstack-swift-has-moved/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Swift integration with other OpenStack components in Essex.</title>
		<link>http://blog.chmouel.com/2012/04/25/swift-integration-with-other-openstack-components-in-essex/</link>
		<comments>http://blog.chmouel.com/2012/04/25/swift-integration-with-other-openstack-components-in-essex/#comments</comments>
		<pubDate>Wed, 25 Apr 2012 15:11:58 +0000</pubDate>
		<dc:creator>chmouel</dc:creator>
				<category><![CDATA[Openstack]]></category>

		<guid isPermaLink="false">http://blog.chmouel.com/?p=525</guid>
		<description><![CDATA[During the development for OpenStack Essex a lot of work has been done to make Swift working well with the other OpenStack components, this is a list of the work that has been done. MIDDLEWARE To make Swift behaving well in the &#8216;stack&#8217; we had to get a rock solid keystone middleware and make sure [...]]]></description>
				<content:encoded><![CDATA[<p>During the development for OpenStack Essex a lot of work has been done to make Swift working well with the other OpenStack components, this is a list of the work that has been done.</p>
<h4><strong>MIDDLEWARE</strong></h4>
<p>To make Swift behaving well in the &#8216;stack&#8217; we had to get a rock solid keystone middleware and make sure most of the features provided by Swift would be supported by the middleware.</p>
<p>The middleware is currently <a href="https://github.com/openstack/keystone/blob/stable/essex/keystone/middleware/swift_auth.py" target="_blank">located</a> in the keystone essex repository and was entirely rewritten from the Diablo release to allow support these Swift features :</p>
<ul>
<li>ACL via keystone roles :</li>
</ul>
<p style="padding-left: 30px;">Allow you to map keystone roles as ACL, for example to allow a user with the keystone role &#8216;Reader&#8217; to read a container the user in <strong>swift_operator_role</strong> can set this ACL :</p>
<p style="padding-left: 30px;"><em>-r:Reader container</em></p>
<ul>
<li>Anonymous access via ACL referrer.</li>
</ul>
<p style="padding-left: 30px;">If a swift_operator wants to give anonymous access to a container in reading they can set this ACL :</p>
<p style="padding-left: 30px;"><em>-r:*</em></p>
<p style="padding-left: 30px;">It basically mean you are enabling public access to the container.</p>
<ul>
<li>Container syncing :</li>
</ul>
<p style="padding-left: 30px;">This allow to have two different container in sync, see the documentation <a href="http://swift.openstack.org/overview_container_sync.html" target="_blank">here</a>.</p>
<ul>
<li>Different reseller prefix :</li>
</ul>
<p style="padding-left: 30px;">You will be able to mix different auth server on your Swift cluster, like swauth and keystone.</p>
<ul>
<li>Special reseller admin account :</li>
</ul>
<p style="padding-left: 30px;">This is a special account whose allowed to access all account. It i used by nova for example to upload images to different accounts.</p>
<ul>
<li>S3 emulation :</li>
</ul>
<p style="padding-left: 30px;">Allows you to connect with S3 API to Swift using swift3 and new s3_token middleware. The S3 token will simply take a S3 token to validate it in keystone and get the proper tenant/user information to Swift.</p>
<p>One thing missing in the middleware is to allow auth overriding, basically it means that when an another middleware wants to take care of the authentication for some request the auth middleware will just let it go and allow the request to continue. Such feature is used for example in the <a href="http://swift.openstack.org/misc.html#module-swift.common.middleware.tempurl" target="_blank">temp_url</a> middleware to allow temporary access/upload to an object. This is projected to be supported in the future.</p>
<p>An important thing to keep in mind when you configure your roles is to have a user in a tenant (or account like called in Swift world) acting as an operator. This is controlled by the setting :</p>
<p><strong>swift_operator_roles</strong></p>
<p>and by default have the roles <em>swiftoperator</em> and <em>admin</em>. A user needs to have this role to be able to do something in a tenant.</p>
<h4><strong>GLANCE</strong></h4>
<p>Glance has been updated as well to be able to store images in swift which have a auth server using the 2.0 identity auth.</p>
<p><strong>NOVA</strong></p>
<p>Nova have the ability to access an objectstore to store images in a store which has been uploaded with the euca-upload-bundle command. Historically nova have shipped with a service called nova-objectstore but the service was buggy and had some security issues. Swift combined with keystone&#8217;s s3_token and swift3 middleware now can act as a more reliable and secure objectstore for Nova.</p>
<h4><strong>DEVSTACK</strong></h4>
<p>support Swift if you add the swift service to the ENABLED_SERVICE variable in your localrc. This is where you want to poke around to see how the configuration is made to have everything playing well together. The only bit that didn&#8217;t made for the devstack essex release is to have glance storing images directly in Swift.</p>
<h4><strong>CLI / Client Library</strong></h4>
<p>Swift CLI and client library (called swift.common.client) has been updated to support auth v2.0 the CLI support now the <a href="http://wiki.openstack.org/CLIAuth" target="_blank">common OpenStack CLI arguments and environment</a> to operate against auth server that has 2.0 identity auth.</p>
<p>We unfortunately were not in time to add the support for OS_AUTH_TENANT and use the Swift auth v1 syntax where if the user has the form of tenant:user OS_AUTH_TENANT will become tenant and OS_AUTH_USER the user.</p>
<p>Aside of a couple of bit missing we believe Swift should be rock solid to use with your other OpenStack components. There is no excuse to not use Swift as your central object storage component in OpenStack <img src='http://blog.chmouel.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> .</p>
<p>&nbsp;</p>
<div><strong><br />
</strong></div>
]]></content:encoded>
			<wfw:commentRss>http://blog.chmouel.com/2012/04/25/swift-integration-with-other-openstack-components-in-essex/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>How does a PUT to a swift object server look like.</title>
		<link>http://blog.chmouel.com/2012/02/06/anatomy-of-a-swift-put-query-to-object-server/</link>
		<comments>http://blog.chmouel.com/2012/02/06/anatomy-of-a-swift-put-query-to-object-server/#comments</comments>
		<pubDate>Mon, 06 Feb 2012 10:00:33 +0000</pubDate>
		<dc:creator>chmouel</dc:creator>
				<category><![CDATA[Openstack]]></category>

		<guid isPermaLink="false">http://blog.chmouel.com/?p=497</guid>
		<description><![CDATA[I have been trying lately to get a better understanding of the Swift code base, and I found the best way to know it was to read it from top to bottom and document it along the way. Here is some of my notes, hopefully more will come. I am starting with an object PUT [...]]]></description>
				<content:encoded><![CDATA[<p>I have been trying lately to get a better understanding of the Swift code base, and I found the best way to know it was to read it from top to bottom and document it along the way. Here is some of my notes, hopefully more will come.</p>
<p>I am starting with an object <strong>PUT</strong> when the request is coming from the proxy server. The request in the log-file will look like this :</p>
<p><em>&#8220;PUT /sdb1/2/AUTH_dcbeb7f1271d4374b951954a4f1be15f/foo/file.txt&#8221; 201 &#8211; &#8220;-&#8221; &#8220;txdw08eca2842e344bb8e11b5869c81cb52&#8243; &#8220;-&#8221; 0.0308</em></p>
<p>The WSGI controller send the request to the method <a href="https://github.com/openstack/swift/blob/80a3cb556d1ea2b8ac284816096198b89a2cf117/swift/obj/server.py#L530">swift.obj.server.ObjectController-&gt;PUT</a> and start to do the following :</p>
<ul>
<li>splits the request.path to :</li>
</ul>
<p style="text-align: center;">device(<strong>sdb1</strong>), partition(<strong>2</strong>), account(<strong>AUTH_ACCOUNT_ID</strong>), container(<strong>foo</strong>), obj(<strong>file.txt</strong>)</p>
<ul>
<li>Make sure that partition is mounted. (<em>there is a <strong>mount_check</strong> option that can toggle this</em>).</li>
<li>Ensure that there is a X-Timestamp header which should be set by the proxy server.</li>
<li>Start the check method <a href="https://github.com/openstack/swift/blob/80a3cb556d1ea2b8ac284816096198b89a2cf117/swift/common/constraints.py#L85">check_object_creation</a> which does the following :</li>
</ul>
<ul>
<li>Make sure the <strong>content_length</strong> is not greater than the <strong>MAX_FILE_SIZE</strong>.</li>
<li>Make sure there is a <strong>content_length</strong> header (<em>except if the transfer has been chunked</em>).</li>
<li>Make sure that there is no <strong>content_length</strong> (ie: zero byte body) when doing a <strong>X-Copy-From</strong>.</li>
<li>Make sure the<strong> object_name</strong> is not greater than <strong>MAX_OBJECT_NAME_LENGTH</strong> (<em>1024 bytes by default</em>).</li>
<li>Making sure we have a <strong>Content-Type</strong> in the headers passed (this could be set by the user or auto-guessed via <a href="http://docs.python.org/library/mimetypes.html#mimetypes.guess_type">mimetypes.guess_type</a> on the proxy server).</li>
<li>When we have an header of <strong>x-object-manifest</strong> (<em>for large files support</em>) it makes sure the value is a container/object style and not contain chars like <strong>? &amp; /</strong> in the referenced objects names.</li>
<li>Checks metadata, make sure at first that the metadata name are not empty.</li>
<li>The metadata name length are not greater than <strong>MAX_META_NAME_LENGTH</strong> (<em>default: 128</em>).</li>
<li>The metadata value is not greater than <strong>MAX_META_VALUE_LENGTH</strong> (<em>default: 256</em>).</li>
<li>We don&#8217;t have a greater amount of metadatas than <strong>MAX_META_COUNT</strong> (<em>default: 90</em>).</li>
<li>The size of the headers combined (<em>name+value</em>) is not over <strong>MAX_META_OVERALL_SIZE</strong> (<em>default: 4096</em>).</li>
<li>If we have &#8216;<strong>X-Delete-At</strong>&#8216; (<em>for the object expiration feature</em>) we are making sure this is not happening in the past or we will exit with an <strong>HTTPBadRequest</strong>.</li>
<li>The class <a href="https://github.com/openstack/swift/blob/80a3cb556d1ea2b8ac284816096198b89a2cf117/swift/obj/server.py#L94">swift.obj.server.DiskFile</a> will be the class that takes care to actually write the file locally. It gets instantiated and do the following in the constructor method:</li>
<li>It will hash the following  value (<strong>account</strong>, <strong>container</strong>, <strong>obj)</strong> which will become hashed for our example into :</li>
</ul>
<p style="text-align: center;"><span style="font-size: small;"><span style="line-height: 24px;">46acec4563797178df9ec79b28146fe1</span></span></p>
<ul>
<li>It will get the path where this is going to be store which going to be :</li>
</ul>
<p style="text-align: center;"><span style="font-size: small;"><span style="line-height: 24px;">/srv/node/sdb1/objects/2/fe1/46acec4563797178df9ec79b28146fe1</span></span></p>
<ul>
<li><strong>/srv/node</strong> is the devices path which is the configuration directive <a href="https://github.com/openstack/swift/blob/master/etc/object-server.conf-sample#L8">[proxy]-&gt;devices</a> (<em>default to /srv/node</em>).</li>
<li><strong>sdb1</strong> being the mounted device name.</li>
<li>add the datadir type, &#8221;<strong>objects</strong>&#8221; for us.</li>
<li>and the partition power (<strong>2</strong>)</li>
<li>last three chars of the hashed name (<strong>fe1</strong>)</li>
<li>the hash itself <strong>46acec4563797178df9ec79b28146fe1</strong></li>
<li>It will get the temporary directory which become in our case to: <strong>/srv/node/sdb1/tmp</strong> it is basically the devices dir, the device and /tmp</li>
<li>If the directory didn&#8217;t exists before then it just return.</li>
<li>If the directory was existing (already uploaded) then it will parse all files in there and would looks if we have :</li>
<li>Files ending up with .<strong><em>ts</em></strong>  which will be the tombstone (a deleted file).  NB: <em>Replication process will take care to os.unlink() the file properly later.</em></li>
<li>In case of a <em>POST</em> and if we have fast post setting enabled (see config <strong>object_post_as_copy</strong> in proxy_server) we will detect it and only do a copy of metadata.</li>
<li>It calculates the expiration time which is from now + the <strong>max_upload_time</strong> setting.</li>
<li>It start the etag hashing to gradually calculate the md5 of the object.</li>
<li> Using the method <strong>mkstemp</strong> of <strong>DiskFile</strong> it will start to write to tmpdir, which does the creation of the file like that :</li>
<li>Make sure to create the <em>tmpdir</em>.</li>
<li>make a secure temporary file (using <strong>mkstemp</strong>(3)) and yield the file descriptor back to <strong>PUT</strong>.</li>
<li>If there is a <strong>content-length</strong> in the headers (assigned by the client) it will use the posix function <strong><a href="http://linux.die.net/man/2/fallocate">fallocate</a></strong>(2) to pre-allocate that disk space to the file descriptor.</li>
<li>It will then iterate over chunk of data size defined by the configuration variable <strong>network_chunk_size</strong> (<em>default: 64m</em>) reading that chunk from the request <em>wsgi.input</em> :</li>
<li>It will update the <strong>upload_size </strong>value.</li>
<li>It will make sure we are not going over our upload expiration time (<em>or get back <strong>HTTPRequestTimeout</strong> HTTP Error</em>).</li>
<li>It will update the calculated md5 with that chunk.</li>
<li>It will write the chunk using python <a href="http://docs.python.org/library/os.html#os.write">os.write</a></li>
<li>For large file sync which is over the configuration variable <strong>bytes_per_sync</strong> it will do a <a href="http://linux.die.net/man/2/fdatasync">fdatasync</a>(2) and drop the kernel buffer caches (s<em>o we are not filling up too much the kernel memory</em>).</li>
<li>if we have a <strong>content-length</strong> in the client headers that doesn&#8217;t match the calculated <strong>upload_size</strong> we return a <strong><em>499 Client Disconnected</em></strong> as it means we had a problem somewhere during the upload.</li>
<li>It will bail out if we have a etag in the client headers that doesn&#8217;t match the calculated etag.</li>
</ul>
<p>And now we are starting defining our metadatas that we are going to store with the file  :</p>
<blockquote><p><em>metadata = {</em><br />
<em>  &#8216;<strong>X-Timestamp&#8217;</strong>: </em>timestamp generated from the proxy_server<em>.</em><br />
<em>  &#8216;<strong>Content-Type</strong>&#8216;: d</em>efined by the user or &#8216;guessed&#8217; by the proxy server<br />
<em>  &#8216;<strong>ETag</strong>&#8216;: </em>calculated value from the request.<br />
<em>  &#8216;<strong>Content</strong>-<strong>Length</strong>&#8216;: </em>an fstat(2) on the file to get the proper value of what is stored on the disk.<br />
<em> }</em></p></blockquote>
<ul>
<li>It will add to the metadata every headers starting by <strong>&#8216;x-object-meta-&#8217;.</strong></li>
<li>It will add to the metadata the allowed headers to be stored which is defined in the config variable<strong> allowed_headers</strong> (default: <em>allowed_headers = Content-Disposition, Content-Encoding, X-Delete-At, X-Object-Manifest</em>).</li>
<li>It will write the file using the put method of the DiskFile class, which finalise the writing on the file on disk and renames it from the temp file to the real location:</li>
<li>It will write the metadata using the <a href="https://developer.apple.com/library/mac/#documentation/Darwin/Reference/ManPages/man1/xattr.1.html">xattr</a>(1) feature which is stored directly with the file.</li>
<li>If there is a <strong>Content-Length</strong> with the metada it will drop the kernel cache of that metadata length.</li>
<li>It will invalidate the hashes of the <strong>datadir</strong> directory using the function <a href="https://github.com/openstack/swift/blob/80a3cb556d1ea2b8ac284816096198b89a2cf117/swift/obj/replicator.py#L128">swift.obj.replicator.invalidate_hashes</a></li>
<li>It will set the hash of the dir as <strong>None</strong>, which would hint the replication process to have something to do with that dir (and that hash will be generated).</li>
<li>This file is stored by partition as python <a href="http://docs.python.org/library/pickle.html">pickle</a> which is in our case: <em>/srv/node/sdb1/objects/2/hashes.pkl</em></li>
<li>Move the file from the tmp dir to go to the <strong>datadir</strong>.</li>
<li>It will use the method <a href="https://github.com/openstack/swift/blob/master/swift/obj/server.py#L283">unlinkold</a> from <strong>DiskFile</strong> to remove any older versions of the object file which is any files that has older timestamp.</li>
<li>It will start construct the request to make to a containers by going passing the following:</li>
<li><strong>account</strong>, <strong>container</strong>, <strong>obj</strong> as request path.</li>
<li>the original headers.</li>
<li>the headers <strong>Content-Length</strong>, <strong>Content-Type</strong>, <strong>X-Timestamp</strong>, <strong>Etag</strong>, <strong>X-trans-ID</strong>.</li>
<li>It will get the headers <strong>X-Container-{Host,Partition,Device}</strong> from the original headers which is defined by the proxy to know on which container server it going to update. Every different PUT will have assigned a different container to each their own.</li>
<li>It will use the <a href="https://github.com/openstack/swift/blob/80a3cb556d1ea2b8ac284816096198b89a2cf117/swift/obj/server.py#L381">async_update</a> method (<em>by self since it&#8217;s part of the same class</em>) to make an asynchronous request:</li>
<li>Passing the aforementioned build headers and req.path.</li>
<li> If the request success (between <strong>200</strong> to <strong>300</strong>) it will return to the main (<strong>PUT</strong>) method.</li>
<li> the request didn&#8217;t succeed it will create a <strong>async_pending</strong> file locally in the tmp dir which is going to be picked-up by the replication process to update the container listing when the container is not too busy.</li>
<li>When finish it will respond by a <strong>HTTPCreated</strong></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.chmouel.com/2012/02/06/anatomy-of-a-swift-put-query-to-object-server/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
	</channel>
</rss>
