<HTML>
<HEAD><!-- Template generated by Exclaimer Mail Disclaimers on 11:27:16 Tuesday, 29 April 2014 -->
<STYLE type=text/css>P.ae431132-9d17-4a38-b6b5-634369783623 {
MARGIN: 0cm 0cm 0pt
}
LI.ae431132-9d17-4a38-b6b5-634369783623 {
MARGIN: 0cm 0cm 0pt
}
DIV.ae431132-9d17-4a38-b6b5-634369783623 {
MARGIN: 0cm 0cm 0pt
}
TABLE.ae431132-9d17-4a38-b6b5-634369783623Table {
MARGIN: 0cm 0cm 0pt
}
DIV.Section1 {
page: Section1
}
</STYLE>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</HEAD>
<BODY style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; color: rgb(0, 0, 0); font-size: 14px; font-family: Calibri, sans-serif;">
<P class=ae431132-9d17-4a38-b6b5-634369783623>
<div>
<div>Before I answer these questions, I want to clear up some ambiguity around our use of terminology:</div>
<div><br />
</div>
<div><i>Schemas</i></div>
<div>JSON schemas are documents written in JSON according to an RFC specification. All they do is define how an API resource (such as a server) is structured: what type they are (string/array/object), what properties they have, what type these properties are,
how many properties, etc. etc. In other words, it acts as a blueprint. Every time we are given arbitrary data that is SUPPOSED to represent one of these resources, we use schemas to validate them. If validation succeeds we know everything's well and that the
data truly represents the resource.</div>
<div><br />
</div>
<div><i>Schema-like DSL</i></div>
<div>Where the confusion is coming from, I think, his how then do we define all the other business logic - like API operations, iterators, exceptions, etc. Well, we'd use a DSL which is extremely <i>similar to</i> how JSON schemas work, but is not strictly
identical. We'd use a similar kind of syntax, but the actual aims of the document would not be the same. JSON schemas define resource models, our Schema-like DSL would define end-user Commands (that directly maps to an API operation). Google's Discovery API,
for example, does this: it defines both data schemas AND API operations in one JSON document.</div>
<div><br />
</div>
<div><br />
</div>
<div><b>How would methods and commands work?</b></div>
<div><br />
</div>
<div>In php-opencloud we do a very similar thing to what the Python folks are doing and what you're suggesting: performing commands in a class hierarchy. So in order to retrieve an object, I need to call the grandparent first (service), then the parent class
(container), then finally the child (object):</div>
<div><br />
</div>
<div>$container = $service->getContainer('foo');</div>
<div>$object = $container->getObject('bar.txt');</div>
<div><br />
</div>
<div>What I'm proposing is slightly different. Instead of having all these commands dependent on a hierarchy, I was thinking about executing everything against the base service class:</div>
<div><br />
</div>
<div>$object = $service->getObject([</div>
<div><span class="Apple-tab-span" style="white-space: pre;"></span>'container' => 'foo',</div>
<div><span class="Apple-tab-span" style="white-space: pre;"></span>'name' => 'bar.txt'</div>
<div>]);</div>
<div><br />
</div>
<div>There are 2 advantages to the above option: with a flat hierarchy you don't need to remember which class another resource belongs to (since everything is called against the service), and the other advantage is that you keep HTTP calls to a minimum and
thereby increase performance and speed. With the first solution you execute a GET for the container and then a GET for the object; with the second solution you only execute one request. If you consider the implications for a full application, it would make
a big difference.</div>
<div><br />
</div>
<div>Now, this is just an idea - nothing set in stone. JSON schema doesn't enforce any particular solution - we can achieve either of the above with it. </div>
<div><br />
</div>
<div>What does everyone think? Is there a real advantage to using a class hierarchy like $service->getContainer('foo')->getObject('bar') instead of a flat hierarchy?</div>
<div><br />
</div>
<div><br />
</div>
<div><b>How does a user discover commands?</b></div>
<div><br />
</div>
<div>I think the ability for an end-user to easily understand our public API is incredibly important. If we used a flat hierarchy, each command would be called as if in a registry. Our schema-like DSL would act as this registry: each command is explicitly defined,
containing all the details the end-user needs to fulfill a particular operation. Because each command is defined in this way (like documentation), we could easily add in a feature for a user to "query" what a command expects of them:</div>
<div><br />
</div>
<div>echo $service->queryCommand('getObject');</div>
<div><br />
</div>
<div>The Swift service would know that "getObject" is a registered command. So it would return all information it has (about expected parameters to the user). I already thought about this in my prototype from a while back:</div>
<div><br />
</div>
<div><a href="http://php-opencloud.readthedocs.org/en/latest/intro.html#executing-commands">http://php-opencloud.readthedocs.org/en/latest/intro.html#executing-commands</a></div>
<div><br />
</div>
<div><br />
</div>
<div><b>How does a user actually execute a command?</b></div>
<div><br />
</div>
<div>The user can EXECUTE commands in two ways:</div>
<div><br />
</div>
<div>// Method 1: calling the registry:</div>
<div>$command = $service->getCommand('GetObject', [</div>
<div><span class="Apple-tab-span" style="white-space: pre;"></span>'name' => 'bar.txt', 'container' => 'foo'</div>
<div>]);</div>
<div>$response = $command->execute();</div>
<div><br />
</div>
<div>// Method 2 using magic methods:</div>
<div>$response = $service->getObject([</div>
<div><span class="Apple-tab-span" style="white-space: pre;"></span>'name' => 'bar.txt', 'container' => 'foo'</div>
<div>]);</div>
<div><br />
</div>
<div>This is how Guzzle does it: it encapsulates HTTP operations as "commands". The end-user then calls a Command and receives the HTTP response.</div>
<div><br />
</div>
<div><br />
</div>
<div><b>Popularity with other SDKs</b></div>
<div><br />
</div>
<div>Other client libraries are definitely using json-schemas, such as the Glance and Marconi official clients. The below link shows how many official OpenStack projects/client libraries currently use schemas:</div>
<div><br />
</div>
<div><a href="https://wiki.openstack.org/wiki/OpenStack-SDK-PHP/Schema-Adoption">https://wiki.openstack.org/wiki/OpenStack-SDK-PHP/Schema-Adoption</a></div>
<div><br />
</div>
<div>There is also active support for incorporating schemas into other client libraries, like Keystone.</div>
<div><br />
</div>
<div><br />
</div>
<div><b>Debugging commands</b></div>
<div><b><br />
</b></div>
<div>The schemas only handle how data is populated into the models. What you're referring to is Commands (i.e. what the end-user interacts with). These commands are defined in a schema-like DSL (in either JSON or PHP). The link I gave you yesterday (both to
my sample and the Google Discovery API) put these Command definitions in the same file as the model Schemas - but there's no reason they should be conflated. Guzzle, for example, defines commands using PHP arrays.</div>
<div><br />
</div>
<div>A simple thread of execution could work like this:</div>
<div><br />
</div>
<div>1. User calls the command (either by calling the registry's "getCommand" method, or using a magic method):</div>
<div><br />
</div>
<div>$response = $service->listServers();</div>
<div><br />
</div>
<div>2. The service detects a magic method is being used. It realizes "listServers" is the Command's name, and checks the command registry to see whether this name exists. As I've previously said, this registry could be in JSON (in a similar syntax to Google's
Discovery API) or PHP (like Guzzle's DSL, etc.)</div>
<div><br />
</div>
<div>3. If the command exists, it checks to see whether the user passed in all the correct parameters. This is where it validates user input. If a required param is missing, an exception is thrown.</div>
<div><br />
</div>
<div>4. Now it serializes everything into a Request, depending on how the command is defined. It looks at the URL path, the verb, any headers to include, what the request body needs to look like, etc. All this is defined in the schema/DSL mentioned in step
2.</div>
<div><br />
</div>
<div>5. The request is sent and a response is procured through cURL. If it receives back an unsuccessful header (4xx or 5xx), it looks to see if the bad status is expected. If, for example, we've set a custom exception to be thrown for a 404, it will do so.
Otherwise, it parses the response.</div>
<div><br />
</div>
<div>6. Here is where JSON schemas enter the picture. Schemas are responsible for validating remote data structures. It validates the response body to see whether the structure within it matches/validates against the schema blueprint. If it does, a Model is
returned to the user. If a particular property fails, it's left out. </div>
<div><br />
</div>
<div><br />
</div>
<div><b>Can we convert Tempest files?</b></div>
<div><br />
</div>
<div>We wouldn't need to - schemas are written in a consistent, interoperable way. </div>
<div><br />
</div>
<div><br />
</div>
<div>Jamie</div>
</div>
<div><br />
</div>
<span id="OLK_SRC_BODY_SECTION">
<div style="font-family:Calibri; font-size:11pt; text-align:left; color:black; BORDER-BOTTOM: medium none; BORDER-LEFT: medium none; PADDING-BOTTOM: 0in; PADDING-LEFT: 0in; PADDING-RIGHT: 0in; BORDER-TOP: #b5c4df 1pt solid; BORDER-RIGHT: medium none; PADDING-TOP: 3pt">
<span style=font-weight:bold>From: </span>Matthew Farina <<a href="mailto:matt@mattfarina.com">matt@mattfarina.com</a>><br />
<span style=font-weight:bold>Date: </span>Tuesday, April 29, 2014 at 3:28 AM<br />
<span style=font-weight:bold>To: </span>Jamie Hannaford <<a href="mailto:jamie.hannaford@rackspace.com">jamie.hannaford@rackspace.com</a>><br />
<span style=font-weight:bold>Cc: </span>"OpenStack Development Mailing List (not for usage questions)" <<a href="mailto:openstack-dev@lists.openstack.org">openstack-dev@lists.openstack.org</a>>, "<a href="mailto:sam.choi@hp.com">sam.choi@hp.com</a>" <<a href="mailto:sam.choi@hp.com">sam.choi@hp.com</a>><br />
<span style=font-weight:bold>Subject: </span>Re: [openstack-sdk-php] discussion: json schema to define apis<br />
</div>
<div><br />
</div>
<div>
<div>
<div dir="ltr">While reading this it struck me that we should prioritize the experience of end-user, that is application developers, over the experience of those working on the SDK. I don't think we'd ever directly talked about this so I wanted to take a moment
and state it.
<div class="gmail_extra"><br />
</div>
<div class="gmail_extra">What I put in below isn't my full set of questions but I think it's enough for now.<br />
<br />
<div class="gmail_quote">On Mon, Apr 28, 2014 at 11:34 AM, Jamie Hannaford <span dir="ltr">
<<a href="mailto:jamie.hannaford@rackspace.com" target="_blank">jamie.hannaford@rackspace.com</a>></span> wrote:<br />
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<div style=font-size:14px;font-family:Calibri,sans-serif;word-wrap:break-word>
<p></p>
<div>
<div>Thanks Matt for bringing up these questions - I think having this kind of discussion is essential for such a big idea. It also helps me clarify my own thinking towards this issue. </div>
<div><br />
</div>
<div>Before I answer, I want to point out that I'm not staunchly for or against any particular idea. I do think that schemas offer a lot of advantages over writing user-land code, but I'm more than willing to abandon the proposal if we all determine there's
a stronger and more compelling alternative.</div>
<div><br />
</div>
<div><b>1. Why use schemas instead of userland code?</b></div>
<div><br />
</div>
<div>I've put my answer to this question here: <a href="https://wiki.openstack.org/wiki/OpenStack-SDK-PHP/JSON-schema" target="_blank">https://wiki.openstack.org/wiki/OpenStack-SDK-PHP/JSON-schema</a></div>
</div>
</div>
</blockquote>
<div><br />
</div>
<div>Can we look at this from the experience an end user would have? In the Python SDK they are working on an ORM style system. It's sorta similar to the system currently in the PHP SDK. For example you could do something like this in Python,</div>
<div><br />
</div>
<div> o = Container.get_by_id('foo').get_object('bar/baz.awesome')<br />
</div>
<div><br />
</div>
<div>I would imagine something similar in PHP like,</div>
<div><br />
</div>
<div> $o = $objectStore->getContainer('foo')->getObject('bar/baz.awesome');</div>
<div><br />
</div>
<div>I don't think you can do this using the json schema code I've seen so far. Can you touch on the experience for developers who are using the library? For example, the coding style or ability to know what they have access to? I was just thinking of how magic
methods using a schema aren't going to work for tools that do autocompletion.</div>
<div><br />
</div>
<div>I'm curious about blueprints for the schema support. Things on the mailing list are great. I'm curious about plans and what's in the blueprints. Do you have any info on that?</div>
<div><br />
</div>
<div>If the other SDKs aren't interested in using json schema, wouldn't that be a lack of consistency?</div>
<div> </div>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<div style=font-size:14px;font-family:Calibri,sans-serif;word-wrap:break-word>
<div><br />
</div>
<div><b>2. How will debugging work?</b></div>
<div><br />
</div>
<div>I'll highlight two conceivable issues which might need debugging. The first issue is the API rejecting a request for whatever reason (i.e. a proxy modifying headers); the second issue is when a data structure returned from the API fails to validate against
a particular schema file.</div>
<div><br />
</div>
<div><i>Issue 1: Malformed requests</i></div>
<div>There are two reasons why a request would fail: if an end-user stocks it with bad data, or if something in the middle deforms it. A very easy solution to the first problem is using schemas to perform basic parameter checking before a request is serialized.
If we know, for example, that the API is expecting a particular value - or a particular header - the schema is in charge of making that happen. Performing basic validation catches most errors - and debugging is very easy due to the exception thrown. If you're
ever in doubt, you just refer to the schema to see<i> </i>what was serialized into a request in the same way you do for a concrete class method. </div>
<div><br />
</div>
<div>If something in the middle deforms the request, the API will naturally reject it. When it comes to debugging this issue, all you need to do is wrap your original code in a try/catch block and use Guzzle's BadResponseException to return the API's response.
You can easily see the type of failure through the HTTP status code, and the exact reason why the request failed. So it doesn't matter where the failure happens - all that matters is that there's a way to catch and spit out the API's response and the originating
request. </div>
<div><br />
</div>
</div>
</blockquote>
<div><br />
</div>
<div>First, this assumes Guzzle. Since we aren't tightly coupled to Guzzle we can't always assume that. But, for practical purposes we can assume it for now.</div>
<div><br />
</div>
<div>I was curious how things would work in PHP, such as the stack trace. For magic methods you'll have a call to the magic method and to __call() where the logic actually sits. In a debugger you'll be able to step through this just fine.</div>
<div><br />
</div>
<div>One thing that may be more difficult is that knowing how the json schema system works to debug and understand what's going on. How the schemas work and how something gets translated into a method. Walking through a few methods that are extended would be
less logic to understand in the process.</div>
<div><br />
</div>
<div>I'm curious how the debugging experience would be for an end user who doesn't know the json schema system but is using the library. Out of curiosity I might try to find some time to sit down with some PHP developers and see how they handle the debugging
experience.</div>
<div> </div>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<div style=font-size:14px;font-family:Calibri,sans-serif;word-wrap:break-word>
<div>
<div></div>
<div><i>Issue 2: Incorrect API data </i></div>
<div>Say we've defined that a Server has two properties: a name (which is a string) and metadata (which is an object). If the API returns a name as an array, that obviously fails validation. When the schema code goes to validate the API data, it will raise
validation error when it comes to validate that "name" property. How you consequently use this validation error them is completely up to you: you could output it to STDOUT, you could save it to a local log on the filesystem, you could buffer it temporarily
in memory.</div>
<div><br />
</div>
<div>Any API data that does not validate successfully against a schema should not be presented to the end-user. So if a "created_date" property is returned, that isn't defined in our schema, it should not be populated in the resulting model. The model returned
to the end-user would be a simple object that implements \ArrayAccess, meaning that it can be accessed like a simple array.<span style=font-family:arial;font-size:small> </span></div>
</div>
</div>
</blockquote>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<div style=font-size:14px;font-family:Calibri,sans-serif;word-wrap:break-word>
<div>
<div><br />
</div>
<div><b>3. Where would JSON schemas come from?</b></div>
<div><b><br />
</b></div>
<div>It depends on each OpenStack service. Glance and Marconi (soon) offer schemas directly through the API - so they are directly responsible for maintaining this - we'd just consume it. We could probably cache a local version to minimize requests.</div>
<div><br />
</div>
<div>For services that do not offer schemas yet, we'd have to use local schema files. There's a project called Tempest which does integration tests for OpenStack clusters, and it uses schema files. So there might be a possibility of using their files in the
future. If this is not possible, we'd write them ourselves. It took me 1-2 days to write the entire Nova API. Once a schema file has been fully tested and signed off as 100% operational, it can be frozen as a set version.</div>
</div>
</div>
</blockquote>
<div><br />
</div>
<div>Can we convert the schema files from Tempest into something we can use?</div>
<div> </div>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<div style=font-size:14px;font-family:Calibri,sans-serif;word-wrap:break-word>
<div>
<div><br />
</div>
<div><b>4. What would the workflow look like?</b></div>
<div><b><br />
</b></div>
<div>I don't really understand what you mean: can you elaborate?</div>
</div>
</div>
</blockquote>
<div><br />
</div>
<div>For example, when would validation happen? Is that for testing or runtime for use in an application?</div>
<div> </div>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<div style=font-size:14px;font-family:Calibri,sans-serif;word-wrap:break-word>
<div>
<div><br />
</div>
<div><b>5. How does schema files handle business logic?</b></div>
<div><br />
</div>
<div>That's a really great question. I've written a brief write-up here: <a href="https://wiki.openstack.org/wiki/OpenStack-SDK-PHP/JSON-schema-business-logic#So_how_can_it_be_done_well.3F" target="_blank">https://wiki.openstack.org/wiki/OpenStack-SDK-PHP/JSON-schema-business-logic</a></div>
<div><br />
</div>
</div>
</div>
</blockquote>
<div><br />
</div>
<div>I think what you're proposing is that the methods map to API calls. There isn't any logic in these objects that isn't an API call.</div>
<div> </div>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<div style=font-size:14px;font-family:Calibri,sans-serif;word-wrap:break-word>
<div>
<div></div>
<div><br />
</div>
<div>Jamie</div>
</div>
<div><br />
</div>
<span>
<div class="">
<div style="border-width:1pt medium medium;border-style:solid none none;padding:3pt 0in 0in;text-align:left;font-size:11pt;font-family:Calibri;border-top-color:rgb(181,196,223)">
<span style=font-weight:bold>From: </span>Matthew Farina <<a href="mailto:matt@mattfarina.com" target="_blank">matt@mattfarina.com</a>><br />
<span style=font-weight:bold>Date: </span>Thursday, April 24, 2014 at 5:42 PM<br />
<span style=font-weight:bold>To: </span>Jamie Hannaford <<a href="mailto:jamie.hannaford@rackspace.com" target="_blank">jamie.hannaford@rackspace.com</a>>, "OpenStack Development Mailing List (not for usage questions)" <<a href="mailto:openstack-dev@lists.openstack.org" target="_blank">openstack-dev@lists.openstack.org</a>><br />
<span style=font-weight:bold>Cc: </span>"<a href="mailto:sam.choi@hp.com" target="_blank">sam.choi@hp.com</a>" <<a href="mailto:sam.choi@hp.com" target="_blank">sam.choi@hp.com</a>><br />
<span style=font-weight:bold>Subject: </span>[openstack-sdk-php] discussion: json schema to define apis<br />
</div>
<div><br />
</div>
</div>
<div>
<div class="h5">
<div>
<div>
<div>Jamie (and whom ever else wants to jump in),</div>
<div><br />
</div>
<div>It's been proposed to use json schema to describe the API calls rather</div>
<div>than code. The operations to perform and what they do would be</div>
<div>described rather than coded and then some code would use the schema to</div>
<div>know how to act.</div>
<div><br />
</div>
<div>Others are already doing this. For example, the AWS SDK for PHP. Take</div>
<div>their S3 structure as an example</div>
<div><a href="https://github.com/aws/aws-sdk-php/blob/master/src/Aws/S3/Resources/s3-2006-03-01.php" target="_blank">https://github.com/aws/aws-sdk-php/blob/master/src/Aws/S3/Resources/s3-2006-03-01.php</a>.</div>
<div>The ability to do this goes beyond this one example. It just appears</div>
<div>to be something similar to what we're considering.</div>
<div><br />
</div>
<div>Given this in the scope of PHP I've got a number of questions. Several</div>
<div>of these I've compiled while discussing this with others so they don't</div>
<div>represent my point of view. Rather, they are just a list of</div>
<div>outstanding questions. Since this is a different method for handling</div>
<div>the API calls from the other SDKs being built the concept should be</div>
<div>really vetted.</div>
<div><br />
</div>
<div>Here are the questions:</div>
<div><br />
</div>
<div>1. Why use json schema rather than other reuse methods? I've discussed</div>
<div>the use of json schemas with others and those working on the other</div>
<div>languages have not been interested in json schema at the moment. Why</div>
<div>do it differently given the context?</div>
<div><br />
</div>
<div>Note, it might be worth looking at the python SDK which is doing</div>
<div>things differently. If I understand it right they are moving aware</div>
<div>from using managers and resources all together.</div>
<div><br />
</div>
<div>2. How will debugging work in practice? For example, a call is made</div>
<div>from behind a proxy. The proxy alters the HTTP headers so the request</div>
<div>fails and an exception is thrown. The schema and endpoint are valid.</div>
<div>It's something in the middle that changed things. Walking through the</div>
<div>code goes through magic methods to handle the schema. How would</div>
<div>debugging that work to understand what's happening compared to what</div>
<div>was expected.</div>
<div><br />
</div>
<div>3. Where would the json schemas for services come from and who would</div>
<div>manage them?</div>
<div><br />
</div>
<div>4. What would the workflow look like for working with the schemas at</div>
<div>both execution time for everyday use and for testing?</div>
<div><br />
</div>
<div>5. How would logic happen? Sometimes a request to an API is more than</div>
<div>just a request and response. For example, calling to something in</div>
<div>object storage where the object does not exist. The transport layer</div>
<div>will throw an exception (this goes all the way down to Guzzle throwing</div>
<div>one) that needs to be caught and managed. How should cases with some</div>
<div>logic like this be handled and easy to understand?</div>
<div><br />
</div>
<div>Thanks for looking into this. The topic has really sparked my</div>
<div>interest. I for one am really curious about the practicalities of</div>
<div>using json schema and the developer experience around it.</div>
<div><br />
</div>
<div>- Matt Farina</div>
<div><br />
</div>
</div>
</div>
</div>
</div>
</span>
<p></p>
<p> </p>
<p></p>
<table border="0" cellpadding="0" width="504">
<tbody>
<tr>
<td style=width:270px><span style=font-family:Verdana;font-size:small>Jamie Hannaford</span>
<div>
<div class="h5"><br />
<span style=font-family:Verdana;font-size:x-small>Software Developer III - CH</span></div>
</div>
</td>
<td style=width:281px><img alt="experience Fanatical Support" align="right" width="159" height="17" /></td>
</tr>
<tr>
<td colspan="2"><img alt="LINE" width="504" height="4" /></td>
</tr>
<tr>
<td><span style=font-family:Calibri>
<table>
<tbody>
<tr>
<td><span style=font-family:Verdana;font-size:x-small>Tel: </span></td>
<td><span style=font-family:Verdana;font-size:x-small><a href="tel:%2B41434303908" value="+41434303908" target="_blank">+41434303908</a></span></td>
</tr>
<tr>
<td><span style=font-family:Verdana;font-size:x-small>Mob: </span></td>
<td><span style=font-family:Verdana;font-size:x-small><a href="tel:%2B41791009767" value="+41791009767" target="_blank">+41791009767</a></span></td>
</tr>
</tbody>
</table>
</span></td>
<td><img alt="Rackspace" width="280" height="60" /></td>
</tr>
<tr>
<td colspan="2"><img width="504" height="3" /></td>
</tr>
</tbody>
</table>
<p></p>
<div>
<div class="h5">
<p> </p>
<p></p>
<span style=font-size:11px>Rackspace International GmbH a company registered in the Canton of Zurich, Switzerland (company identification number CH-020.4.047.077-1) whose registered office is at Pfingstweidstrasse 60, 8005 Zurich, Switzerland. Rackspace International
GmbH privacy policy can be viewed at <a href="http://www.rackspace.co.uk/legal/swiss-privacy-policy" target="_blank">
www.rackspace.co.uk/legal/swiss-privacy-policy</a><br />
-<br />
Rackspace Hosting Australia PTY LTD a company registered in the state of Victoria, Australia (company registered number ACN 153 275 524) whose registered office is at Suite 3, Level 7, 210 George Street, Sydney, NSW 2000, Australia. Rackspace Hosting Australia
PTY LTD privacy policy can be viewed at <a href="http://www.rackspace.com.au/company/legal-privacy-statement.php" target="_blank">
www.rackspace.com.au/company/legal-privacy-statement.php</a><br />
-<span style=font-size:11px></span><br />
Rackspace US, Inc, 5000 Walzem Road, San Antonio, Texas 78218, United States of America</span><br />
<span style=font-size:11px>Rackspace US, Inc privacy policy can be viewed at <a href="http://www.rackspace.com/information/legal/privacystatement" target="_blank">
www.rackspace.com/information/legal/privacystatement</a></span><br />
<span style=font-size:11px>-</span><br />
<span style=font-size:11px>Rackspace Limited is a company registered in England & Wales (company registered number 03897010) whose registered office is at 5 Millington Road, Hyde Park Hayes, Middlesex UB3 4AZ.</span><br />
<span style=font-size:11px>Rackspace Limited privacy policy can be viewed at <a href="http://www.rackspace.co.uk/legal/privacy-policy" target="_blank">
www.rackspace.co.uk/legal/privacy-policy</a></span><br />
<span style=font-size:11px>-</span><br />
<span style=font-size:11px>Rackspace Benelux B.V. is a company registered in the Netherlands (company KvK nummer 34276327) whose registered office is at Teleportboulevard 110, 1043 EJ Amsterdam.</span><br />
<span style=font-size:11px>Rackspace Benelux B.V privacy policy can be viewed at
<a href="http://www.rackspace.nl/juridisch/privacy-policy" target="_blank">www.rackspace.nl/juridisch/privacy-policy</a></span><br />
<span style=font-size:11px>-</span><br />
<span style=font-size:11px>Rackspace Asia Limited is a company registered in Hong Kong (Company no: 1211294) whose registered office is at 9/F, Cambridge House, Taikoo Place, 979 King's Road, Quarry Bay, Hong Kong.</span><br />
<span style=font-size:11px>Rackspace Asia Limited privacy policy can be viewed at
<a href="http://www.rackspace.com.hk/company/legal-privacy-statement.php" target="_blank">
www.rackspace.com.hk/company/legal-privacy-statement.php</a></span><br />
<span style=font-size:11px>-</span><br />
<span style=font-size:11px>This e-mail message (including any attachments or embedded documents) is intended for the exclusive and confidential use of the individual or entity to which this message is addressed, and unless otherwise expressly indicated, is
confidential and privileged information of Rackspace. Any dissemination, distribution or copying of the enclosed material is prohibited. If you receive this transmission in error, please notify us immediately by e-mail at
<a href="mailto:abuse@rackspace.com" target="_blank">abuse@rackspace.com</a> and delete the original message. Your cooperation is appreciated.</span></div>
</div>
</div>
</blockquote>
</div>
<br />
</div>
</div>
</div>
</div>
</span>
</P>
<P class=ae431132-9d17-4a38-b6b5-634369783623> </P>
<P class=ae431132-9d17-4a38-b6b5-634369783623>
<TABLE border=0 cellPadding=0 width=504>
<TBODY>
<TR>
<TD style="WIDTH: 270px" class=LEFT_ALIGNED><span style='font-family:Verdana; font-size:small; '>Jamie Hannaford</span><BR /><span style='font-family:Verdana; font-size:x-small; '>Software Developer III - CH</span></TD>
<TD style="WIDTH: 281px"><IMG alt="experience Fanatical Support" align=right src="cid:image9ae567.JPG@f1c154a8.4f9db45d" width=159 height=17 /></TD></TR>
<TR class=LEFT_ALIGNED>
<TD colSpan=2><IMG alt=LINE src="cid:image6ffd37.JPG@e3464b94.43a1a8da" width=504 height=4 /></TD></TR>
<TR>
<TD class=CONTACTINFO><span style='font-family:Calibri; '><table class=ae431132-9d17-4a38-b6b5-634369783623Table><tr><td><span style='font-family:Verdana; font-size:x-small; '>Tel: </span></td><td><span style='font-family:Verdana; font-size:x-small; '>+41434303908</span></td></tr><tr><td><span style='font-family:Verdana; font-size:x-small; '>Mob: </span></td><td><span style='font-family:Verdana; font-size:x-small; '>+41791009767</span></td></tr></table></span></TD>
<TD class=RIGHT_ALIGNED><IMG alt=Rackspace src="cid:image8b57d5.JPG@4acd30d2.4c95bfdc" width=280 height=60 /></TD></TR>
<TR class=LEFT_ALIGNED>
<TD class=CONTACTINFO colSpan=2><IMG src="cid:image1270b0.JPG@7709bc3e.4d97da86" width=504 height=3 /></TD></TR></TBODY></TABLE></P>
<P class=ae431132-9d17-4a38-b6b5-634369783623> </P>
<P class=ae431132-9d17-4a38-b6b5-634369783623></P><span style="font-size: 11px;">Rackspace International GmbH a company registered in the Canton of Zurich, Switzerland (company identification number CH-020.4.047.077-1) whose registered office is at Pfingstweidstrasse 60, 8005 Zurich, Switzerland. Rackspace International GmbH privacy policy can be viewed at www.rackspace.co.uk/legal/swiss-privacy-policy<br>-<br>Rackspace Hosting Australia PTY LTD a company registered in the state of Victoria, Australia (company registered number ACN 153 275 524) whose registered office is at Suite 3, Level 7, 210 George Street, Sydney, NSW 2000, Australia. Rackspace Hosting Australia PTY LTD privacy policy can be viewed at www.rackspace.com.au/company/legal-privacy-statement.php<br>-<span style="font-size: 11px;"></span><br>Rackspace US, Inc, 5000 Walzem Road, San Antonio, Texas 78218, United States of America</span><br><span style="font-size: 11px;">Rackspace US, Inc privacy policy can be viewed at www.rackspace.com/information/legal/privacystatement</span><br><span style="font-size: 11px;">-</span><br><span style="font-size: 11px;">Rackspace Limited is a company registered in England & Wales (company registered number 03897010) whose registered office is at 5 Millington Road, Hyde Park Hayes, Middlesex UB3 4AZ.</span><br><span style="font-size: 11px;">Rackspace Limited privacy policy can be viewed at www.rackspace.co.uk/legal/privacy-policy</span><br><span style="font-size: 11px;">-</span><br><span style="font-size: 11px;">Rackspace Benelux B.V. is a company registered in the Netherlands (company KvK nummer 34276327) whose registered office is at Teleportboulevard 110, 1043 EJ Amsterdam.</span><br><span style="font-size: 11px;">Rackspace Benelux B.V privacy policy can be viewed at www.rackspace.nl/juridisch/privacy-policy</span><br><span style="font-size: 11px;">-</span><br><span style="font-size: 11px;">Rackspace Asia Limited is a company registered in Hong Kong (Company no: 1211294) whose registered office is at 9/F, Cambridge House, Taikoo Place, 979 King's Road, Quarry Bay, Hong Kong.</span><br><span style="font-size: 11px;">Rackspace Asia Limited privacy policy can be viewed at www.rackspace.com.hk/company/legal-privacy-statement.php</span><br><span style="font-size: 11px;">-</span><br><span style="font-size: 11px;">This e-mail message (including any attachments or embedded documents) is intended for the exclusive and confidential use of the individual or entity to which this message is addressed, and unless otherwise expressly indicated, is confidential and privileged information of Rackspace. Any dissemination, distribution or copying of the enclosed material is prohibited. If you receive this transmission in error, please notify us immediately by e-mail at abuse@rackspace.com and delete the original message. Your cooperation is appreciated.</span></BODY>
</HTML>