<?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</title>
	<atom:link href="http://blog.chmouel.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.chmouel.com</link>
	<description>Random and probably boring stuff.</description>
	<lastBuildDate>Wed, 25 Apr 2012 15:11:58 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
<atom:link rel="hub" href="http://pubsubhubbub.appspot.com"/><atom:link rel="hub" href="http://superfeedr.com/hubbub"/>		<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 &#8230; <a href="http://blog.chmouel.com/2012/04/25/swift-integration-with-other-openstack-components-in-essex/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></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 &#8230; <a href="http://blog.chmouel.com/2012/02/06/anatomy-of-a-swift-put-query-to-object-server/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></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>4</slash:comments>
		</item>
		<item>
		<title>Audit a swift cluster</title>
		<link>http://blog.chmouel.com/2012/02/01/audit-a-swift-cluster/</link>
		<comments>http://blog.chmouel.com/2012/02/01/audit-a-swift-cluster/#comments</comments>
		<pubDate>Wed, 01 Feb 2012 10:18:11 +0000</pubDate>
		<dc:creator>chmouel</dc:creator>
				<category><![CDATA[Openstack]]></category>

		<guid isPermaLink="false">http://blog.chmouel.com/?p=493</guid>
		<description><![CDATA[Swift integrity tools. There is quite a bit of tools shipped with Swift to ensure you have the right object on your cluster. At first there is the basic : swift-object-info It will take a swift object stored on the &#8230; <a href="http://blog.chmouel.com/2012/02/01/audit-a-swift-cluster/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Swift integrity tools.</p>
<p>There is quite a bit of tools shipped with Swift to ensure you have the right object on your cluster.</p>
<p>At first there is the basic :</p>
<p><strong>swift-object-info</strong></p>
<p>It will take a swift object stored on the filesystem and print some infos about it, like this :</p>
<blockquote><p>swift@storage01:0/016/0b221bab535ac1b8f0d91e394f225016$ swift-object-info 1327991417.01411.data<br />
Path: /AUTH_root/foobar/file.txt<br />
Account: AUTH_root<br />
Container: foobar<br />
Object: file.txt<br />
Object hash: 0b221bab535ac1b8f0d91e394f225016<br />
Ring locations:<br />
192.168.254.12:6000 &#8211; /srv/node/sdb1/objects/0/016/0b221bab535ac1b8f0d91e394f225016/1327991417.01411.data<br />
Content-Type: text/plain<br />
Timestamp: 2012-01-31 06:30:17.014110 (1327991417.01411)<br />
ETag: 053a0f8516a5023b9af76c49ca917d3e (valid)<br />
Content-Length: 24 (valid)<br />
User Metadata: {&#8216;X-Object-Meta-Mtime&#8217;: &#8217;1327968327.21&#8242;}</p></blockquote>
<p>PS: If you don&#8217;t know where is your object on which node, you can you use swift-get-nodes</p>
<p>For auditing, the Etag value is important because swift-object-info will compare the object recorded etag in the metadata with what we have on the disks. Let&#8217;s try to see if that works :</p>
<blockquote><p>swift@storage01:0/016/0b221bab535ac1b8f0d91e394f225016$ cp 1327991417.01411.data /tmp<br />
swift@storage01:0/016/0b221bab535ac1b8f0d91e394f225016$ echo &#8220;foo&#8221; &gt;&gt; 1327991417.01411.data<br />
swift@storage01:0/016/0b221bab535ac1b8f0d91e394f225016$ swift-object-info 1327991417.01411.data|grep &#8216;^Etag&#8217;<br />
Etag: 053a0f8516a5023b9af76c49ca917d3e doesn&#8217;t match file hash of 9ff871e5ce5dcb5d3f2680a80a88ff38!</p></blockquote>
<p>swift-object-info has detected that this file is not the one we have uploaded.</p>
<p>There is an other tool called <strong>swift-drive-audit</strong> which as explained in the <a title="Admin Guide" href="http://swift.openstack.org/admin_guide.html">admin guide</a> will parse the <em>/var/log/kern.log</em> and have predefined regexp  to detect disk failure notified by the kernel. It is usually run periodically by cron and there is a config file for it called <em><a href="https://github.com/openstack/swift/blob/master/etc/drive-audit.conf-sample">/etc/swift/drive-audit.conf.</a></em> If the script find any errors for a certain drive it will unmount it and comment it in /etc/fstab(5). Afterwards  the replication process will pick it up from other replicas and put the object on that drive in <em>handover</em>.</p>
<p>Swift provide as well different type of auditor daemons for account/container/object :</p>
<ul>
<li> swift-account-auditor</li>
<li> swift-container-auditor</li>
<li> swift-object-auditor</li>
</ul>
<p><strong>swift-account-auditor</strong> will open all sqlite db of an account server and launch a SQL query to make sure all the dbs are valid.<br />
<strong>swift-container-auditor</strong> will do the same but for containers.<br />
<strong>swift-object-auditor</strong> will open all object of an object server and make sure of :</p>
<ul>
<li>Metadata are correct.</li>
<li>We have the proper size.</li>
<li>We have the proper MD5.</li>
</ul>
<p>Those auditors needs to be set in each type-server.conf, for example for account server you will add something like this to /etc/swift/account-server.conf :</p>
<blockquote><p>[account-auditor]<br />
# You can override the default log routing for this app here (don&#8217;t use set!):<br />
# log_name = account-auditor<br />
# log_facility = LOG_LOCAL0<br />
# log_level = INFO<br />
# Will audit, at most, 1 account per device per interval<br />
interval = 1800<br />
# log_facility = LOG_LOCAL0<br />
# log_level = INFO</p></blockquote>
<p>For container this is about the same options but for object-server does are the options :</p>
<blockquote><p>[object-auditor]<br />
# You can override the default log routing for this app here (don&#8217;t use set!):<br />
# log_name = object-auditor<br />
# log_facility = LOG_LOCAL0<br />
# log_level = INFO<br />
# files_per_second = 20<br />
# bytes_per_second = 10000000<br />
# log_time = 3600<br />
# zero_byte_files_per_second = 50</p></blockquote>
<p>Another tool shipped with swift is <strong>swift-account-audit</strong> which will audit a full account and report if there is missing replicas or incorrect object in that account.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.chmouel.com/2012/02/01/audit-a-swift-cluster/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>My stats for this year running and cycling</title>
		<link>http://blog.chmouel.com/2011/12/28/my-training-year-cycling-and-running/</link>
		<comments>http://blog.chmouel.com/2011/12/28/my-training-year-cycling-and-running/#comments</comments>
		<pubDate>Wed, 28 Dec 2011 19:08:27 +0000</pubDate>
		<dc:creator>chmouel</dc:creator>
				<category><![CDATA[Life]]></category>

		<guid isPermaLink="false">http://blog.chmouel.com/?p=483</guid>
		<description><![CDATA[Running 1,266 km  (786 miles): Cycling 3865 km (2401 miles): Let&#8217;s see if I can improve for next year]]></description>
			<content:encoded><![CDATA[<p>Running 1,266 km  (786 miles):</p>
<p><a href="http://blog.chmouel.com/wp-content/uploads/2011/12/Screen-Shot-2011-12-28-at-19.44.05.png"><img class="aligncenter size-large wp-image-484" title="Screen Shot 2011-12-28 at 19.44.05" src="http://blog.chmouel.com/wp-content/uploads/2011/12/Screen-Shot-2011-12-28-at-19.44.05-1024x262.png" alt="" width="640" height="163" /></a></p>
<p>Cycling 3865 km (2401 miles):</p>
<p><a href="http://blog.chmouel.com/wp-content/uploads/2011/12/Screen-Shot-2011-12-28-at-19.44.20.png"><img class="aligncenter size-large wp-image-485" title="Screen Shot 2011-12-28 at 19.44.20" src="http://blog.chmouel.com/wp-content/uploads/2011/12/Screen-Shot-2011-12-28-at-19.44.20-1024x306.png" alt="" width="640" height="191" /></a></p>
<p>Let&#8217;s see if I can improve for next year</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.chmouel.com/2011/12/28/my-training-year-cycling-and-running/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Swift and Keystone middleware &#8211; Part1</title>
		<link>http://blog.chmouel.com/2011/11/24/swift-and-keystone-middleware-part1/</link>
		<comments>http://blog.chmouel.com/2011/11/24/swift-and-keystone-middleware-part1/#comments</comments>
		<pubDate>Thu, 24 Nov 2011 09:20:39 +0000</pubDate>
		<dc:creator>chmouel</dc:creator>
				<category><![CDATA[Openstack]]></category>

		<guid isPermaLink="false">http://blog.chmouel.com/?p=472</guid>
		<description><![CDATA[It seems that integrating Swift and Keystone together present some challenges to people and this is absolutely normal as there is a lot of changes going on. This is my attempt to document how everything is plugged together. I am &#8230; <a href="http://blog.chmouel.com/2011/11/24/swift-and-keystone-middleware-part1/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>It seems that integrating <a href="http://swift.openstack.org/" target="_blank">Swift</a> and <a href="http://keystone.openstack.org/" target="_blank">Keystone</a> together present some challenges to people and this is absolutely normal as there is a lot of changes going on. This is my attempt to document how everything is plugged together.</p>
<p>I am not going to explain how a middleware is supposed to work as this is nicely documented on Wikipedia :</p>
<p><a href="http://en.wikipedia.org/wiki/Middleware" target="_blank">http://en.wikipedia.org/wiki/Middleware</a></p>
<p>or how the auth middlewares works on Swift :</p>
<p><a href="http://swift.openstack.org/development_auth.html" target="_blank">http://swift.openstack.org/development_auth.html<br />
</a><br />
or even how this is plugged inside Keystone :</p>
<p><a href="http://keystone.openstack.org/middleware_architecture.html" target="_blank">http://keystone.openstack.org/middleware_architecture.html<br />
</a></p>
<p>At first let&#8217;s get some of the wordings right :</p>
<ul>
<li>A <strong>tenant</strong> in keystone is an <strong>account</strong> in swift.</li>
<li>A <strong>user</strong> in keystone is also a <strong>user</strong> in swift.</li>
<li>A <strong>role</strong> in keystone is a <strong>group</strong> in swift.</li>
</ul>
<p>Now that you keep this in mind let&#8217;s walk-though how a request will<br />
look like.</p>
<p>At first your user connect to keystone and says this is my username for this<br />
tenant and here is the secret/api key, give me the endpoints for the<br />
services and add a token to it. This will look like this in curl :</p>

<div class="wp_codebox"><table><tr id="p4728"><td class="code" id="p472code8"><pre class="bash" style="font-family:monospace;">curl <span style="color: #660033;">-s</span> <span style="color: #660033;">-d</span> <span style="color: #ff0000;">'{&quot;auth&quot;: {&quot;tenantName&quot;: &quot;demo&quot;, &quot;passwordCredentials&quot;: {&quot;username&quot;: &quot;demo&quot;, &quot;password&quot;: &quot;password&quot;}}}'</span> <span style="color: #660033;">-H</span> <span style="color: #ff0000;">'Content-type: application/json'</span> http:<span style="color: #000000; font-weight: bold;">//</span>localhost:<span style="color: #000000;">5000</span><span style="color: #000000; font-weight: bold;">/</span>v2.0<span style="color: #000000; font-weight: bold;">/</span>tokens</pre></td></tr></table></div>

<p>If successfully authenticated you get back in Json those public/internal urls<br />
for swift so you are able to connect, here is some part of the replied request :</p>
<pre>{
    "endpoints": [
        {
            "adminURL": "http://localhost:8080/",
            "internalURL": "http://localhost:8080/v1/AUTH_2",
            "publicURL": "http://localhost:8080/v1/AUTH_2",
            "region": "RegionOne"
        }
    ],
    "name": "swift",
    "type": "object-store"
}
[...]
"token": {
    "expires": "2011-11-24T12:35:56",
    "id": "ea29dae7-4c54-4e80-98e1-9f886acb389a",
    "tenant": {
        "id": "2",
        "name": "demo"
    }
},</pre>
<p>So now the clients is going to get the publicURL (or can be internal) with the token and able to give request to swift with it. Let&#8217;s take the simple request which list the container,  this is a basic GET on the account :</p>

<div class="wp_codebox"><table><tr id="p4729"><td class="code" id="p472code9"><pre class="bash" style="font-family:monospace;">curl <span style="color: #660033;">-v</span> <span style="color: #660033;">-H</span> <span style="color: #ff0000;">'X-Auth-Token: ea29dae7-4c54-4e80-98e1-9f886acb389a'</span> http:<span style="color: #000000; font-weight: bold;">//</span>localhost:<span style="color: #000000;">8080</span><span style="color: #000000; font-weight: bold;">/</span>v1<span style="color: #000000; font-weight: bold;">/</span>AUTH_2</pre></td></tr></table></div>

<p>which should come back by a 20* http code if that work.</p>
<p>What&#8217;s happening here is that when you connect to swift it will pass it to the middleware to make sure we are able to have access with that token.</p>
<p>The middleware will take that token connect to keystone admin url with the admin token and pass that user token to be validated. The query looks like this in curl :</p>

<div class="wp_codebox"><table><tr id="p47210"><td class="code" id="p472code10"><pre class="bash" style="font-family:monospace;">curl <span style="color: #660033;">-H</span> <span style="color: #ff0000;">'X-Auth-Token: 7XX'</span> http:<span style="color: #000000; font-weight: bold;">//</span>localhost:<span style="color: #000000;">35357</span><span style="color: #000000; font-weight: bold;">/</span>v2.0<span style="color: #000000; font-weight: bold;">/</span>tokens<span style="color: #000000; font-weight: bold;">/</span>ea29dae7-4c54-4e80-98e1-9f886acb389a</pre></td></tr></table></div>

<p><em><strong>note</strong>: localhost:35357 is the keystone admin url and 7XX is the admin token set in the configuration of the middleware.</em></p>
<p>if successful keystone will come back with a reply that look like this :</p>

<div class="wp_codebox"><table><tr id="p47211"><td class="code" id="p472code11"><pre class="javascript" style="font-family:monospace;"><span style="color: #009900;">&#123;</span>
    <span style="color: #3366CC;">&quot;access&quot;</span><span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #3366CC;">&quot;token&quot;</span><span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #3366CC;">&quot;expires&quot;</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;2011-11-24T12:35:56&quot;</span><span style="color: #339933;">,</span>
            <span style="color: #3366CC;">&quot;id&quot;</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;ea29dae7-4c54-4e80-98e1-9f886acb389a&quot;</span><span style="color: #339933;">,</span>
            <span style="color: #3366CC;">&quot;tenant&quot;</span><span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span>
                <span style="color: #3366CC;">&quot;id&quot;</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;2&quot;</span><span style="color: #339933;">,</span>
                <span style="color: #3366CC;">&quot;name&quot;</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;demo&quot;</span>
            <span style="color: #009900;">&#125;</span>
        <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
        <span style="color: #3366CC;">&quot;user&quot;</span><span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #3366CC;">&quot;id&quot;</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;2&quot;</span><span style="color: #339933;">,</span>
            <span style="color: #3366CC;">&quot;roles&quot;</span><span style="color: #339933;">:</span> <span style="color: #009900;">&#91;</span>
                <span style="color: #009900;">&#123;</span>
                    <span style="color: #3366CC;">&quot;id&quot;</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;2&quot;</span><span style="color: #339933;">,</span>
                    <span style="color: #3366CC;">&quot;name&quot;</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;Member&quot;</span><span style="color: #339933;">,</span>
                    <span style="color: #3366CC;">&quot;tenantId&quot;</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;2&quot;</span>
                <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
                <span style="color: #009900;">&#123;</span>
                    <span style="color: #3366CC;">&quot;id&quot;</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;5&quot;</span><span style="color: #339933;">,</span>
                    <span style="color: #3366CC;">&quot;name&quot;</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;SwiftOperator&quot;</span><span style="color: #339933;">,</span>
                    <span style="color: #3366CC;">&quot;tenantId&quot;</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;2&quot;</span>
                <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>
            <span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span>
            <span style="color: #3366CC;">&quot;username&quot;</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;demo&quot;</span>
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>Let&#8217;s step back before more Curl command and understand a thing about Swift, a user of an account in Swift by default don&#8217;t have any rights at all but there is one user in that account  whose able to give ACL on containers for other users. In swift keystone middleware we call it an Operator.</p>
<p>The way the middleware knows which user is able to be admin on an account is by using the roles matching to whatever configuration we have on the middleware setting called :</p>
<pre>keystone_swift_operator_roles = Admin, SwiftOperator</pre>
<p>since this user is part the SwiftOperator then it has access and he&#8217;s allowed to do whatever he wants for that account like creating containers or giving ACL to other users.</p>
<p>So let&#8217;s say we have a user called demo2 which is part of the demo account and have only the role Member to it and not SwiftOperator by default as we say before he will not be able to do much.</p>
<p>But if demo user give access to the group/role Memeber to a container via acl then demo2 will be able to do stuff on it.</p>
<p>We can all have fun with bunch of curl commands but since swift 1.4.7 the swift CLI tool have support for the auth server version 2.0 and allow you to connect to keystone for auth so we are going to use that instead.</p>
<p>Let first create a testcontainer and upload a file into it with our &#8216;operator&#8217; user :</p>

<div class="wp_codebox"><table><tr id="p47212"><td class="code" id="p472code12"><pre class="bash" style="font-family:monospace;">swift <span style="color: #660033;">--auth-version</span> <span style="color: #000000;">2</span> <span style="color: #660033;">-A</span> http:<span style="color: #000000; font-weight: bold;">//</span>localhost:<span style="color: #000000;">5000</span><span style="color: #000000; font-weight: bold;">/</span>v2.0 <span style="color: #660033;">-U</span> demo:demo <span style="color: #660033;">-K</span> password post testcontainer</pre></td></tr></table></div>

<p>now let&#8217;s give access to the Member group for that container on reading :</p>

<div class="wp_codebox"><table><tr id="p47213"><td class="code" id="p472code13"><pre class="bash" style="font-family:monospace;">swift <span style="color: #660033;">--auth-version</span> <span style="color: #000000;">2</span> <span style="color: #660033;">-A</span> http:<span style="color: #000000; font-weight: bold;">//</span>localhost:<span style="color: #000000;">5000</span><span style="color: #000000; font-weight: bold;">/</span>v2.0 <span style="color: #660033;">-U</span> demo:demo <span style="color: #660033;">-K</span> password post testcontainer <span style="color: #660033;">-r</span> Member</pre></td></tr></table></div>

<p>and now if we try to read that file directly with demo2 it will be allowed :</p>

<div class="wp_codebox"><table><tr id="p47214"><td class="code" id="p472code14"><pre class="bash" style="font-family:monospace;">swift <span style="color: #660033;">--auth-version</span> <span style="color: #000000;">2</span> <span style="color: #660033;">-A</span> http:<span style="color: #000000; font-weight: bold;">//</span>localhost:<span style="color: #000000;">5000</span><span style="color: #000000; font-weight: bold;">/</span>v2.0 <span style="color: #660033;">-U</span> demo:demo2 <span style="color: #660033;">-K</span> password download testcontainer etc<span style="color: #000000; font-weight: bold;">/</span>issue <span style="color: #660033;">-o-</span></pre></td></tr></table></div>

<p>Hope this make things a bit more clears how everything works, in the next part I am going to explain how the config files and packages will look like for installing keystone and swift.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.chmouel.com/2011/11/24/swift-and-keystone-middleware-part1/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Debugging python-novaclient on the command line.</title>
		<link>http://blog.chmouel.com/2011/09/02/debugging-python-novaclient-on-the-command-line/</link>
		<comments>http://blog.chmouel.com/2011/09/02/debugging-python-novaclient-on-the-command-line/#comments</comments>
		<pubDate>Fri, 02 Sep 2011 03:00:13 +0000</pubDate>
		<dc:creator>chmouel</dc:creator>
				<category><![CDATA[Openstack]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blog.chmouel.com/?p=464</guid>
		<description><![CDATA[I have done lately quite a bit of work with python-novaclient the (nova/keystone) openstack client. I often experiment it with ipython in the console. There is a nice debugging facility in novaclient which you can see while using &#8211;debug argument &#8230; <a href="http://blog.chmouel.com/2011/09/02/debugging-python-novaclient-on-the-command-line/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I have done lately quite a bit of work with <a href="https://github.com/rackspace/python-novaclient" target="_blank">python-novaclient</a> the (nova/keystone) openstack client. I often experiment it with <a href="http://ipython.org/" target="_blank">ipython</a> in the console.</p>
<p>There is a nice debugging facility in novaclient which you can see while using &#8211;debug argument on the command line and if you wanted to use it with ipython you could have that at the beginning of your session :</p>
<p><script src="https://gist.github.com/1187833.js?file=noclientdebug.py"></script></p>
<p>This would give you the details of the session showing you the REST requests and responses including the headers. It even show you the curl commands that you can use on the command line to experiment with it.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.chmouel.com/2011/09/02/debugging-python-novaclient-on-the-command-line/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Rackspace CloudDNS python binding</title>
		<link>http://blog.chmouel.com/2011/07/17/rackspace-clouddns-python-binding/</link>
		<comments>http://blog.chmouel.com/2011/07/17/rackspace-clouddns-python-binding/#comments</comments>
		<pubDate>Sun, 17 Jul 2011 07:32:09 +0000</pubDate>
		<dc:creator>chmouel</dc:creator>
				<category><![CDATA[Cloud]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://blog.chmouel.com/?p=457</guid>
		<description><![CDATA[I have released a python binding to Rackspace CloudDNS here which allow you to create/update/delete domains and records. It&#8217;s available on github https://github.com/rackspace/python-clouddns/ The binding is pretty simple and have unfortunately no documentation (or even tests) but you can figure &#8230; <a href="http://blog.chmouel.com/2011/07/17/rackspace-clouddns-python-binding/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I have released a python binding to <a href="http://www.rackspace.com/cloud/cloud_hosting_products/dns/" title="DNSaas" target="_blank">Rackspace CloudDNS</a> here which allow you to create/update/delete domains and records. It&#8217;s available on github</p>
<p><a href="https://github.com/rackspace/python-clouddns/" target="_blank">https://github.com/rackspace/python-clouddns/</a></p>
<p>The binding is pretty simple and have unfortunately no documentation (or even tests) but you can figure out most of it from here :</p>
<p><a href="https://github.com/rackspace/python-clouddns/blob/master/tests/t.py" target="_blank">https://github.com/rackspace/python-clouddns/blob/master/tests/t.py</a></p>
<p>I will be very welcoming pull request that add a bit of documentation.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.chmouel.com/2011/07/17/rackspace-clouddns-python-binding/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Mass editing firewall on Rackspace Cloud.</title>
		<link>http://blog.chmouel.com/2011/05/05/mass-editing-firewall-on-rackspace-cloud/</link>
		<comments>http://blog.chmouel.com/2011/05/05/mass-editing-firewall-on-rackspace-cloud/#comments</comments>
		<pubDate>Thu, 05 May 2011 22:12:42 +0000</pubDate>
		<dc:creator>chmouel</dc:creator>
				<category><![CDATA[Cloud]]></category>
		<category><![CDATA[Rackspace]]></category>

		<guid isPermaLink="false">http://blog.chmouel.com/?p=447</guid>
		<description><![CDATA[A lot of our customers in Rackspace cloud has been asking how to mass edit firewalls of servers when you have multiple servers without doing it manually. Part of my cloudservers-api-demo I have written a simple firewall scripts abstracting the &#8230; <a href="http://blog.chmouel.com/2011/05/05/mass-editing-firewall-on-rackspace-cloud/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>A lot of our customers in Rackspace cloud has been asking how to mass edit firewalls of servers when you have multiple servers without doing it manually.</p>
<p>Part of my <a href="https://github.com/chmouel/cloudservers-api-demo">cloudservers-api-dem</a>o I have written a simple firewall scripts abstracting the Operating System firewall software to allow/enable/disable the firewall and ports/networks.</p>
<p>The script has been kept very simple by design and currently allow only to :</p>
<ul>
<li><span style="font-size: medium;">
<p style="display: inline !important;">enable the firewall</p>
<p></span></li>
<li><span style="font-size: medium;">
<p style="display: inline !important;">disable the firewall</p>
<p></span></li>
<li><span style="font-size: medium;">
<p style="display: inline !important;">allow or disallow a port or a network</p>
<p></span></li>
<li><span style="font-size: medium;">
<p style="display: inline !important;">see firewall status</p>
<p></span></li>
</ul>
<h3>PREREQUISITES</h3>
<ul>
<li><span style="font-size: medium;">
<p style="display: inline !important;">A management server under Ubuntu maverick.</p>
<p></span></li>
<li><span style="font-size: medium;">
<p style="display: inline !important;">A supported Operating System for clients which includes :</p>
<p></span></li>
<li><span style="font-size: medium;">
<p style="display: inline !important;">Debian.</p>
<p></span></li>
<li><span style="font-size: medium;">
<p style="display: inline !important;">Ubuntu.</p>
<p></span></li>
<li><span style="font-size: medium;">
<p style="display: inline !important;">RHEL.</p>
<p></span></li>
<li><span style="font-size: medium;">
<p style="display: inline !important;">Fedora</p>
<p></span></li>
<li><span style="font-size: medium;">
<p style="display: inline !important;">My patched python-cloudservers library (see below for installs).</p>
<p></span></li>
<li><span style="font-size: medium;">
<p style="display: inline !important;">Your SSH key installed on all VM for root users.</p>
<p></span></li>
</ul>
<h3>Install</h3>
<ul>
<li><span style="font-size: medium;">
<p style="display: inline !important;">After you have kicked a VM with a Ubuntu maverick and connected to it as root you want first execute intall some prereq packages :</p>
<p></span></li>
</ul>

<div class="wp_codebox"><table><tr id="p44719"><td class="code" id="p447code19"><pre class="sh" style="font-family:monospace;">apt-get update &amp;amp;&amp;amp; apt-get -y install python-stdeb git</pre></td></tr></table></div>

<p>checkout my python-cloudservers library :</p>

<div class="wp_codebox"><table><tr id="p44720"><td class="code" id="p447code20"><pre class="sh" style="font-family:monospace;">git clone git://github.com/chmouel/python-cloudservers.git</pre></td></tr></table></div>

<p>after being checked-out you will go into the python-cloudservers directory which has just been created and do this :</p>

<div class="wp_codebox"><table><tr id="p44721"><td class="code" id="p447code21"><pre class="sh" style="font-family:monospace;">cd python-cloudservers/
python setup.py install</pre></td></tr></table></div>

<p>this should automatically install all the dependences.</p>
<p>Now you can install my api-demo which include the firewall script :</p>

<div class="wp_codebox"><table><tr id="p44722"><td class="code" id="p447code22"><pre class="sh" style="font-family:monospace;">cd ../
git clone git://github.com/chmouel/cloudservers-api-demo</pre></td></tr></table></div>

<p>You need to configure some environemnt variable first which keep information about your rackspace account.</p>
<p>edit your ~/.bashrc (or /etc/environement if you want to make it global) and configure those variable :</p>
<pre>export RCLOUD_DATACENTER=UK
export UK_RCLOUD_USER="MY_USERNAME"
export UK_RCLOUD_KEY="MY_API_KEY"
export UK_RCLOUD_AURL="https://lon.auth.api.rackspacecloud.com/v1.0"</pre>
<p>or for the US you would have :</p>
<pre>export RCLOUD_DATACENTER=US
export UK_RCLOUD_USER="MY_USERNAME"
export UK_RCLOUD_KEY="MY_API_KEY"
export UK_RCLOUD_AURL="https://auth.api.rackspacecloud.com/v1.0"</pre>
<p>source the ~/.bashrc or relog into your account to have those accounts set-up you can test it to see if that works by going to :</p>
<pre>~/cloudservers-api-demo/python</pre>
<p>and launch the command :</p>
<pre>./list-servers.py</pre>
<p>to test if this is working properly (it should list your servers for your DATACENTER)</p>
<p>you are now basically ready to mass update firewall on all servers.</p>
<p>Let&#8217;s say you have two web servers named web1 and web2 and two db servers named db1 and db2 and you would like to allow the 80 port on the web servers and 3306 port on the db servers.</p>
<p>You would have to go to this directory :</p>
<pre>~/cloudservers-api-demo/firewall/</pre>
<p>and first execute this command to see the help/usages :</p>
<pre>./fw-control.py --help</pre>
<p>so let&#8217;s say to enable the firewall on all the web and db server first you can do :</p>
<pre>./fw-control.py -s "web db" enable</pre>
<p>it will connect and enable the firewall on all the servers which match the name web and db.</p>
<p>now let&#8217;s say we want to enable port 80 on the web :</p>
<pre>./fw-control.py -s "web" allow port 80</pre>
<p>if you log into the servers you can check with</p>
<pre>iptables -L -n</pre>
<p>that it it has been enabled properly.</p>
<p>This is simple enough for you to modify the script to your liking to make it more modular for your specific environement.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.chmouel.com/2011/05/05/mass-editing-firewall-on-rackspace-cloud/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Howto shutdown your Cloud Server and not getting billed for it.</title>
		<link>http://blog.chmouel.com/2011/04/07/howto-shutdown-your-cloud-server-and-not-getting-billed-for-it/</link>
		<comments>http://blog.chmouel.com/2011/04/07/howto-shutdown-your-cloud-server-and-not-getting-billed-for-it/#comments</comments>
		<pubDate>Thu, 07 Apr 2011 09:36:28 +0000</pubDate>
		<dc:creator>chmouel</dc:creator>
				<category><![CDATA[Cloud]]></category>
		<category><![CDATA[Rackspace]]></category>

		<guid isPermaLink="false">http://blog.chmouel.com/?p=441</guid>
		<description><![CDATA[Currently in Rackspace-Cloud when you are shutting-down your Cloud Servers you are still paying for it. The reason is that when the Cloud Server is shut-down your CloudServer is still sitting on the hyper-visor and still use resources on the &#8230; <a href="http://blog.chmouel.com/2011/04/07/howto-shutdown-your-cloud-server-and-not-getting-billed-for-it/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Currently in Rackspace-Cloud when you are shutting-down your Cloud Servers you are still paying for it.</p>
<p>The reason is that when the Cloud Server is shut-down your CloudServer is still sitting on the hyper-visor and still use resources on the Cloud and then get you billed for it.</p>
<p>There is a way to get around it by having the CloudServer stored as an image into CloudFiles.</p>
<p>The caveat with this solution is that every-time you are creating a server out of the stored image you are getting a new IP and in certain cases you would need to make a change in your application with the new IP.</p>
<p>If you only use domain names instead of IP in your application you are not dependent of the IP change, to update the domain with the new IP after creating the VM you can either :</p>
<p>  &#8211; Have a dynamic DNS or &#8216;Cloud DNS&#8217; updated just after you created your server out of the image.</p>
<p>  &#8211; Have a script going into your server and update the IP directly in /etc/hosts.</p>
<p>In programming words this is the steps you would do. I am using the python-nova binding which allow you to connect to RackSpace Cloud.</p>
<p>At first I am going to create an object which we are going to authenticate</p>

<div class="wp_codebox"><table><tr id="p44132"><td class="code" id="p441code32"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> novaclient
cx = novaclient.<span style="color: black;">OpenStack</span><span style="color: black;">&#40;</span>USERNAME,
                            API_KEY<span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>or for the UK :</p>

<div class="wp_codebox"><table><tr id="p44133"><td class="code" id="p441code33"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> novaclient
cx = novaclient.<span style="color: black;">OpenStack</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;USERNAME&quot;</span>,
                            <span style="color: #483d8b;">&quot;API_KEY&quot;</span>,
                            <span style="color: #483d8b;">'https://lon.auth.api.rackspacecloud.com/v1.0'</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>cx is going to be the object from where we can do things on it. Let&#8217;s first find the server server that we want, assuming your server is called test you would get the server like this :</p>

<div class="wp_codebox"><table><tr id="p44134"><td class="code" id="p441code34"><pre class="python" style="font-family:monospace;">server = cx.<span style="color: black;">servers</span>.<span style="color: black;">find</span><span style="color: black;">&#40;</span>name=<span style="color: #483d8b;">'test'</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>The variable &#8216;server&#8217; contain our server &#8216;object&#8217; and we can get its ID out of it :</p>

<div class="wp_codebox"><table><tr id="p44135"><td class="code" id="p441code35"><pre class="python" style="font-family:monospace;">server_id = server.<span style="color: #008000;">id</span></pre></td></tr></table></div>

<p>We got the function cx.images.create to create an image from a server which accept as first argument the image name and the second the server id we just got. this would start the creation of the image :</p>

<div class="wp_codebox"><table><tr id="p44136"><td class="code" id="p441code36"><pre class="python" style="font-family:monospace;">cx.<span style="color: black;">images</span>.<span style="color: black;">create</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;backup_server&quot;</span>, server_id<span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>The server has started to get backed-up into your Cloud Files account, you can see it directly into the &#8220;My Server Images&#8221; tab of Hosting => Cloud Servers section :</p>
<p><a href="http://blog.chmouel.com/wp-content/uploads/2011/04/Backup.png"><img src="http://blog.chmouel.com/wp-content/uploads/2011/04/Backup-1024x31.png" alt="" title="Backup" width="640" height="19" class="aligncenter size-large wp-image-442" /></a></p>
<p>You can now delete the server since it&#8217;s &#8216;backuped&#8217; into cloud files ;</p>

<div class="wp_codebox"><table><tr id="p44137"><td class="code" id="p441code37"><pre class="python" style="font-family:monospace;">server.<span style="color: black;">delete</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>At this time you are not billed for your Cloud Servers anymore and only for the storage usage in Cloud Files.</p>
<p>When you want to restore the image as a server, you would first get the id of your image  :</p>

<div class="wp_codebox"><table><tr id="p44138"><td class="code" id="p441code38"><pre class="python" style="font-family:monospace;">image = cx.<span style="color: black;">images</span>.<span style="color: black;">find</span><span style="color: black;">&#40;</span>name=<span style="color: #483d8b;">'backup-test'</span><span style="color: black;">&#41;</span>
image_id = image.<span style="color: #008000;">id</span></pre></td></tr></table></div>

<p>and create the server out of this image :</p>

<div class="wp_codebox"><table><tr id="p44139"><td class="code" id="p441code39"><pre class="python" style="font-family:monospace;"> CNX.<span style="color: black;">servers</span>.<span style="color: black;">create</span><span style="color: black;">&#40;</span>image=image_id,
                            flavor=<span style="color: #ff4500;">1</span>,
                            name=<span style="color: #483d8b;">&quot;test&quot;</span>,
                            <span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>The flavor argument is the type of image you want, 1 the minimal 256M flavor. The full list is :</p>

<div class="wp_codebox"><table><tr id="p44140"><td class="code" id="p441code40"><pre class="python" style="font-family:monospace;">&nbsp;
In <span style="color: black;">&#91;</span><span style="color: #ff4500;">14</span><span style="color: black;">&#93;</span>: <span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> cx.<span style="color: black;">flavors</span>.<span style="color: #008000;">list</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
   ....:     <span style="color: #ff7700;font-weight:bold;">print</span> x.<span style="color: #008000;">id</span>, <span style="color: #483d8b;">'-'</span>, x.<span style="color: black;">name</span>
   ....:     
   ....:     
<span style="color: #ff4500;">1</span> - <span style="color: #ff4500;">256</span> server
<span style="color: #ff4500;">2</span> - <span style="color: #ff4500;">512</span> server
<span style="color: #ff4500;">3</span> - 1GB server
<span style="color: #ff4500;">4</span> - 2GB server
<span style="color: #ff4500;">5</span> - 4GB server
<span style="color: #ff4500;">6</span> - 8GB server
<span style="color: #ff4500;">7</span> - 15.5GB server</pre></td></tr></table></div>

<p>When the server has created it should be exactly the same as what you have before created in image. You can now run a script using SSH with SSH keys to log into servers and do adjustment with the new IP.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.chmouel.com/2011/04/07/howto-shutdown-your-cloud-server-and-not-getting-billed-for-it/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Uploading to Rackspace Cloud Files via FTP</title>
		<link>http://blog.chmouel.com/2011/04/06/uploading-to-rackspace-cloud-files-via-ftp/</link>
		<comments>http://blog.chmouel.com/2011/04/06/uploading-to-rackspace-cloud-files-via-ftp/#comments</comments>
		<pubDate>Wed, 06 Apr 2011 13:05:44 +0000</pubDate>
		<dc:creator>chmouel</dc:creator>
				<category><![CDATA[Cloud]]></category>
		<category><![CDATA[Rackspace]]></category>

		<guid isPermaLink="false">http://blog.chmouel.com/?p=436</guid>
		<description><![CDATA[Sometime ago I wrote a FTP proxy to RackSpace Cloud Files which expose Rackspace Cloud Files as a FTP server acting as a proxy. Thanks to the OpenSource community a user on github took it and add support OpenStack and &#8230; <a href="http://blog.chmouel.com/2011/04/06/uploading-to-rackspace-cloud-files-via-ftp/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.chmouel.com/2009/10/29/ftp-server-for-cloud-files/">Sometime ago</a> I wrote a <a href="https://github.com/chmouel/ftp-cloudfs/">FTP proxy</a> to RackSpace Cloud Files which expose Rackspace Cloud Files as a FTP server acting as a proxy. </p>
<p>Thanks to the OpenSource community a user on github took it and add support <a href="http://www.openstack.org/">OpenStack</a> and all the latest features available in Cloud Files.</p>
<p>It is now pretty robust and works pretty well via nautilus even with the <a href="http://docs.openstack.org/openstack-object-storage/developer/content/ch03s02.html#d5e527">pseudo hierarchical folder feature</a>. The fun part here is that it allow you to effectively have a Cloud Drive where you can easily store your files/backup from your Linux desktop via nautilus built-in ftp support.</p>
<p>I have made a video that show how it works :</p>
<p><iframe src="http://player.vimeo.com/video/22024058" width="400" height="300" frameborder="0"></iframe>
<p><a href="http://vimeo.com/22024058">Upload to the Cloud via FTP</a> from <a href="http://vimeo.com/user4559588">Chmouel Boudjnah</a> on <a href="http://vimeo.com">Vimeo</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.chmouel.com/2011/04/06/uploading-to-rackspace-cloud-files-via-ftp/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

